Merge pull request #6865 from bluetech/more-config-store

Convert a couple of places to use config store
This commit is contained in:
Ran Benita 2020-03-06 15:49:01 +02:00 committed by GitHub
commit 1df593f978
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 47 additions and 13 deletions

View File

@ -7,6 +7,7 @@ from typing import Optional
from _pytest.assertion import rewrite
from _pytest.assertion import truncate
from _pytest.assertion import util
from _pytest.assertion.rewrite import assertstate_key
from _pytest.compat import TYPE_CHECKING
from _pytest.config import hookimpl
@ -82,13 +83,13 @@ class AssertionState:
def install_importhook(config):
"""Try to install the rewrite hook, raise SystemError if it fails."""
config._assertstate = AssertionState(config, "rewrite")
config._assertstate.hook = hook = rewrite.AssertionRewritingHook(config)
config._store[assertstate_key] = AssertionState(config, "rewrite")
config._store[assertstate_key].hook = hook = rewrite.AssertionRewritingHook(config)
sys.meta_path.insert(0, hook)
config._assertstate.trace("installed rewrite import hook")
config._store[assertstate_key].trace("installed rewrite import hook")
def undo():
hook = config._assertstate.hook
hook = config._store[assertstate_key].hook
if hook is not None and hook in sys.meta_path:
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
# so for example not in the master process of pytest-xdist
# (which does not collect test modules)
assertstate = getattr(session.config, "_assertstate", None)
assertstate = session.config._store.get(assertstate_key, None)
if assertstate:
if assertstate.hook is not None:
assertstate.hook.set_session(session)
@ -163,7 +164,7 @@ def pytest_runtest_protocol(item):
def pytest_sessionfinish(session):
assertstate = getattr(session.config, "_assertstate", None)
assertstate = session.config._store.get(assertstate_key, None)
if assertstate:
if assertstate.hook is not None:
assertstate.hook.set_session(None)

View File

@ -26,9 +26,18 @@ from _pytest.assertion.util import ( # noqa: F401
format_explanation as _format_explanation,
)
from _pytest.compat import fspath
from _pytest.compat import TYPE_CHECKING
from _pytest.pathlib import fnmatch_ex
from _pytest.pathlib import Path
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_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):
if self._writing_pyc:
return None
state = self.config._assertstate
state = self.config._store[assertstate_key]
if self._early_rewrite_bailout(name, state):
return None
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):
fn = Path(module.__spec__.origin)
state = self.config._assertstate
state = self.config._store[assertstate_key]
self._rewritten_names.add(module.__name__)

View File

@ -2,21 +2,28 @@ import os
import platform
import sys
import traceback
from typing import Any
from typing import Dict
from ..outcomes import fail
from ..outcomes import TEST_OUTCOME
from _pytest.config import Config
from _pytest.store import StoreKey
def cached_eval(config, expr, d):
if not hasattr(config, "_evalcache"):
config._evalcache = {}
evalcache_key = StoreKey[Dict[str, Any]]()
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:
return config._evalcache[expr]
return evalcache[expr]
except KeyError:
import _pytest._code
exprcode = _pytest._code.compile(expr, mode="eval")
config._evalcache[expr] = x = eval(exprcode, d)
evalcache[expr] = x = eval(exprcode, d)
return x

View File

@ -104,6 +104,15 @@ class Store:
except KeyError:
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:
"""Delete the value for key.

View File

@ -37,6 +37,14 @@ def test_store() -> None:
with pytest.raises(KeyError):
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.
with pytest.raises(AttributeError):
store.foo = "nope" # type: ignore[attr-defined] # noqa: F821