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]