stash: make Stash and StashKey public

It's had enough time to bake - let's allow external plugins to use it.
This commit is contained in:
Ran Benita
2021-07-18 14:05:58 +03:00
parent 5f39e31736
commit c6bdeb8491
7 changed files with 79 additions and 29 deletions

View File

@@ -923,6 +923,15 @@ class Config:
:type: PytestPluginManager
"""
self.stash = Stash()
"""A place where plugins can store information on the config for their
own use.
:type: Stash
"""
# Deprecated alias. Was never public. Can be removed in a few releases.
self._store = self.stash
from .compat import PathAwareHookProxy
self.trace = self.pluginmanager.trace.root.get("config")
@@ -931,9 +940,6 @@ class Config:
self._override_ini: Sequence[str] = ()
self._opt2dest: Dict[str, str] = {}
self._cleanup: List[Callable[[], None]] = []
# A place where plugins can store information on the config for their
# own use. Currently only intended for internal plugins.
self._store = Stash()
self.pluginmanager.register(self, "pytestconfig")
self._configured = False
self.hook.pytest_addoption.call_historic(

View File

@@ -218,9 +218,13 @@ class Node(metaclass=NodeMeta):
if self.name != "()":
self._nodeid += "::" + self.name
# A place where plugins can store information on the node for their
# own use. Currently only intended for internal plugins.
self._store = Stash()
#: A place where plugins can store information on the node for their
#: own use.
#:
#: :type: Stash
self.stash = Stash()
# Deprecated alias. Was never public. Can be removed in a few releases.
self._store = self.stash
@property
def fspath(self) -> LEGACY_PATH:

View File

@@ -14,7 +14,7 @@ D = TypeVar("D")
class StashKey(Generic[T]):
"""``StashKey`` is an object used as a key to a ``Stash``.
"""``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.
@@ -29,17 +29,19 @@ class Stash:
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``:
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 wants to store data in this Stash, it creates ``StashKey``\s
for its keys (at the module level):
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]()
@@ -59,25 +61,6 @@ class Stash:
some_str = stash[some_str_key]
# The static type of some_bool is bool.
some_bool = stash[some_bool_key]
Why use this?
-------------
Problem: module Internal defines an object. Module External, which
module Internal doesn't know about, receives the object and wants to
attach information to it, to be retrieved later given the object.
Bad solution 1: Module External assigns private attributes directly on
the object. This doesn't work well because the type checker doesn't
know about these attributes and it complains about undefined attributes.
Bad solution 2: module Internal adds a ``Dict[str, Any]`` attribute to
the object. Module External stores its data in private keys of this dict.
This doesn't work well because retrieved values are untyped.
Good solution: module Internal adds a ``Stash`` to the object. Module
External mints StashKeys for its own keys. Module External stores and
retrieves its data using these keys.
"""
__slots__ = ("_storage",)

View File

@@ -55,6 +55,8 @@ from _pytest.recwarn import deprecated_call
from _pytest.recwarn import WarningsRecorder
from _pytest.recwarn import warns
from _pytest.runner import CallInfo
from _pytest.stash import Stash
from _pytest.stash import StashKey
from _pytest.tmpdir import TempdirFactory
from _pytest.tmpdir import TempPathFactory
from _pytest.warning_types import PytestAssertRewriteWarning
@@ -131,6 +133,8 @@ __all__ = [
"Session",
"set_trace",
"skip",
"Stash",
"StashKey",
"version_tuple",
"TempPathFactory",
"Testdir",