Source code for pywikibot.site._tokenwallet

#
# (C) Pywikibot team, 2008-2026
#
# Distributed under the terms of the MIT license.
#
"""Objects representing api tokens."""
from __future__ import annotations

from collections.abc import Container
from typing import TYPE_CHECKING


if TYPE_CHECKING:
    from pywikibot.site import APISite


[docs] class TokenWallet(Container): """Container for tokens. You should not use this container class directly; use :attr:`APISite.tokens<pywikibot.site._apisite.APISite.tokens>` instead which gives access to the site's TokenWallet instance. """ def __init__(self, site: APISite) -> None: """Initializer.""" self.site: APISite = site self._tokens: dict[str, str] = {} self._currentuser: str | None = site.user() # guess the needed token in update_tokens self._last_token_key: str | None = None def __getitem__(self, key: str) -> str: """Get token value for the given key. .. version-changed:: 11.0 Support of legacy API tokens was dropped. """ if self.site.user() is None and key != 'login': self.site.login() if self.site.user() != self._currentuser: self._currentuser = self.site.user() self.clear() if not self._tokens: self._tokens = self.site.get_tokens([]) try: token = self._tokens[key] except KeyError: raise KeyError( f'Invalid token {key!r} for user {self._currentuser!r} on ' f'{self.site} wiki.') from None self._last_token_key = key return token def __contains__(self, key) -> bool: """Return True if the token name is cached for the current user.""" try: self[key] except KeyError: return False return True def __str__(self) -> str: """Return a str representation of the internal tokens dictionary.""" return str(self._tokens) def __repr__(self) -> str: """Return a representation of the TokenWallet. >>> import pywikibot >>> site = pywikibot.Site('wikipedia:test') >>> repr(site.tokens) "TokenWallet(pywikibot.Site('wikipedia:test'))" .. version-changed:: 8.0 Provide a string which looks like a valid Python expression. """ user = f', user={self._currentuser!r}' if self._currentuser else '' return (f'{type(self).__name__}' f'(pywikibot.Site({self.site.sitename!r}{user}))')
[docs] def clear(self) -> None: """Clear the self._tokens cache. Tokens are reloaded when needed. .. version-added:: 8.0 """ self._tokens.clear()
[docs] def update_tokens(self, tokens: list[str]) -> list[str]: """Return a list of new tokens for a given list of tokens. This method can be used if a token is outdated and has to be renewed but the token type is unknown and we only have the old token. It first gets the token names from all given tokens, clears the cache and returns fresh new tokens of the found types. **Usage:** >>> import pywikibot >>> site = pywikibot.Site() >>> tokens = [site.tokens['csrf']] # doctest: +SKIP >>> new_tokens = site.tokens.update_tokens(tokens) # doctest: +SKIP .. code-block:: Python :caption: An example for replacing request token parameters r._params['token'] = r.site.tokens.update_tokens(r._params['token']) .. version-added:: 8.0 :param tokens: A list of token types that need to be updated. :return: A list of updated tokens corresponding to the given *tokens* types. :raises KeyError: If no valid token types can be determined to update. """ # find the token types types = [key for key, value in self._tokens.items() for token in tokens if value == token] # fallback to _last_token_key if no types found if not types and self._last_token_key is not None: types = [self._last_token_key] if not types: raise KeyError('No valid token types found to update.') self.clear() # clear the cache return [self[token_type] for token_type in types]