jenkins-bot has submitted this change. (
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1172853?usp=email )
Change subject: IMPR: Add `expiry` parameter to Page.watch() and Site.watch()
......................................................................
IMPR: Add `expiry` parameter to Page.watch() and Site.watch()
This commit enhances the Page.watch() method by adding support for
the`expiry` parameter, allowing temporary watchlist entries using
relative or absolute expiry times. The parameter is passed through
to APISite.watch().
Additionally, positional arguments for these methods are deprecated
starting with version 10.4.0. Calls must now use keyword arguments only.
A warning is issued if `expiry` is passed together with `unwatch=True`,
since the MediaWiki API ignores `expiry` in that case.
Includes:
- Updated docstring with version and usage notes.
- deprecate positional arguments
- Type annotations and Literal support for expiry.
- Tests for watch/unwatch behavior and expiry.
- Warning check for ignored expiry with unwatch.
Bug: T330839
Change-Id: Ic81919eb5c5d866da6a6ca5cddec1bd5a07d01dd
---
M pywikibot/page/_basepage.py
M pywikibot/site/_apisite.py
M tests/page_tests.py
3 files changed, 77 insertions(+), 10 deletions(-)
Approvals:
jenkins-bot: Verified
Xqt: Looks good to me, approved
diff --git a/pywikibot/page/_basepage.py b/pywikibot/page/_basepage.py
index 39bc1a0..6e3adfb 100644
--- a/pywikibot/page/_basepage.py
+++ b/pywikibot/page/_basepage.py
@@ -1458,13 +1458,40 @@
force=force, asynchronous=asynchronous, callback=callback,
**kwargs)
- def watch(self, unwatch: bool = False) -> bool:
- """Add or remove this page to/from bot account's watchlist.
+ @deprecate_positionals(since='10.4.0')
+ def watch(
+ self, *,
+ unwatch: bool = False,
+ expiry: Timestamp | str | Literal[
+ 'infinite', 'indefinite', 'infinity', 'never'] | None = None
+ ) -> bool:
+ """Add or remove this page from the bot account's watchlist.
- :param unwatch: True to unwatch, False (default) to watch.
+ .. versionchanged:: 10.4.0
+ Added the *expiry* parameter to specify watch expiry time.
+ Positional parameters are deprecated; all parameters must be
+ passed as keyword arguments.
+
+ .. seealso::
+ - :meth:`Site.watch()<pywikibot.site._apisite.APISite.watch>`
+ - :meth:`Site.watched_pages()
+ <pywikibot.site._generators.GeneratorsMixin.watched_pages>`
+ - :api:`Watch`
+
+ :param unwatch: If True, the page will be from the watchlist.
+ :param expiry: Expiry timestamp to apply to the watch. Passing
+ None or omitting this parameter leaves any existing expiry
+ unchanged. Expiry values may be relative (e.g. ``5 months``
+ or ``2 weeks``) or absolute (e.g. ``2014-09-18T12:34:56Z``).
+ For no expiry, use ``infinite``, ``indefinite``, ``infinity``
+ or `never`. For absolute timestamps the :class:`Timestamp`
+ class can be used.
:return: True if successful, False otherwise.
+ :raises APIError: badexpiry: Invalid value for expiry parameter
+ :raises KeyError: 'watch' isn't in API response
+ :raises TypeError: unexpected keyword argument
"""
- return self.site.watch(self, unwatch)
+ return self.site.watch(self, unwatch=unwatch, expiry=expiry)
def clear_cache(self) -> None:
"""Clear the cached attributes of the page."""
diff --git a/pywikibot/site/_apisite.py b/pywikibot/site/_apisite.py
index 9ee6fb4..29ca580 100644
--- a/pywikibot/site/_apisite.py
+++ b/pywikibot/site/_apisite.py
@@ -14,7 +14,7 @@
from collections import OrderedDict, defaultdict
from contextlib import suppress
from textwrap import fill
-from typing import TYPE_CHECKING, Any, NamedTuple, TypeVar
+from typing import TYPE_CHECKING, Any, Literal, NamedTuple, TypeVar
from warnings import warn
import pywikibot
@@ -74,6 +74,7 @@
MediaWikiVersion,
cached,
deprecate_arg,
+ deprecate_positionals,
deprecated,
issue_deprecation_warning,
merge_unique_dicts,
@@ -2917,27 +2918,56 @@
return req.submit()
@need_right('editmywatchlist')
+ @deprecate_positionals(since='10.4.0')
def watch(
self,
pages: BasePage | str | list[BasePage | str],
- unwatch: bool = False
+ *,
+ unwatch: bool = False,
+ expiry: pywikibot.Timestamp | str | Literal[
+ 'infinite', 'indefinite', 'infinity', 'never'] | None = None
) -> bool:
"""Add or remove pages from watchlist.
- .. seealso:: :api:`Watch`
+ .. versionchanged:: 10.4.0
+ Added the *expiry* parameter to specify watch expiry time.
+ Passing *unwatch* as a positional parameter is deprecated;
+ it must be passed as keyword argument.
+
+ .. seealso::
+ - :api:`Watch`
+ - :meth:`BasePage.watch`
+ - :meth:`Site.watched_pages()
+ <pywikibot.site._generators.GeneratorsMixin.watched_pages>`
:param pages: A single page or a sequence of pages.
:param unwatch: If True, remove pages from watchlist;
if False add them (default).
+ :param expiry: Expiry timestamp to apply to the watch. Passing
+ None or omitting this parameter leaves any existing expiry
+ unchanged. Expiry values may be relative (e.g. ``5 months``
+ or ``2 weeks``) or absolute (e.g. ``2014-09-18T12:34:56Z``).
+ For no expiry, use ``infinite``, ``indefinite``, ``infinity``
+ or `never`. For absolute timestamps the :class:`Timestamp`
+ class can be used.
:return: True if API returned expected response; False otherwise
+ :raises APIError: badexpiry: Invalid value for expiry parameter
:raises KeyError: 'watch' isn't in API response
+ :raises TypeError: unexpected keyword argument
"""
parameters = {
'action': 'watch',
'titles': pages,
'token': self.tokens['watch'],
'unwatch': unwatch,
+ 'expiry': expiry or None,
}
+ if not unwatch:
+ parameters['expiry'] = expiry or None
+ elif expiry:
+ msg = (f'\nexpiry parameter ({expiry!r}) is ignored when '
+ f"unwatch=True.\nPlease omit 'expiry' when unwatching.")
+ warn(msg, category=UserWarning, stacklevel=2)
req = self.simple_request(**parameters)
results = req.submit()
unwatch_s = 'unwatched' if unwatch else 'watched'
diff --git a/tests/page_tests.py b/tests/page_tests.py
index 5c00543..813fb3b 100755
--- a/tests/page_tests.py
+++ b/tests/page_tests.py
@@ -9,6 +9,7 @@
import pickle
import re
+import time
from contextlib import suppress
from datetime import timedelta
from unittest import mock
@@ -1082,13 +1083,22 @@
# Note: this test uses the userpage, so that it is unwatched and
# therefore is not listed by script_tests test_watchlist_simulate.
+
userpage = self.get_userpage()
+ # watched_pages parameters
+ wp_params = {'force': True, 'with_talkpage': False}
rv = userpage.watch()
- self.assertIsInstance(rv, bool)
self.assertTrue(rv)
- rv = userpage.watch(unwatch=True)
- self.assertIsInstance(rv, bool)
+ self.assertIn(userpage, userpage.site.watched_pages(**wp_params))
+ with self.assertWarnsRegex(UserWarning,
+ r"expiry parameter \('.+'\) is ignored"):
+ rv = userpage.watch(unwatch=True, expiry='indefinite')
self.assertTrue(rv)
+ rv = userpage.watch(expiry='5 seconds')
+ self.assertTrue(rv)
+ self.assertIn(userpage, userpage.site.watched_pages(**wp_params))
+ time.sleep(10)
+ self.assertNotIn(userpage, userpage.site.watched_pages(**wp_params))
class TestPageDelete(TestCase):
--
To view, visit
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1172853?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: Ic81919eb5c5d866da6a6ca5cddec1bd5a07d01dd
Gerrit-Change-Number: 1172853
Gerrit-PatchSet: 4
Gerrit-Owner: Xqt <[email protected]>
Gerrit-Reviewer: BinĂ¡ris <[email protected]>
Gerrit-Reviewer: Xqt <[email protected]>
Gerrit-Reviewer: jenkins-bot
_______________________________________________
Pywikibot-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]