jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1023474?usp=email )
Change subject: [tests] Show user rights if UserRightsError is raised during tests ......................................................................
[tests] Show user rights if UserRightsError is raised during tests
Bug: T363190 Change-Id: Ic46e899e0fdc07ee34e1b2cd855e2fdd51835ead --- M pywikibot/site/_decorators.py M tests/site_decorators_tests.py 2 files changed, 48 insertions(+), 46 deletions(-)
Approvals: Xqt: Looks good to me, approved jenkins-bot: Verified
diff --git a/pywikibot/site/_decorators.py b/pywikibot/site/_decorators.py index 3656e4e..6539355 100644 --- a/pywikibot/site/_decorators.py +++ b/pywikibot/site/_decorators.py @@ -1,15 +1,23 @@ """Decorators used by site models.""" # -# (C) Pywikibot team, 2008-2023 +# (C) Pywikibot team, 2008-2024 # # Distributed under the terms of the MIT license. # from __future__ import annotations
+import os +from textwrap import fill + from pywikibot.exceptions import UnknownExtensionError, UserRightsError from pywikibot.tools import MediaWikiVersion, manage_wrapping
+CLOSED_WIKI_MSG = ( + 'Site {site} has been closed. Only steward can perform requested action.' +) + + def must_be(group: str | None = None): """Decorator to require a certain user status when method is called.
@@ -24,15 +32,11 @@ grp = kwargs.pop('as_group', group) if self.obsolete: if not self.has_group('steward'): - raise UserRightsError( - 'Site {} has been closed. Only steward ' - 'can perform requested action.' - .format(self.sitename)) + raise UserRightsError(CLOSED_WIKI_MSG.format(site=self))
elif not self.has_group(grp): - raise UserRightsError('User "{}" is not part of the required ' - 'user group "{}"' - .format(self.user(), grp)) + raise UserRightsError(f'User "{self.user()}" is not part of ' + f'the required user group "{grp}"')
return fn(self, *args, **kwargs)
@@ -53,8 +57,8 @@ def callee(self, *args, **kwargs): if not self.has_extension(extension): raise UnknownExtensionError( - 'Method "{}" is not implemented without the extension {}' - .format(fn.__name__, extension)) + f'Method "{fn.__name__}" is not implemented without the ' + f'extension {extension}') return fn(self, *args, **kwargs)
manage_wrapping(callee, fn) @@ -74,15 +78,18 @@ def callee(self, *args, **kwargs): if self.obsolete: if not self.has_group('steward'): - raise UserRightsError( - 'Site {} has been closed. Only stewards ' - 'can perform the requested action.' - .format(self.sitename)) + raise UserRightsError(CLOSED_WIKI_MSG.format(site=self))
elif right is not None and not self.has_right(right): - raise UserRightsError('User "{}" does not have required ' - 'user right "{}"' - .format(self.user(), right)) + if os.environ.get('PYWIKIBOT_TEST_RUNNING', '0') == '1': + rights = ' but:\n' + fill( + str(sorted(self.userinfo['rights'])), + width=76, break_on_hyphens=False) + else: + rights = '.' + raise UserRightsError( + f'User "{self.user()}" does not have required user right ' + f'"{right}"{rights}') return fn(self, *args, **kwargs)
manage_wrapping(callee, fn) @@ -102,9 +109,8 @@ def callee(self, *args, **kwargs): if MediaWikiVersion(self.version()) < MediaWikiVersion(version): raise NotImplementedError( - 'Method or function "{}"\n' - "isn't implemented in MediaWiki version < {}" - .format(fn.__name__, version)) + f'Method or function "{fn.__name__}"\n' + f"isn't implemented in MediaWiki version < {version}") return fn(self, *args, **kwargs)
manage_wrapping(callee, fn) diff --git a/tests/site_decorators_tests.py b/tests/site_decorators_tests.py index a1e3c71..8256132 100755 --- a/tests/site_decorators_tests.py +++ b/tests/site_decorators_tests.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """Tests against a fake Site object.""" # -# (C) Pywikibot team, 2012-2023 +# (C) Pywikibot team, 2012-2024 # # Distributed under the terms of the MIT license. # @@ -15,9 +15,9 @@ from tests.aspects import DeprecationTestCase, TestCase
-class TestMustBe(TestCase): +class DecoratorTestsBase(TestCase):
- """Test cases for the must_be decorator.""" + """Base class for decorator tests."""
net = False
@@ -30,20 +30,29 @@ self.family.name = 'test' self.sitename = self.family.name + ':' + self.code self._logged_in_as = None - self._userinfo = [] self.obsolete = False super().setUp() - self.version = lambda: '1.23' # lowest supported release + self.version = lambda: '1.27' # lowest supported release + + def user(self): + """Fake the logged in user.""" + return self._logged_in_as + + +class TestMustBe(DecoratorTestsBase): + + """Test cases for the must_be decorator.""" + + def setUp(self): + """Creating fake variables to appear as a site.""" + self._userinfo = [] + super().setUp()
def login(self, group): """Fake the log in as required user group.""" self._logged_in_as = group self._userinfo = [group]
- def user(self): - """Fake the logged in user.""" - return self._logged_in_as - def has_group(self, group): """Fake the groups user belongs to.""" return group in self._userinfo @@ -127,38 +136,25 @@ self.call_this_user_req_function(args, kwargs)
-class TestNeedRight(TestCase): +class TestNeedRight(DecoratorTestsBase):
"""Test cases for the must_be decorator."""
- net = False - # Implemented without setUpClass(cls) and global variables as objects # were not completely disposed and recreated but retained 'memory' def setUp(self): """Creating fake variables to appear as a site.""" - self.code = 'test' - self.family = lambda: None - self.family.name = 'test' - self.sitename = self.family.name + ':' + self.code - self._logged_in_as = None - self._userinfo = [] - self.obsolete = False + self.userinfo = {'rights': []} super().setUp() - self.version = lambda: '1.23' # lowest supported release
def login(self, group, right): """Fake the log in as required user group.""" self._logged_in_as = group - self._userinfo = [right] - - def user(self): - """Fake the logged in user.""" - return self._logged_in_as + self.userinfo['rights'] = [right]
def has_right(self, right): """Fake the groups user belongs to.""" - return right in self._userinfo + return right in self.userinfo['rights']
@need_right('edit') def call_this_edit_req_function(self, *args, **kwargs):