jenkins-bot has submitted this change and it was merged. ( https://gerrit.wikimedia.org/r/585333 )
Change subject: [bugfix] Clear second level domain cookies after logout ......................................................................
[bugfix] Clear second level domain cookies after logout
To solve this issue, there are two options: Option A (this patch): - clear second level domain cookies in the current requests session directly after logout (this session logout) and after "badtoken" response (parallel session logout) Option B: - make separate session and *.lwp file for every site
Bug: T224712 Change-Id: I0e31ecaf14650ed499c82601a2afda6e9009f2a5 --- M pywikibot/data/api.py M pywikibot/site/__init__.py M tests/site_tests.py 3 files changed, 48 insertions(+), 0 deletions(-)
Approvals: Xqt: Looks good to me, approved jenkins-bot: Verified
diff --git a/pywikibot/data/api.py b/pywikibot/data/api.py index 499722b..9560b53 100644 --- a/pywikibot/data/api.py +++ b/pywikibot/data/api.py @@ -37,6 +37,7 @@ Server504Error, Server414Error, FatalServerError, NoUsername, Error, TimeoutError, MaxlagTimeoutError, InvalidTitle, UnsupportedPage ) +from pywikibot.family import SubdomainFamily from pywikibot.tools import ( deprecated, itergroup, PY2, PYTHON_VERSION, getargspec, UnicodeType, remove_last_args @@ -101,6 +102,21 @@ r'Waiting for [\w.: ]+: (?P<lag>\d+(?:.\d+)?) seconds? lagged')
+def _invalidate_superior_cookies(family): + """ + Clear cookies for site's second level domain. + + get_login_token() will generate new cookies needed. + This is a workaround for requests bug, see T224712 + and https://github.com/psf/requests/issues/5411 + for more details. + """ + if isinstance(family, SubdomainFamily): + for cookie in http.cookie_jar: + if family.domain == cookie.domain: + http.cookie_jar.clear(cookie.domain, cookie.path, cookie.name) + + class APIError(Error):
"""The wiki site returned an error message.""" @@ -1916,6 +1932,9 @@ 'invalidated them.' .format(self.site.user(), '", "'.join(sorted(set(invalid_param.values()))))) + # invalidate superior wiki cookies (T224712) + _invalidate_superior_cookies(self.site.family) + # request new token(s) instead of invalid self.site.tokens.load_tokens(set(invalid_param.values())) # fix parameters; lets hope that it doesn't mistake actual # parameters as tokens @@ -3180,6 +3199,8 @@ # force relogin and generate fresh one pywikibot.error('Received incorrect login token. ' 'Forcing re-login.') + # invalidate superior wiki cookies (T224712) + _invalidate_superior_cookies(self.site.family) continue elif (status == 'Throttled' or status == self.keyword('fail') and (response['messagecode'] == 'login-throttled' diff --git a/pywikibot/site/__init__.py b/pywikibot/site/__init__.py index 7729276..d99ad80 100644 --- a/pywikibot/site/__init__.py +++ b/pywikibot/site/__init__.py @@ -2135,6 +2135,9 @@ self.tokens = TokenWallet(self) self._paraminfo = api.ParamInfo(self)
+ # Clear also cookies for site's second level domain (T224712) + api._invalidate_superior_cookies(self.family) + def getuserinfo(self, force=False): """Retrieve userinfo from site and store in _userinfo attribute.
diff --git a/tests/site_tests.py b/tests/site_tests.py index e772cdc..0873eb6 100644 --- a/tests/site_tests.py +++ b/tests/site_tests.py @@ -3864,6 +3864,30 @@ self.assertIsNone(site.user())
+class TestClearCookies(TestCase): + """Test cookies are cleared after logout.""" + + user = True + + family = 'wikisource' + code = 'zh' + + def test_clear_cookies(self): + """Test cookies are cleared (T224712).""" + site = self.get_site() + site.login() + site2 = pywikibot.Site('mul', 'wikisource', user=site.username()) + site2.login() + site.logout() + + raised = False + try: + site.login() + except Exception as e: + raised = e + self.assertFalse(raised) + + if __name__ == '__main__': # pragma: no cover try: unittest.main()
pywikibot-commits@lists.wikimedia.org