Xqt has submitted this change. ( 
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1341907?usp=email )

Change subject: Add BasePage.flagged_state for FlaggedRevs info
......................................................................

Add BasePage.flagged_state for FlaggedRevs info

Expose the prop=flagged dictionary (stable_revid, level,
pending_since, etc.) via FlaggedRevsMixin.flagged_state and
BasePage.flagged_state, returning None when unavailable.
Refactor stable_revid to reuse the new helper.

Bug: T410893
Change-Id: I7e77aa91d97937427cfc178d82e77114efd8dc09
---
M pywikibot/page/_basepage.py
M pywikibot/site/_extensions.py
M tests/flaggedrevs_tests.py
3 files changed, 151 insertions(+), 6 deletions(-)

Approvals:
  Xqt: Verified; Looks good to me, approved
  jenkins-bot: Verified




diff --git a/pywikibot/page/_basepage.py b/pywikibot/page/_basepage.py
index cf2bec4..62cfc3a 100644
--- a/pywikibot/page/_basepage.py
+++ b/pywikibot/page/_basepage.py
@@ -572,6 +572,7 @@
         .. version-added:: 11.7
         .. seealso:
            - :attr:`stable_revision`
+           - :attr:`flagged_state`
            - :attr:`latest_revision_id`

         :raises UnknownExtensionError: FlaggedRevs not available
@@ -583,6 +584,8 @@
         """Remove the cached latest stable revision id set for this Page."""
         with suppress(AttributeError):
             del self._stable_revision_id
+        with suppress(AttributeError):
+            del self._flagged_state

     @property
     def stable_revision(self) -> pywikibot.page.Revision | None:
@@ -623,6 +626,34 @@

         return None

+    @property
+    @cached
+    def flagged_state(self) -> dict | None:
+        """Return FlaggedRevs info for this page, if any.
+
+        Returns the ``flagged`` property dict from the API (for example
+        ``stable_revid``, ``level``, ``level_text``, ``pending_since``)
+        or ``None`` if the page has no flagged data.
+
+        .. version-added:: 11.8
+        .. seealso::
+           - :attr:`stable_revision_id`
+           - :attr:`stable_revision`
+           - :meth:`APISite.flagged_state
+             <pywikibot.site._extensions.FlaggedRevsMixin.flagged_state>`
+
+        :raises UnknownExtensionError: FlaggedRevs not available
+        """
+        return self.site.flagged_state(self)
+
+    @flagged_state.deleter
+    def flagged_state(self) -> None:
+        """Remove the cached flagged state set for this Page."""
+        with suppress(AttributeError):
+            del self._flagged_state
+        with suppress(AttributeError):
+            del self._stable_revision_id
+
     def _check_revision(self, revid: int, refresh: bool) -> None:
         """Check whether the *revid* is valid and belongs to this page."""
         try:
@@ -678,6 +709,7 @@

         # The stable revision may have changed.
         del self.stable_revision_id
+        del self.flagged_state

     def unreview(
         self,
@@ -724,6 +756,7 @@

         # The stable revision may have changed.
         del self.stable_revision_id
+        del self.flagged_state

     @property
     def text(self) -> str:
diff --git a/pywikibot/site/_extensions.py b/pywikibot/site/_extensions.py
index c7c9a95..3a2cdec 100644
--- a/pywikibot/site/_extensions.py
+++ b/pywikibot/site/_extensions.py
@@ -478,12 +478,22 @@
     """

     @need_extension('FlaggedRevs')
-    def stable_revid(self: BaseSiteProtocol,
-                     page: pywikibot.Page) -> int | None:
-        """Return the stable (reviewed) revision id for a page, if any.
+    def flagged_state(self: BaseSiteProtocol,
+                      page: pywikibot.Page) -> dict | None:
+        """Return the FlaggedRevs info dict for a page, if any.
+
+        Uses ``prop=flagged`` and returns the ``flagged`` object from the
+        API (keys such as ``stable_revid``, ``level``, ``level_text``,
+        ``pending_since``), or ``None`` if the page has no flagged data.
+
+        .. version-added:: 11.8
+        .. seealso::
+           - :meth:`stable_revid`
+           - :attr:`BasePage.flagged_state
+             <page.BasePage.flagged_state>`

         :param page: The page to inspect.
-        :return: The stable revision id or None if not available.
+        :return: Flagged info dict or None if not available.
         :raises UnknownExtensionError: FlaggedRevs not available
         """
         req = self.simple_request(
@@ -498,7 +508,22 @@
         if not pages:
             return None

-        return pages[0].get('flagged', {}).get('stable_revid')
+        flagged = pages[0].get('flagged')
+        return flagged or None
+
+    @need_extension('FlaggedRevs')
+    def stable_revid(self: BaseSiteProtocol,
+                     page: pywikibot.Page) -> int | None:
+        """Return the stable (reviewed) revision id for a page, if any.
+
+        :param page: The page to inspect.
+        :return: The stable revision id or None if not available.
+        :raises UnknownExtensionError: FlaggedRevs not available
+        """
+        flagged = self.flagged_state(page)
+        if not flagged:
+            return None
+        return flagged.get('stable_revid')

     @need_extension('FlaggedRevs')
     @need_right('review')
diff --git a/tests/flaggedrevs_tests.py b/tests/flaggedrevs_tests.py
index 3d62467..6837da8 100644
--- a/tests/flaggedrevs_tests.py
+++ b/tests/flaggedrevs_tests.py
@@ -3,7 +3,7 @@
 #
 # Distributed under the terms of the MIT license.
 #
-"""Unit tests for Page.stable_revision."""
+"""Unit tests for Page.stable_revision and flagged_state."""
 from __future__ import annotations

 import unittest
@@ -145,6 +145,93 @@
             self.assertEqual(result.revid, 999)


+class TestPageFlaggedState(TestCase):
+
+    """Test Page.flagged_state with full mocking."""
+
+    family = 'wikipedia'
+    code = 'fi'
+    dry = True
+
+    def setUp(self) -> None:
+        """Test setup."""
+        super().setUp()
+        self.page = pywikibot.Page(self.site, 'TestPage')
+        self.page.exists = MagicMock(return_value=True)
+
+    def _mock_response(self, data: dict | list[dict]) -> dict:
+        """Helper: build API response for action=query&prop=flagged."""
+        return {
+            'query': {
+                'pages': data if isinstance(data, list) else [data]
+            }
+        }
+
+    @patch('pywikibot.site._apisite.APISite.has_extension')
+    def test_flagged_state_extension_disabled(self, mock_has_ext):
+        """FlaggedRevs not enabled → UnknownExtensionError."""
+        mock_has_ext.return_value = False
+        with self.assertRaisesRegex(
+            UnknownExtensionError,
+            'Method "flagged_state" is not implemented without the extension '
+            'FlaggedRevs'
+        ):
+            self.page.flagged_state
+
+    @patch('pywikibot.site._apisite.APISite.simple_request')
+    @patch('pywikibot.site._apisite.APISite.has_extension')
+    def test_flagged_state_none(self, mock_has_ext, mock_req):
+        """API returns no flagged key → None."""
+        mock_has_ext.return_value = True
+        mock_req.return_value.submit.return_value = self._mock_response(
+            {'pageid': 1, 'ns': 0, 'title': 'TestPage'}
+        )
+        self.assertIsNone(self.page.flagged_state)
+
+    @patch('pywikibot.site._apisite.APISite.simple_request')
+    @patch('pywikibot.site._apisite.APISite.has_extension')
+    def test_flagged_state_success(self, mock_has_ext, mock_req):
+        """Valid flagged dict is returned."""
+        mock_has_ext.return_value = True
+        flagged = {
+            'stable_revid': 12345,
+            'level': 2,
+            'level_text': 'stable',
+            'pending_since': '2025-01-01T00:00:00Z',
+        }
+        mock_req.return_value.submit.return_value = self._mock_response(
+            {
+                'pageid': 1,
+                'title': 'TestPage',
+                'flagged': flagged,
+            }
+        )
+        result = self.page.flagged_state
+        self.assertEqual(result, flagged)
+        self.assertEqual(result['stable_revid'], 12345)
+        self.assertEqual(result['level'], 2)
+        # Cached: second access does not call the API again
+        mock_req.reset_mock()
+        self.assertEqual(self.page.flagged_state, flagged)
+        mock_req.assert_not_called()
+
+    @patch('pywikibot.site._apisite.APISite.simple_request')
+    @patch('pywikibot.site._apisite.APISite.has_extension')
+    def test_site_flagged_state(self, mock_has_ext, mock_req):
+        """APISite.flagged_state returns the flagged dict."""
+        mock_has_ext.return_value = True
+        flagged = {'stable_revid': 42, 'level': 1}
+        mock_req.return_value.submit.return_value = self._mock_response(
+            {
+                'pageid': 1,
+                'title': 'TestPage',
+                'flagged': flagged,
+            }
+        )
+        self.assertEqual(self.site.flagged_state(self.page), flagged)
+        self.assertEqual(self.site.stable_revid(self.page), 42)
+
+
 class TestFlaggedRevsReview(PatchingTestCase):

     """Test site.review() with flagged revisions."""

--
To view, visit 
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1341907?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.wikimedia.org/r/settings?usp=email

Gerrit-MessageType: merged
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Change-Id: I7e77aa91d97937427cfc178d82e77114efd8dc09
Gerrit-Change-Number: 1341907
Gerrit-PatchSet: 2
Gerrit-Owner: Chuiimuii_ofc <[email protected]>
Gerrit-Reviewer: Matěj Suchánek <[email protected]>
Gerrit-Reviewer: Xqt <[email protected]>
Gerrit-Reviewer: jenkins-bot
Gerrit-CC: Mahveotm <[email protected]>
_______________________________________________
Pywikibot-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to