Spaces:
Sleeping
Sleeping
from __future__ import annotations | |
from typing import Any | |
from typing import cast | |
from typing import Generic | |
from typing import TypeVar | |
__all__ = ["Stash", "StashKey"] | |
T = TypeVar("T") | |
D = TypeVar("D") | |
class StashKey(Generic[T]): | |
"""``StashKey`` is an object used as a key to a :class:`Stash`. | |
A ``StashKey`` is associated with the type ``T`` of the value of the key. | |
A ``StashKey`` is unique and cannot conflict with another key. | |
.. versionadded:: 7.0 | |
""" | |
__slots__ = () | |
class Stash: | |
r"""``Stash`` is a type-safe heterogeneous mutable mapping that | |
allows keys and value types to be defined separately from | |
where it (the ``Stash``) is created. | |
Usually you will be given an object which has a ``Stash``, for example | |
:class:`~pytest.Config` or a :class:`~_pytest.nodes.Node`: | |
.. code-block:: python | |
stash: Stash = some_object.stash | |
If a module or plugin wants to store data in this ``Stash``, it creates | |
:class:`StashKey`\s for its keys (at the module level): | |
.. code-block:: python | |
# At the top-level of the module | |
some_str_key = StashKey[str]() | |
some_bool_key = StashKey[bool]() | |
To store information: | |
.. code-block:: python | |
# Value type must match the key. | |
stash[some_str_key] = "value" | |
stash[some_bool_key] = True | |
To retrieve the information: | |
.. code-block:: python | |
# The static type of some_str is str. | |
some_str = stash[some_str_key] | |
# The static type of some_bool is bool. | |
some_bool = stash[some_bool_key] | |
.. versionadded:: 7.0 | |
""" | |
__slots__ = ("_storage",) | |
def __init__(self) -> None: | |
self._storage: dict[StashKey[Any], object] = {} | |
def __setitem__(self, key: StashKey[T], value: T) -> None: | |
"""Set a value for key.""" | |
self._storage[key] = value | |
def __getitem__(self, key: StashKey[T]) -> T: | |
"""Get the value for key. | |
Raises ``KeyError`` if the key wasn't set before. | |
""" | |
return cast(T, self._storage[key]) | |
def get(self, key: StashKey[T], default: D) -> T | D: | |
"""Get the value for key, or return default if the key wasn't set | |
before.""" | |
try: | |
return self[key] | |
except KeyError: | |
return default | |
def setdefault(self, key: StashKey[T], default: T) -> T: | |
"""Return the value of key if already set, otherwise set the value | |
of key to default and return default.""" | |
try: | |
return self[key] | |
except KeyError: | |
self[key] = default | |
return default | |
def __delitem__(self, key: StashKey[T]) -> None: | |
"""Delete the value for key. | |
Raises ``KeyError`` if the key wasn't set before. | |
""" | |
del self._storage[key] | |
def __contains__(self, key: StashKey[T]) -> bool: | |
"""Return whether key was set.""" | |
return key in self._storage | |
def __len__(self) -> int: | |
"""Return how many items exist in the stash.""" | |
return len(self._storage) | |