jenkins-bot has submitted this change and it was merged.
Change subject: api: handle assertuserfailed and mustbeposted (purge) errors
......................................................................
api: handle assertuserfailed and mustbeposted (purge) errors
Bug: T108942
Bug: T108947
Change-Id: I9a6f84079ce8279ffb5a0b8c907c9afffd11f119
---
M pywikibot/data/api.py
1 file changed, 15 insertions(+), 0 deletions(-)
Approvals:
John Vandenberg: Looks good to me, approved
Merlijn van Deen: Looks good to me, but someone else must approve
jenkins-bot: Verified
diff --git a/pywikibot/data/api.py b/pywikibot/data/api.py
index aafb63e..814b6ee 100644
--- a/pywikibot/data/api.py
+++ b/pywikibot/data/api.py
@@ -2036,6 +2036,21 @@
self.site._relogin()
continue
+ # If the user assertion failed, we're probably logged out as well.
+ if code == 'assertuserfailed':
+ pywikibot.error("User assertion failed. Forcing re-login.")
+ self.site._relogin()
+ continue
+
+ # Lastly, the purge module require a POST if used as anonymous user,
+ # but we normally send a GET request. If the API tells us the request
+ # has to be POSTed, we're probably logged out.
+ if code == 'mustbeposted' and self.action == 'purge':
+ pywikibot.error("Received unexpected 'mustbeposted' error. "
+ "Forcing re-login.")
+ self.site._relogin()
+ continue
+
if code == "maxlag":
lag = lagpattern.search(info)
if lag:
--
To view, visit https://gerrit.wikimedia.org/r/231218
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I9a6f84079ce8279ffb5a0b8c907c9afffd11f119
Gerrit-PatchSet: 12
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: Ladsgroup <ladsgroup(a)gmail.com>
Gerrit-Reviewer: Merlijn van Deen <valhallasw(a)arctus.nl>
Gerrit-Reviewer: XZise <CommodoreFabianus(a)gmx.de>
Gerrit-Reviewer: jenkins-bot <>
jenkins-bot has submitted this change and it was merged.
Change subject: fixup for 029ec04
......................................................................
fixup for 029ec04
- use self.login instead of self.site.login in Site
- use site._relogin rather than site.relogin
Change-Id: I564bef9106afe75b2111190dd5f4876061e73351
---
M pywikibot/data/api.py
M pywikibot/site.py
2 files changed, 14 insertions(+), 7 deletions(-)
Approvals:
John Vandenberg: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/data/api.py b/pywikibot/data/api.py
index 6283343..aafb63e 100644
--- a/pywikibot/data/api.py
+++ b/pywikibot/data/api.py
@@ -1996,6 +1996,13 @@
# case, force a re-login.
username = result['query']['userinfo']['name']
if self.site.user() is not None and self.site.user() != username:
+ pywikibot.error(
+ "Logged in as '{actual}' instead of '{expected}'. "
+ "Forcing re-login.".format(
+ actual=username,
+ expected=self.site.user()
+ )
+ )
self.site._relogin()
continue
@@ -2019,14 +2026,14 @@
code = result['error'].setdefault('code', 'Unknown')
info = result['error'].setdefault('info', None)
+ # Older wikis returned an error instead of a warning when
+ # the request asked for too many values. If we get this
+ # error, assume we are not logged in (we can't check this
+ # because the userinfo data is not present) and force
+ # a re-login
if code.endswith('limit'):
- # Older wikis returned an error instead of a warning when
- # the request asked for too many values. If we get this
- # error, assume we are not logged in (we can't check this
- # because the userinfo data is not present) and force
- # a re-login
pywikibot.error("Received API limit error. Forcing re-login")
- self.site.relogin()
+ self.site._relogin()
continue
if code == "maxlag":
diff --git a/pywikibot/site.py b/pywikibot/site.py
index 1ebbfc9..fa9e518 100644
--- a/pywikibot/site.py
+++ b/pywikibot/site.py
@@ -1934,7 +1934,7 @@
del self._userinfo
old_status = self._loginstatus
self._loginstatus = LoginStatus.NOT_LOGGED_IN
- self.site.login(old_status)
+ self.login(old_status)
def logout(self):
"""Logout of the site and load details for the logged out user.
--
To view, visit https://gerrit.wikimedia.org/r/236413
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I564bef9106afe75b2111190dd5f4876061e73351
Gerrit-PatchSet: 1
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: Merlijn van Deen <valhallasw(a)arctus.nl>
Gerrit-Reviewer: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: Ladsgroup <ladsgroup(a)gmail.com>
Gerrit-Reviewer: jenkins-bot <>
jenkins-bot has submitted this change and it was merged.
Change subject: APISite: simplify _userinfo caching
......................................................................
APISite: simplify _userinfo caching
Removed two checks in getuserinfo:
- The old code compared the username in _userinfo
to the username //based on the groups in _userinfo//,
which caused repetitive requests in two cases:
1) no username configured
2) no sysopname configured and the normal username
has sysop rights
- The code checked if _userinfo contained 'rights',
but the only code that sets 'rights' is getuserinfo(),
which explicitly requests 'rights'. If the API doesn't
return those, requesting it again won't solve the issue.
Removed code in api.py that wrote to site._userinfo. Updates
should only be done by self.getuserinfo.
Reworked the 'logged out' check to use Site functions instead
of fiddling with Site internals directly.
Moved LoginStatus into a seperate module.
[1] https://www.mediawiki.org/wiki/API:Errors_and_warnings
The original code for getuserinfo was added in 697a20d
The original code for api.php was added in 5b0fc90
Bug: T57192
Change-Id: I409bd268bf655c2a05d0f206e164d8db334b1311
---
M pywikibot/data/api.py
M pywikibot/site.py
2 files changed, 33 insertions(+), 22 deletions(-)
Approvals:
John Vandenberg: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/data/api.py b/pywikibot/data/api.py
index f3772c7..6283343 100644
--- a/pywikibot/data/api.py
+++ b/pywikibot/data/api.py
@@ -1989,26 +1989,16 @@
"Unable to process query response of type %s."
% type(result),
data=result)
- if self.action == 'query':
- if 'userinfo' in result.get('query', ()):
- if hasattr(self.site, '_userinfo'):
- self.site._userinfo.update(result['query']['userinfo'])
- else:
- self.site._userinfo = result['query']['userinfo']
- status = self.site._loginstatus # save previous login status
- if (('error' in result and
- result['error']['code'].endswith('limit')) or
- (status >= 0 and
- self.site._userinfo['name'] != self.site._username[status])):
- # user is no longer logged in (session expired?)
- # reset userinfo, then make user log in again
- del self.site._userinfo
- self.site._loginstatus = -1
- if status < 0:
- status = 0 # default to non-sysop login
- self.site.login(status)
- # retry the previous query
+
+ if self.action == 'query' and 'userinfo' in result.get('query', ()):
+ # if we get passed userinfo in the query result, we can confirm
+ # that we are logged in as the correct user. If this is not the
+ # case, force a re-login.
+ username = result['query']['userinfo']['name']
+ if self.site.user() is not None and self.site.user() != username:
+ self.site._relogin()
continue
+
self._handle_warnings(result)
if "error" not in result:
@@ -2028,6 +2018,17 @@
result['error']['help'] = result['error'].pop("*")
code = result['error'].setdefault('code', 'Unknown')
info = result['error'].setdefault('info', None)
+
+ if code.endswith('limit'):
+ # Older wikis returned an error instead of a warning when
+ # the request asked for too many values. If we get this
+ # error, assume we are not logged in (we can't check this
+ # because the userinfo data is not present) and force
+ # a re-login
+ pywikibot.error("Received API limit error. Forcing re-login")
+ self.site.relogin()
+ continue
+
if code == "maxlag":
lag = lagpattern.search(info)
if lag:
diff --git a/pywikibot/site.py b/pywikibot/site.py
index e9d1100..1ebbfc9 100644
--- a/pywikibot/site.py
+++ b/pywikibot/site.py
@@ -1924,6 +1924,18 @@
forceLogin = redirect_func(login, old_name='forceLogin',
class_name='APISite')
+ def _relogin(self):
+ """Force a login sequence without logging out, using the current user.
+
+ This is an internal function which is used to re-login when
+ the internal login state does not match the state we receive
+ from the site.
+ """
+ del self._userinfo
+ old_status = self._loginstatus
+ self._loginstatus = LoginStatus.NOT_LOGGED_IN
+ self.site.login(old_status)
+
def logout(self):
"""Logout of the site and load details for the logged out user.
@@ -1954,9 +1966,7 @@
@param force: force to retrieve userinfo ignoring cache
@type force: bool
"""
- if (not hasattr(self, '_userinfo') or force or
- 'rights' not in self._userinfo or
- self._userinfo['name'] != self._username['sysop' in self._userinfo['groups']]):
+ if force or not hasattr(self, '_userinfo'):
uirequest = self._simple_request(
action="query",
meta="userinfo",
--
To view, visit https://gerrit.wikimedia.org/r/231769
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I409bd268bf655c2a05d0f206e164d8db334b1311
Gerrit-PatchSet: 13
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: Merlijn van Deen <valhallasw(a)arctus.nl>
Gerrit-Reviewer: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: Ladsgroup <ladsgroup(a)gmail.com>
Gerrit-Reviewer: Malafaya <malafaya(a)clix.pt>
Gerrit-Reviewer: Merlijn van Deen <valhallasw(a)arctus.nl>
Gerrit-Reviewer: XZise <CommodoreFabianus(a)gmx.de>
Gerrit-Reviewer: jenkins-bot <>
jenkins-bot has submitted this change and it was merged.
Change subject: Deprecate fetching all mediawiki_messages using *
......................................................................
Deprecate fetching all mediawiki_messages using *
Support for fetching multiple messages was added for T60944
in d209142, with b34209d allowing '*' to be used to fetch all messages.
It would be unusual to actually need to use all messages.
More usual would be to need to fetch all message names, which may
be supported using amnocontent.
Move the '*' tests to a dry site, as they are running
particularly slow on ar.wikipedia causing timeouts.
Bug: T111479
Change-Id: Ideefaa198c44bde07d90f23f53991bd3ab81585d
---
M pywikibot/site.py
M tests/site_tests.py
M tests/utils.py
3 files changed, 37 insertions(+), 12 deletions(-)
Approvals:
John Vandenberg: Looks good to me, but someone else must approve
Mpaa: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/site.py b/pywikibot/site.py
index e9d1100..d39178e 100644
--- a/pywikibot/site.py
+++ b/pywikibot/site.py
@@ -2149,7 +2149,8 @@
def mediawiki_messages(self, keys):
"""Fetch the text of a set of MediaWiki messages.
- If keys is '*' or ['*'], all messages will be fetched.
+ If keys is '*' or ['*'], all messages will be fetched. (deprecated)
+
The returned dict uses each key to store the associated message.
@param keys: MediaWiki messages to fetch
@@ -2157,6 +2158,10 @@
@return: dict
"""
+ if keys == '*' or keys == ['*']:
+ issue_deprecation_warning('mediawiki_messages("*")',
+ 'specific messages', 2)
+
if not all(_key in self._msgcache for _key in keys):
parameters = {'meta': 'allmessages',
'ammessages': keys,
diff --git a/tests/site_tests.py b/tests/site_tests.py
index b7c7038..0e13503 100644
--- a/tests/site_tests.py
+++ b/tests/site_tests.py
@@ -157,6 +157,19 @@
self.assertOneDeprecationParts('Calling the namespaces property',
'it directly')
+ def test_messages_star(self):
+ """Test that fetching all messages is deprecated."""
+ # Load all messages and check that '*' is not a valid key.
+ mysite = self.site
+ self.assertIsInstance(mysite.mediawiki_messages('*'), dict)
+ self.assertOneDeprecationParts('mediawiki_messages("*")',
+ 'specific messages')
+
+ self.assertEqual(len(mysite.mediawiki_messages(['*'])), 1)
+ self.assertOneDeprecation()
+ self.assertEqual(mysite.mediawiki_messages('*'), {'*': 'dummy entry'})
+ self.assertOneDeprecation()
+
class TestBaseSiteProperties(TestCase):
@@ -315,13 +328,16 @@
for key in ns
for item in mysite.namespace(key, True)))
- def testApiMethods(self):
- """Test generic ApiSite methods."""
+ def test_user_attributes_return_types(self):
+ """Test returned types of user attributes."""
mysite = self.get_site()
self.assertIsInstance(mysite.logged_in(), bool)
self.assertIsInstance(mysite.logged_in(True), bool)
self.assertIsInstance(mysite.userinfo, dict)
+ def test_messages(self):
+ """Test MediaWiki: messages."""
+ mysite = self.get_site()
for msg in ('about', 'aboutpage', 'aboutsite', 'accesskey-n-portal'):
self.assertTrue(mysite.has_mediawiki_message(msg))
self.assertIsInstance(mysite.mediawiki_message(msg), basestring)
@@ -329,28 +345,31 @@
self.assertRaises(KeyError, mysite.mediawiki_message, "nosuchmessage")
msg = ('about', 'aboutpage')
+ about_msgs = self.site.mediawiki_messages(msg)
self.assertIsInstance(mysite.mediawiki_messages(msg), dict)
self.assertTrue(mysite.mediawiki_messages(msg))
+ self.assertEqual(len(about_msgs), 2)
+ self.assertIn(msg[0], about_msgs)
+
+ # mediawiki_messages must be given a list; using a string will split it
+ self.assertRaises(KeyError, self.site.mediawiki_messages, 'about')
msg = ("nosuchmessage1", "about", "aboutpage", "nosuchmessage")
self.assertFalse(mysite.has_all_mediawiki_messages(msg))
self.assertRaises(KeyError, mysite.mediawiki_messages, msg)
-
- # Load all messages and check that '*' is not a valid key.
- self.assertIsInstance(mysite.mediawiki_messages('*'), dict)
- self.assertGreater(len(mysite.mediawiki_messages(['*'])), 10)
- self.assertNotIn('*', mysite.mediawiki_messages(['*']))
self.assertIsInstance(mysite.server_time(), pywikibot.Timestamp)
ts = mysite.getcurrenttimestamp()
self.assertIsInstance(ts, basestring)
self.assertRegex(ts, r'(19|20)\d\d[0-1]\d[0-3]\d[0-2]\d[0-5]\d[0-5]\d')
- self.assertIsInstance(mysite.siteinfo, pywikibot.site.Siteinfo)
self.assertIsInstance(mysite.months_names, list)
- ver = mysite.version()
- self.assertIsInstance(ver, basestring)
- self.assertIsNotNone(re.search('^\d+\.\d+.*?\d*$', ver))
+ self.assertEqual(len(mysite.months_names), 12)
+ self.assertTrue(all(isinstance(month, tuple)
+ for month in mysite.months_names))
+ self.assertTrue(all(len(month) == 2
+ for month in mysite.months_names))
+
self.assertEqual(mysite.list_to_text(('pywikibot',)), 'pywikibot')
def testEnglishSpecificMethods(self):
diff --git a/tests/utils.py b/tests/utils.py
index 79a9244..54731af 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -348,6 +348,7 @@
if self.family.name == 'wikisource':
extensions.append({'name': 'ProofreadPage'})
self._siteinfo._cache['extensions'] = (extensions, True)
+ self._msgcache = {'*': 'dummy entry'}
def _build_namespaces(self):
return Namespace.builtin_namespaces(case=self.siteinfo['case'])
--
To view, visit https://gerrit.wikimedia.org/r/236245
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Ideefaa198c44bde07d90f23f53991bd3ab81585d
Gerrit-PatchSet: 1
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: Ladsgroup <ladsgroup(a)gmail.com>
Gerrit-Reviewer: Mpaa <mpaa.wiki(a)gmail.com>
Gerrit-Reviewer: Xqt <info(a)gno.de>
Gerrit-Reviewer: jenkins-bot <>
jenkins-bot has submitted this change and it was merged.
Change subject: Mark site.patrol() as a user write action
......................................................................
Mark site.patrol() as a user write action
Set the patrol test case to be 'write' so that it is
disabled by default, and only run on the 'test:test' site.
Fix SiteWriteMixin so that
- use of 'write' and 'cached' attributes always cause an error
even if write tests are not enabled with PYWIKIBOT2_TEST_WRITE
- an error occurs if write tests are run on sites which haven't
been configured as test sites using Family.test_codes, however
they are skipped on non-test sites when PYWIKIBOT2_TEST_WRITE is
not enabled.
Change-Id: I0ab4dc20f82857505236c0c678a602c02c001e37
---
M pywikibot/families/test_family.py
M pywikibot/site.py
M tests/aspects.py
M tests/site_tests.py
4 files changed, 19 insertions(+), 6 deletions(-)
Approvals:
XZise: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/families/test_family.py b/pywikibot/families/test_family.py
index fa26d62..4a80e7d 100644
--- a/pywikibot/families/test_family.py
+++ b/pywikibot/families/test_family.py
@@ -14,3 +14,4 @@
name = 'test'
domain = 'test.wikipedia.org'
+ test_codes = ('test', )
diff --git a/pywikibot/site.py b/pywikibot/site.py
index e9d1100..e88ab36 100644
--- a/pywikibot/site.py
+++ b/pywikibot/site.py
@@ -4979,6 +4979,7 @@
"notpatrollable": "The revision %(revid)s can't be patrolled as it's too old."
}
+ @must_be(group='user')
@deprecated_args(token=None)
def patrol(self, rcid=None, revid=None, revision=None):
"""Return a generator of patrolled pages.
diff --git a/tests/aspects.py b/tests/aspects.py
index 0ed694f..1add9e2 100644
--- a/tests/aspects.py
+++ b/tests/aspects.py
@@ -539,10 +539,15 @@
Otherwise the test class is skipped unless environment variable
PYWIKIBOT2_TEST_WRITE is set to 1.
"""
+ if issubclass(cls, ForceCacheMixin):
+ raise Exception(
+ '%s can not be a subclass of both '
+ 'SiteWriteMixin and ForceCacheMixin'
+ % cls.__name__)
+
super(SiteWriteMixin, cls).setUpClass()
site = cls.get_site()
- assert 'test' in (site.family.name, site.code)
if cls.write == -1:
env_var = 'PYWIKIBOT2_TEST_WRITE_FAIL'
@@ -555,11 +560,13 @@
'Set %s=1 to enable.'
% (cls.__name__, env_var))
- if issubclass(cls, ForceCacheMixin):
+ if (not hasattr(site.family, 'test_codes') or
+ site.code not in site.family.test_codes):
raise Exception(
- '%s can not be a subclass of both '
- 'SiteEditTestCase and ForceCacheMixin'
- % cls.__name__)
+ '%s should only be run on test sites. '
+ 'To run this test, add \'%s\' to the %s family '
+ 'attribute \'test_codes\'.'
+ % (cls.__name__, site.code, site.family.name))
class RequireUserMixin(TestCaseBase):
diff --git a/tests/site_tests.py b/tests/site_tests.py
index b7c7038..a7ef0f1 100644
--- a/tests/site_tests.py
+++ b/tests/site_tests.py
@@ -1620,12 +1620,16 @@
raise unittest.SkipTest('Test usernames not found')
-class PatrolTestCase(TokenTestBase, DefaultSiteTestCase):
+class PatrolTestCase(TokenTestBase, TestCase):
"""Test patrol method."""
+ family = 'test'
+ code = 'test'
+
user = True
token_type = 'patrol'
+ write = True
def testPatrol(self):
"""Test the site.patrol() method."""
--
To view, visit https://gerrit.wikimedia.org/r/233912
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I0ab4dc20f82857505236c0c678a602c02c001e37
Gerrit-PatchSet: 4
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: Ladsgroup <ladsgroup(a)gmail.com>
Gerrit-Reviewer: XZise <CommodoreFabianus(a)gmx.de>
Gerrit-Reviewer: jenkins-bot <>