```
WARNING: Using OAuth suppresses logout function
WARNING: API error badtoken: Invalid CSRF token.
WARNING: API error badtoken: Invalid CSRF token.
WARNING: API error badtoken: Invalid CSRF token.
…
299.703s FAILED
```
```
=================================== FAILURES ===================================
________________________ TestPageUserAction.test_watch _________________________
self = <tests.page_tests.TestPageUserAction testMethod=test_watch>
def test_watch(self):
"""Test Page.watch, with and without unwatch enabled."""
# 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()
> rv = userpage.watch()
tests/page_tests.py:1010:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
pywikibot/page/__init__.py:1372: in watch
return self.site.watch(self, unwatch)
pywikibot/site/_decorators.py:94: in callee
return fn(self, *args, **kwargs)
pywikibot/site/__init__.py:4193: in watch
results = req.submit()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = pywikibot.data.api.Request<wpbeta:en->'/w/api.php?action=watch&titles=User:Pywikibot-oauth&assert=user&maxlag=5&format=json&token=0477a4b0e20fe8b26065084af718455b5fdb43f5+\\'>
def submit(self) -> dict:
"""
Submit a query and parse the response.
@return: a dict containing data retrieved from api.php
"""
self._add_defaults()
use_get = self._use_get()
retries = 0
while True:
paramstring = self._http_param_string()
simulate = self._simulate(self.action)
if simulate:
return simulate
if self.throttle:
self.site.throttle(write=self.write)
else:
pywikibot.log(
"Submitting unthrottled action '{0}'.".format(self.action))
use_get, uri, body, headers = self._get_request_params(use_get,
paramstring)
rawdata, use_get = self._http_request(use_get, uri, body, headers,
paramstring)
if rawdata is None:
continue
result = self._json_loads(rawdata)
if result is None:
continue
if self._userinfo_query(result):
continue
self._handle_warnings(result)
if 'error' not in result:
return result
error = result['error'].copy()
for key in result:
if key in ('error', 'warnings'):
continue
assert key not in error
assert isinstance(result[key], str), \
'Unexpected %s: %r' % (key, result[key])
error[key] = result[key]
if '*' in result['error']:
# help text returned
result['error']['help'] = result['error'].pop('*')
code = result['error'].setdefault('code', 'Unknown')
info = result['error'].setdefault('info', None)
if not self._logged_in(code):
continue
if code == 'maxlag':
retries += 1
if retries > max(5, pywikibot.config.max_retries):
break
pywikibot.log('Pausing due to database lag: ' + info)
try:
lag = result['error']['lag']
except KeyError:
lag = lagpattern.search(info)
lag = float(lag.group('lag')) if lag else 0.0
self.site.throttle.lag(lag * retries)
continue
elif code == 'help' and self.action == 'help':
# The help module returns an error result with the complete
# API information. As this data was requested, return the
# data instead of raising an exception.
return {'help': {'mime': 'text/plain',
'help': result['error']['help']}}
pywikibot.warning('API error %s: %s' % (code, info))
if self._internal_api_error(code, error, result):
continue
# Phab. tickets T48535, T64126, T68494, T68619
if code == 'failed-save' and \
self._is_wikibase_error_retryable(result['error']):
self.wait()
continue
if code == 'ratelimited':
self._ratelimited()
continue
# If readapidenied is returned try to login
if code == 'readapidenied' \
and self.site._loginstatus in (LoginStatus.NOT_ATTEMPTED,
LoginStatus.NOT_LOGGED_IN):
self.site.login()
continue
if self._bad_token(code):
continue
if 'mwoauth-invalid-authorization' in code:
if 'Nonce already used' in info:
pywikibot.error(
'Retrying failed OAuth authentication for {0}: {1}'
.format(self.site, info))
continue
raise NoUsername('Failed OAuth authentication for %s: %s'
% (self.site, info))
if code == 'cirrussearch-too-busy-error': # T170647
self.wait()
continue
if code == 'urlshortener-blocked': # T244062
# add additional informations to result['error']
result['error']['current site'] = self.site
if self.site.user():
result['error']['current user'] = self.site.user()
else: # not logged in; show the IP
uinfo = self.site.userinfo
result['error']['current user'] = uinfo['name']
# raise error
try:
param_repr = str(self._params)
pywikibot.log('API Error: query=\n%s'
% pprint.pformat(param_repr))
pywikibot.log(' response=\n{}'.format(result))
> raise APIError(**result['error'])
E pywikibot.data.api.APIError: badtoken: Invalid CSRF token.
E [help: See https://en.wikipedia.beta.wmflabs.org/w/api.php for API usage. Subscribe to the mediawiki-api-announce mailing list at <https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce> for notice of API deprecations and breaking changes.]
pywikibot/data/api.py:1981: APIError
------------------------------ Captured log call -------------------------------
INFO pywiki:logging.py:102 Sleeping for 9.4 seconds, 2020-12-17 11:41:41
WARNING pywiki:logging.py:102 API error badtoken: Invalid CSRF token.
VERBOSE pywiki:logging.py:102 Login status: IN_PROGRESS
VERBOSE pywiki:logging.py:102 API Error: query=
("{'action': ['watch'], 'token': "
"['0477a4b0e20fe8b26065084af718455b5fdb43f5+\\\\'], 'unwatch': [False], "
"'titles': [User('User:Pywikibot-oauth')], 'assert': ['user'], 'maxlag': "
"['5'], 'format': ['json']}")
VERBOSE pywiki:logging.py:102 response=
{'error': {'code': 'badtoken', 'info': 'Invalid CSRF token.', 'help': 'See https://en.wikipedia.beta.wmflabs.org/w/api.php for API usage. Subscribe to the mediawiki-api-announce mailing list at <https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce> for notice of API deprecations and breaking changes.'}, 'servedby': 'deployment-mediawiki-07'}
______________________ TestLoginLogout.test_login_logout _______________________
self = <tests.site_tests.TestLoginLogout testMethod=test_login_logout>
def test_login_logout(self):
"""Validate login and logout methods by toggling the state."""
site = self.get_site()
loginstatus = pywikibot.login.LoginStatus
self.assertTrue(site.logged_in())
self.assertIn(site._loginstatus, (loginstatus.IN_PROGRESS,
loginstatus.AS_USER))
self.assertIn('_userinfo', site.__dict__.keys())
self.assertIsNone(site.login())
if site.is_oauth_token_available():
with self.assertRaisesRegex(api.APIError, 'cannotlogout.*OAuth'):
> site.logout()
tests/site_tests.py:3300:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
pywikibot/site/__init__.py:368: in logout
uirequest.submit()
pywikibot/data/api.py:1872: in submit
paramstring)
pywikibot/data/api.py:1610: in _http_request
body=body, headers=headers)
pywikibot/comms/http.py:257: in request
r = fetch(baseuri, method, params, body, headers, **kwargs)
pywikibot/tools/__init__.py:1481: in wrapper
return obj(*__args, **__kw)
pywikibot/comms/http.py:412: in fetch
**kwargs)
../../../virtualenv/python3.6.7/lib/python3.6/site-packages/requests/sessions.py:542: in request
resp = self.send(prep, **send_kwargs)
../../../virtualenv/python3.6.7/lib/python3.6/site-packages/requests/sessions.py:655: in send
r = adapter.send(request, **kwargs)
../../../virtualenv/python3.6.7/lib/python3.6/site-packages/requests/adapters.py:449: in send
timeout=timeout
../../../virtualenv/python3.6.7/lib/python3.6/site-packages/urllib3/connectionpool.py:706: in urlopen
chunked=chunked,
../../../virtualenv/python3.6.7/lib/python3.6/site-packages/urllib3/connectionpool.py:445: in _make_request
six.raise_from(e, None)
<string>:3: in raise_from
???
../../../virtualenv/python3.6.7/lib/python3.6/site-packages/urllib3/connectionpool.py:440: in _make_request
httplib_response = conn.getresponse()
/opt/python/3.6.7/lib/python3.6/http/client.py:1331: in getresponse
response.begin()
/opt/python/3.6.7/lib/python3.6/http/client.py:297: in begin
version, status, reason = self._read_status()
/opt/python/3.6.7/lib/python3.6/http/client.py:258: in _read_status
line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
/opt/python/3.6.7/lib/python3.6/socket.py:586: in readinto
return self._sock.recv_into(b)
/opt/python/3.6.7/lib/python3.6/ssl.py:1012: in recv_into
return self.read(nbytes, buffer)
/opt/python/3.6.7/lib/python3.6/ssl.py:874: in read
return self._sslobj.read(len, buffer)
/opt/python/3.6.7/lib/python3.6/ssl.py:631: in read
v = self._sslobj.read(len, buffer)
../../../virtualenv/python3.6.7/lib/python3.6/site-packages/pytest_timeout.py:200: in handler
timeout_sigalrm(item, params.timeout)
../../../virtualenv/python3.6.7/lib/python3.6/site-packages/pytest_timeout.py:375: in timeout_sigalrm
pytest.fail("Timeout >%ss" % timeout)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
@_with_exception(Failed)
def fail(msg: str = "", pytrace: bool = True) -> "NoReturn":
"""Explicitly fail an executing test with the given message.
:param str msg:
The message to show the user as reason for the failure.
:param bool pytrace:
If False, msg represents the full failure information and no
python traceback will be reported.
"""
__tracebackhide__ = True
> raise Failed(msg=msg, pytrace=pytrace)
E Failed: Timeout >300.0s
```