Xqt has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1350308?usp=email )
Change subject: user: Rename force parameter to refresh
......................................................................
user: Rename force parameter to refresh
In User methods force only drops the cached user properties and reloads
them; it does not override any restriction. Rename it to refresh and keep
force working through @deprecated_args for the deprecation period.
save(force=...) and botMayEdit(force=...) keep the old name, where the
parameter really does override something.
Bug: T433225
Change-Id: I757e0fc188f4700714623d112102f3926fdf1999
---
M ROADMAP.rst
M pywikibot/page/_user.py
M tests/user_tests.py
3 files changed, 132 insertions(+), 46 deletions(-)
Approvals:
Xqt: Verified; Looks good to me, approved
diff --git a/ROADMAP.rst b/ROADMAP.rst
index 020fef9..5706226 100644
--- a/ROADMAP.rst
+++ b/ROADMAP.rst
@@ -1,6 +1,8 @@
Release 11.9
============
+* The *force* parameter of :class:`pywikibot.User` methods was renamed to
+ *refresh* (:phab:`T433225`)
* Suggest installing all requirements for missing dependencies with
:mod:`pwb<pywikibot.scripts.wrapper>` wrapper.
* Various performance, stability, and code quality improvements.
@@ -107,6 +109,8 @@
Pending removal in Pywikibot 14
-------------------------------
+* 11.9.0: The *force* parameter of :class:`pywikibot.User` methods was renamed to
+ *refresh*. The old parameter name will be removed. (:phab:`T433225`)
* 11.8.0: Public *reason* and *comment* parameters used for page-action and
upload summaries were renamed to *summary*. The old parameter names will
be removed. (:phab:`T62442`)
diff --git a/pywikibot/page/_user.py b/pywikibot/page/_user.py
index 5956b8a..d37c930 100644
--- a/pywikibot/page/_user.py
+++ b/pywikibot/page/_user.py
@@ -22,7 +22,7 @@
from pywikibot.page._page import Page
from pywikibot.page._revision import Revision
from pywikibot.time import Timestamp
-from pywikibot.tools import is_ip_address, is_ip_network
+from pywikibot.tools import deprecated_args, is_ip_address, is_ip_network
from pywikibot.tools.collections import DataRecord
@@ -101,7 +101,8 @@
return '#' + self.title(with_ns=False)
return self.title(with_ns=False)
- def isRegistered(self, force: bool = False) -> bool: # noqa: N802
+ @deprecated_args(force='refresh') # since 11.9.0
+ def isRegistered(self, refresh: bool = False) -> bool: # noqa: N802
"""Determine if the user is registered on the site.
It is possible to have a page named ``User:xyz`` and not have a
@@ -117,13 +118,16 @@
- :meth:`is_temporary`
- :meth:`is_named`
- :param force: If True, forces reloading the data from API
+ .. version-changed:: 11.9
+ The *force* parameter was renamed to *refresh*.
+
+ :param refresh: If True, forces reloading the data from API
:return: True if the user is either a named (regular) user or a
temporary account.
"""
# T135828: the registration timestamp may be None but the key exists
return (not self.isAnonymous()
- and 'registration' in self.getprops(force))
+ and 'registration' in self.getprops(refresh))
def isAnonymous(self) -> bool: # noqa: N802
"""Determine if the user is editing as an IP address.
@@ -148,7 +152,8 @@
"""
return is_ip_network(self.username)
- def is_named(self, *, force: bool = False) -> bool:
+ @deprecated_args(force='refresh') # since 11.9.0
+ def is_named(self, *, refresh: bool = False) -> bool:
"""Determine if the user is a regular named account.
A named account is neither an IP nor a temporary account.
@@ -159,9 +164,12 @@
- :meth:`isAnonymous`
- :meth:`is_temporary`
- :param force: If True, forces reloading the data from API
+ .. version-changed:: 11.9
+ The *force* parameter was renamed to *refresh*.
+
+ :param refresh: If True, forces reloading the data from API
"""
- return self.isRegistered(force) and not self.is_temporary()
+ return self.isRegistered(refresh) and not self.is_temporary()
def is_temporary(self) -> bool:
"""Determine if the user is a temporary account.
@@ -175,7 +183,8 @@
"""
return 'temp' in self.groups()
- def temp_expired(self, force: bool = False) -> bool | None:
+ @deprecated_args(force='refresh') # since 11.9.0
+ def temp_expired(self, refresh: bool = False) -> bool | None:
"""Indicates whether the temporary account has expired or not.
If account isn't temporary, None is returned.
@@ -183,16 +192,20 @@
.. version-added:: 11.4
.. seealso:: :meth:`is_temporary`
- :param force: If True, forces reloading the data from API
+ .. version-changed:: 11.9
+ The *force* parameter was renamed to *refresh*.
+
+ :param refresh: If True, forces reloading the data from API
"""
if not self.is_temporary():
return None
- return 'tempexpired' in self.getprops(force, ['tempexpired'])
+ return 'tempexpired' in self.getprops(refresh, ['tempexpired'])
+ @deprecated_args(force='refresh') # since 11.9.0
def getprops(
self,
- force: bool = False,
+ refresh: bool = False,
extra_props: Iterable[str] = ()
) -> dict[str, Any]:
"""Return user properties.
@@ -201,8 +214,10 @@
detect range blocks
.. version-changed:: 11.4
Added the *extra_props* parameter.
+ .. version-changed:: 11.9
+ The *force* parameter was renamed to *refresh*.
- :param force: If True, forces reloading the data from API
+ :param refresh: If True, forces reloading the data from API
:param extra_props: Additional user properties to request.
"""
if not hasattr(self, '_additional_props'):
@@ -214,7 +229,7 @@
new_props = bool(missing)
self._additional_props.update(missing)
- if (force or new_props) and hasattr(self, '_userprops'):
+ if (refresh or new_props) and hasattr(self, '_userprops'):
self._userprops: dict[str, Any]
del self._userprops
@@ -230,28 +245,37 @@
return self._userprops
+ @deprecated_args(force='refresh') # since 11.9.0
def registration(self,
- force: bool = False) -> pywikibot.Timestamp | None:
+ refresh: bool = False) -> pywikibot.Timestamp | None:
"""Fetch registration date for this user.
- :param force: If True, forces reloading the data from API
+ .. version-changed:: 11.9
+ The *force* parameter was renamed to *refresh*.
+
+ :param refresh: If True, forces reloading the data from API
"""
if not self.isAnonymous():
- reg = self.getprops(force).get('registration')
+ reg = self.getprops(refresh).get('registration')
if reg:
return pywikibot.Timestamp.fromISOformat(reg)
return None
- def editCount(self, force: bool = False) -> int: # noqa: N802
+ @deprecated_args(force='refresh') # since 11.9.0
+ def editCount(self, refresh: bool = False) -> int: # noqa: N802
"""Return edit count for a registered user.
Always returns 0 for 'anonymous' users.
- :param force: If True, forces reloading the data from API
- """
- return self.getprops(force).get('editcount', 0)
+ .. version-changed:: 11.9
+ The *force* parameter was renamed to *refresh*.
- def is_blocked(self, force: bool = False) -> bool:
+ :param refresh: If True, forces reloading the data from API
+ """
+ return self.getprops(refresh).get('editcount', 0)
+
+ @deprecated_args(force='refresh') # since 11.9.0
+ def is_blocked(self, refresh: bool = False) -> bool:
"""Determine whether the user is currently blocked.
.. seealso::
@@ -262,12 +286,15 @@
renamed from :meth:`isBlocked` method
.. version-changed:: 9.0
can also detect range blocks.
+ .. version-changed:: 11.9
+ The *force* parameter was renamed to *refresh*.
- :param force: If True, forces reloading the data from API
+ :param refresh: If True, forces reloading the data from API
"""
- return 'blockedby' in self.getprops(force)
+ return 'blockedby' in self.getprops(refresh)
- def is_partial_blocked(self, *, force: bool = False) -> bool:
+ @deprecated_args(force='refresh') # since 11.9.0
+ def is_partial_blocked(self, *, refresh: bool = False) -> bool:
"""Return True if this user is partially blocked, False otherwise.
.. seealso::
@@ -276,12 +303,17 @@
<pywikibot.site._apisite.APISite.is_partial_blocked>`
.. version-added:: 11.0
+ .. version-changed:: 11.9
+ The *force* parameter was renamed to *refresh*.
- :param force: If True, forces reloading the data from API
+ :param refresh: If True, forces reloading the data from API
"""
- return 'blockpartial' in self.getprops(force)
+ return 'blockpartial' in self.getprops(refresh)
- def get_block_info(self, *, force: bool = False) -> dict[str, Any] | None:
+ @deprecated_args(force='refresh') # since 11.9.0
+ def get_block_info(
+ self, *, refresh: bool = False
+ ) -> dict[str, Any] | None:
"""Return a dictionary of block information if the user is blocked.
Returns None if the user is not blocked.
@@ -298,23 +330,28 @@
- :meth:`is_partial_blocked`
.. version-added:: 11.0
+ .. version-changed:: 11.9
+ The *force* parameter was renamed to *refresh*.
- :param force: If True, forces reloading the data from API
+ :param refresh: If True, forces reloading the data from API
"""
- props = self.getprops(force)
+ props = self.getprops(refresh)
if 'blockid' not in props:
return None
return {k: v for k, v in props.items() if k.startswith('block')}
- def is_locked(self, force: bool = False) -> bool:
+ @deprecated_args(force='refresh') # since 11.9.0
+ def is_locked(self, refresh: bool = False) -> bool:
"""Determine whether the user is currently locked globally.
.. version-added:: 7.0
+ .. version-changed:: 11.9
+ The *force* parameter was renamed to *refresh*.
- :param force: If True, forces reloading the data from API
+ :param refresh: If True, forces reloading the data from API
"""
- return self.site.is_locked(self.username, force)
+ return self.site.is_locked(self.username, refresh)
def is_globally_blocked(self) -> bool:
"""Return whether an active global block matches this user.
@@ -339,40 +376,56 @@
"""
return self.site.is_globally_blocked(self.username)
- def isEmailable(self, force: bool = False) -> bool: # noqa: N802
+ @deprecated_args(force='refresh') # since 11.9.0
+ def isEmailable(self, refresh: bool = False) -> bool: # noqa: N802
"""Determine whether emails may be sent to this user through MediaWiki.
- :param force: If True, forces reloading the data from API
- """
- return not self.isAnonymous() and 'emailable' in self.getprops(force)
+ .. version-changed:: 11.9
+ The *force* parameter was renamed to *refresh*.
- def groups(self, force: bool = False) -> list:
+ :param refresh: If True, forces reloading the data from API
+ """
+ return not self.isAnonymous() and 'emailable' in self.getprops(refresh)
+
+ @deprecated_args(force='refresh') # since 11.9.0
+ def groups(self, refresh: bool = False) -> list:
"""Return a list of groups to which this user belongs.
The list of groups may be empty.
- :param force: If True, forces reloading the data from API
+ .. version-changed:: 11.9
+ The *force* parameter was renamed to *refresh*.
+
+ :param refresh: If True, forces reloading the data from API
:return: Groups property
"""
- return self.getprops(force).get('groups', [])
+ return self.getprops(refresh).get('groups', [])
- def gender(self, force: bool = False) -> str:
+ @deprecated_args(force='refresh') # since 11.9.0
+ def gender(self, refresh: bool = False) -> str:
"""Return the gender of the user.
- :param force: If True, forces reloading the data from API
+ .. version-changed:: 11.9
+ The *force* parameter was renamed to *refresh*.
+
+ :param refresh: If True, forces reloading the data from API
:return: Return 'male', 'female', or 'unknown'
"""
if self.isAnonymous():
return 'unknown'
- return self.getprops(force).get('gender', 'unknown')
+ return self.getprops(refresh).get('gender', 'unknown')
- def rights(self, force: bool = False) -> list:
+ @deprecated_args(force='refresh') # since 11.9.0
+ def rights(self, refresh: bool = False) -> list:
"""Return user rights.
- :param force: If True, forces reloading the data from API
+ .. version-changed:: 11.9
+ The *force* parameter was renamed to *refresh*.
+
+ :param refresh: If True, forces reloading the data from API
:return: Return user rights
"""
- return self.getprops(force).get('rights', [])
+ return self.getprops(refresh).get('rights', [])
def getUserPage(self, subpage: str = '') -> Page: # noqa: N802
"""Return a Page object relative to this user's main page.
diff --git a/tests/user_tests.py b/tests/user_tests.py
index 16d7366..11f52a7 100755
--- a/tests/user_tests.py
+++ b/tests/user_tests.py
@@ -18,7 +18,7 @@
AutoblockUserError,
UnknownExtensionError,
)
-from tests.aspects import DefaultSiteTestCase, TestCase
+from tests.aspects import DefaultSiteTestCase, DeprecationTestCase, TestCase
class TestUserClass(TestCase):
@@ -355,6 +355,35 @@
self.assertEqual(event.user(), user.username)
+class TestUserRefreshParameter(DeprecationTestCase):
+
+ """Test the rename of the *force* parameter to *refresh*."""
+
+ family = 'wikipedia'
+ code = 'de'
+ dry = True
+
+ def test_refresh(self) -> None:
+ """Test that refresh is forwarded without a deprecation."""
+ user = User(self.site, 'Example')
+ with patch.object(
+ User, 'getprops', return_value={'editcount': 7}
+ ) as getprops:
+ self.assertEqual(user.editCount(refresh=True), 7)
+ getprops.assert_called_once_with(True)
+ self.assertNoDeprecation()
+
+ def test_force_is_deprecated(self) -> None:
+ """Test that force still works but warns."""
+ user = User(self.site, 'Example')
+ with patch.object(
+ User, 'getprops', return_value={'editcount': 7}
+ ) as getprops:
+ self.assertEqual(user.editCount(force=True), 7)
+ getprops.assert_called_once_with(True)
+ self.assertOneDeprecation()
+
+
if __name__ == '__main__':
with suppress(SystemExit):
unittest.main()
--
To view, visit https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1350308?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: I757e0fc188f4700714623d112102f3926fdf1999
Gerrit-Change-Number: 1350308
Gerrit-PatchSet: 2
Gerrit-Owner: Varshitha <varshithakolupuri100(a)gmail.com>
Gerrit-Reviewer: Xqt <info(a)gno.de>
Gerrit-Reviewer: jenkins-bot
jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1348495?usp=email )
Change subject: docs: update changelog link to the rendered docs instead of HISTORY.rst
......................................................................
docs: update changelog link to the rendered docs instead of HISTORY.rst
The stable documentation is more up to date than the stable branch
and includes rendered links to Phabricator tasks and methods.
Change-Id: If833e9e3b893ae22bd4caf25d23dc9b53bdbcca2
---
M README.rst
1 file changed, 1 insertion(+), 1 deletion(-)
Approvals:
jenkins-bot: Verified
Mahveotm: Looks good to me, approved
diff --git a/README.rst b/README.rst
index 81ae5fc..c885b8a 100644
--- a/README.rst
+++ b/README.rst
@@ -143,7 +143,7 @@
Release history
===============
-See https://github.com/wikimedia/pywikibot/blob/stable/HISTORY.rst
+See https://doc.wikimedia.org/pywikibot/stable/changelog.html
Contributing
============
--
To view, visit https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1348495?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: If833e9e3b893ae22bd4caf25d23dc9b53bdbcca2
Gerrit-Change-Number: 1348495
Gerrit-PatchSet: 2
Gerrit-Owner: Xqt <info(a)gno.de>
Gerrit-Reviewer: Mahveotm <mahveotm(a)gmail.com>
Gerrit-Reviewer: jenkins-bot