Source code for pywikibot.site._tokenwallet

"""Objects representing api tokens."""
#
# (C) Pywikibot team, 2008-2020
#
# Distributed under the terms of the MIT license.
#
from pywikibot import log
from pywikibot.exceptions import Error


[docs]class TokenWallet: """Container for tokens.""" def __init__(self, site): """Initializer. :type site: pywikibot.site.APISite """ self.site = site self._tokens = {} self.failed_cache = set() # cache unavailable tokens.
[docs] def load_tokens(self, types, all=False): """ Preload one or multiple tokens. :param types: the types of token. :type types: iterable :param all: load all available tokens, if None only if it can be done in one request. :type all: bool """ if self.site.user() is None: self.site.login() self._tokens.setdefault(self.site.user(), {}).update( self.site.get_tokens(types, all=all)) # Preload all only the first time. # When all=True types is extended in site.get_tokens(). # Keys not recognised as tokens, are cached so they are not requested # any longer. if all is not False: for key in types: if key not in self._tokens[self.site.user()]: self.failed_cache.add((self.site.user(), key))
def __getitem__(self, key): """Get token value for the given key.""" if self.site.user() is None: self.site.login() user_tokens = self._tokens.setdefault(self.site.user(), {}) # always preload all for users without tokens failed_cache_key = (self.site.user(), key) # redirect old tokens to be compatible with older MW version # https://www.mediawiki.org/wiki/MediaWiki_1.37/Deprecation_of_legacy_API_token_parameters if self.site.mw_version >= '1.24wmf19' \ and key in {'edit', 'delete', 'protect', 'move', 'block', 'unblock', 'email', 'import', 'options'}: log('Token {!r} was replaced by {!r}'.format(key, 'csrf')) key = 'csrf' try: key = self.site.validate_tokens([key])[0] except IndexError: raise Error( "Requested token '{}' is invalid on {} wiki." .format(key, self.site)) if (key not in user_tokens and failed_cache_key not in self.failed_cache): self.load_tokens([key], all=False if user_tokens else None) if key in user_tokens: return user_tokens[key] # token not allowed for self.site.user() on self.site self.failed_cache.add(failed_cache_key) # to be changed back to a plain KeyError? raise Error( "Action '{}' is not allowed for user {} on {} wiki." .format(key, self.site.user(), self.site)) def __contains__(self, key): """Return True if the given token name is cached.""" return key in self._tokens.setdefault(self.site.user(), {}) def __str__(self): """Return a str representation of the internal tokens dictionary.""" return self._tokens.__str__() def __repr__(self): """Return a representation of the internal tokens dictionary.""" return self._tokens.__repr__()