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