Merge pull request #6865 from bluetech/more-config-store
Convert a couple of places to use config store
This commit is contained in:
commit
1df593f978
|
@ -7,6 +7,7 @@ from typing import Optional
|
||||||
from _pytest.assertion import rewrite
|
from _pytest.assertion import rewrite
|
||||||
from _pytest.assertion import truncate
|
from _pytest.assertion import truncate
|
||||||
from _pytest.assertion import util
|
from _pytest.assertion import util
|
||||||
|
from _pytest.assertion.rewrite import assertstate_key
|
||||||
from _pytest.compat import TYPE_CHECKING
|
from _pytest.compat import TYPE_CHECKING
|
||||||
from _pytest.config import hookimpl
|
from _pytest.config import hookimpl
|
||||||
|
|
||||||
|
@ -82,13 +83,13 @@ class AssertionState:
|
||||||
|
|
||||||
def install_importhook(config):
|
def install_importhook(config):
|
||||||
"""Try to install the rewrite hook, raise SystemError if it fails."""
|
"""Try to install the rewrite hook, raise SystemError if it fails."""
|
||||||
config._assertstate = AssertionState(config, "rewrite")
|
config._store[assertstate_key] = AssertionState(config, "rewrite")
|
||||||
config._assertstate.hook = hook = rewrite.AssertionRewritingHook(config)
|
config._store[assertstate_key].hook = hook = rewrite.AssertionRewritingHook(config)
|
||||||
sys.meta_path.insert(0, hook)
|
sys.meta_path.insert(0, hook)
|
||||||
config._assertstate.trace("installed rewrite import hook")
|
config._store[assertstate_key].trace("installed rewrite import hook")
|
||||||
|
|
||||||
def undo():
|
def undo():
|
||||||
hook = config._assertstate.hook
|
hook = config._store[assertstate_key].hook
|
||||||
if hook is not None and hook in sys.meta_path:
|
if hook is not None and hook in sys.meta_path:
|
||||||
sys.meta_path.remove(hook)
|
sys.meta_path.remove(hook)
|
||||||
|
|
||||||
|
@ -100,7 +101,7 @@ def pytest_collection(session: "Session") -> None:
|
||||||
# this hook is only called when test modules are collected
|
# this hook is only called when test modules are collected
|
||||||
# so for example not in the master process of pytest-xdist
|
# so for example not in the master process of pytest-xdist
|
||||||
# (which does not collect test modules)
|
# (which does not collect test modules)
|
||||||
assertstate = getattr(session.config, "_assertstate", None)
|
assertstate = session.config._store.get(assertstate_key, None)
|
||||||
if assertstate:
|
if assertstate:
|
||||||
if assertstate.hook is not None:
|
if assertstate.hook is not None:
|
||||||
assertstate.hook.set_session(session)
|
assertstate.hook.set_session(session)
|
||||||
|
@ -163,7 +164,7 @@ def pytest_runtest_protocol(item):
|
||||||
|
|
||||||
|
|
||||||
def pytest_sessionfinish(session):
|
def pytest_sessionfinish(session):
|
||||||
assertstate = getattr(session.config, "_assertstate", None)
|
assertstate = session.config._store.get(assertstate_key, None)
|
||||||
if assertstate:
|
if assertstate:
|
||||||
if assertstate.hook is not None:
|
if assertstate.hook is not None:
|
||||||
assertstate.hook.set_session(None)
|
assertstate.hook.set_session(None)
|
||||||
|
|
|
@ -26,9 +26,18 @@ from _pytest.assertion.util import ( # noqa: F401
|
||||||
format_explanation as _format_explanation,
|
format_explanation as _format_explanation,
|
||||||
)
|
)
|
||||||
from _pytest.compat import fspath
|
from _pytest.compat import fspath
|
||||||
|
from _pytest.compat import TYPE_CHECKING
|
||||||
from _pytest.pathlib import fnmatch_ex
|
from _pytest.pathlib import fnmatch_ex
|
||||||
from _pytest.pathlib import Path
|
from _pytest.pathlib import Path
|
||||||
from _pytest.pathlib import PurePath
|
from _pytest.pathlib import PurePath
|
||||||
|
from _pytest.store import StoreKey
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from _pytest.assertion import AssertionState # noqa: F401
|
||||||
|
|
||||||
|
|
||||||
|
assertstate_key = StoreKey["AssertionState"]()
|
||||||
|
|
||||||
|
|
||||||
# pytest caches rewritten pycs in pycache dirs
|
# pytest caches rewritten pycs in pycache dirs
|
||||||
PYTEST_TAG = "{}-pytest-{}".format(sys.implementation.cache_tag, version)
|
PYTEST_TAG = "{}-pytest-{}".format(sys.implementation.cache_tag, version)
|
||||||
|
@ -65,7 +74,7 @@ class AssertionRewritingHook(importlib.abc.MetaPathFinder, importlib.abc.Loader)
|
||||||
def find_spec(self, name, path=None, target=None):
|
def find_spec(self, name, path=None, target=None):
|
||||||
if self._writing_pyc:
|
if self._writing_pyc:
|
||||||
return None
|
return None
|
||||||
state = self.config._assertstate
|
state = self.config._store[assertstate_key]
|
||||||
if self._early_rewrite_bailout(name, state):
|
if self._early_rewrite_bailout(name, state):
|
||||||
return None
|
return None
|
||||||
state.trace("find_module called for: %s" % name)
|
state.trace("find_module called for: %s" % name)
|
||||||
|
@ -104,7 +113,7 @@ class AssertionRewritingHook(importlib.abc.MetaPathFinder, importlib.abc.Loader)
|
||||||
|
|
||||||
def exec_module(self, module):
|
def exec_module(self, module):
|
||||||
fn = Path(module.__spec__.origin)
|
fn = Path(module.__spec__.origin)
|
||||||
state = self.config._assertstate
|
state = self.config._store[assertstate_key]
|
||||||
|
|
||||||
self._rewritten_names.add(module.__name__)
|
self._rewritten_names.add(module.__name__)
|
||||||
|
|
||||||
|
|
|
@ -2,21 +2,28 @@ import os
|
||||||
import platform
|
import platform
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
|
from typing import Any
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
from ..outcomes import fail
|
from ..outcomes import fail
|
||||||
from ..outcomes import TEST_OUTCOME
|
from ..outcomes import TEST_OUTCOME
|
||||||
|
from _pytest.config import Config
|
||||||
|
from _pytest.store import StoreKey
|
||||||
|
|
||||||
|
|
||||||
def cached_eval(config, expr, d):
|
evalcache_key = StoreKey[Dict[str, Any]]()
|
||||||
if not hasattr(config, "_evalcache"):
|
|
||||||
config._evalcache = {}
|
|
||||||
|
def cached_eval(config: Config, expr: str, d: Dict[str, object]) -> Any:
|
||||||
|
default = {} # type: Dict[str, object]
|
||||||
|
evalcache = config._store.setdefault(evalcache_key, default)
|
||||||
try:
|
try:
|
||||||
return config._evalcache[expr]
|
return evalcache[expr]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
import _pytest._code
|
import _pytest._code
|
||||||
|
|
||||||
exprcode = _pytest._code.compile(expr, mode="eval")
|
exprcode = _pytest._code.compile(expr, mode="eval")
|
||||||
config._evalcache[expr] = x = eval(exprcode, d)
|
evalcache[expr] = x = eval(exprcode, d)
|
||||||
return x
|
return x
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,15 @@ class Store:
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return default
|
return default
|
||||||
|
|
||||||
|
def setdefault(self, key: StoreKey[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: StoreKey[T]) -> None:
|
def __delitem__(self, key: StoreKey[T]) -> None:
|
||||||
"""Delete the value for key.
|
"""Delete the value for key.
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,14 @@ def test_store() -> None:
|
||||||
with pytest.raises(KeyError):
|
with pytest.raises(KeyError):
|
||||||
store[key1]
|
store[key1]
|
||||||
|
|
||||||
|
# setdefault
|
||||||
|
store[key1] = "existing"
|
||||||
|
assert store.setdefault(key1, "default") == "existing"
|
||||||
|
assert store[key1] == "existing"
|
||||||
|
key_setdefault = StoreKey[bytes]()
|
||||||
|
assert store.setdefault(key_setdefault, b"default") == b"default"
|
||||||
|
assert store[key_setdefault] == b"default"
|
||||||
|
|
||||||
# Can't accidentally add attributes to store object itself.
|
# Can't accidentally add attributes to store object itself.
|
||||||
with pytest.raises(AttributeError):
|
with pytest.raises(AttributeError):
|
||||||
store.foo = "nope" # type: ignore[attr-defined] # noqa: F821
|
store.foo = "nope" # type: ignore[attr-defined] # noqa: F821
|
||||||
|
|
Loading…
Reference in New Issue