Disable caching when evaluating expressions in marks (#7373)
This commit is contained in:
parent
b6fd89ef31
commit
a67c553beb
|
@ -0,0 +1,2 @@
|
|||
Fix possibly incorrect evaluation of string expressions passed to ``pytest.mark.skipif`` and ``pytest.mark.xfail``,
|
||||
in rare circumstances where the exact same string is used but refers to different global values.
|
|
@ -10,25 +10,14 @@ from typing import Optional
|
|||
from ..outcomes import fail
|
||||
from ..outcomes import TEST_OUTCOME
|
||||
from .structures import Mark
|
||||
from _pytest.config import Config
|
||||
from _pytest.nodes import Item
|
||||
from _pytest.store import StoreKey
|
||||
|
||||
|
||||
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 evalcache[expr]
|
||||
except KeyError:
|
||||
def compiled_eval(expr: str, d: Dict[str, object]) -> Any:
|
||||
import _pytest._code
|
||||
|
||||
exprcode = _pytest._code.compile(expr, mode="eval")
|
||||
evalcache[expr] = x = eval(exprcode, d)
|
||||
return x
|
||||
return eval(exprcode, d)
|
||||
|
||||
|
||||
class MarkEvaluator:
|
||||
|
@ -98,7 +87,7 @@ class MarkEvaluator:
|
|||
self.expr = expr
|
||||
if isinstance(expr, str):
|
||||
d = self._getglobals()
|
||||
result = cached_eval(self.item.config, expr, d)
|
||||
result = compiled_eval(expr, d)
|
||||
else:
|
||||
if "reason" not in mark.kwargs:
|
||||
# XXX better be checked at collection time
|
||||
|
|
|
@ -706,6 +706,36 @@ class TestFunctional:
|
|||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(skipped=1)
|
||||
|
||||
def test_reevaluate_dynamic_expr(self, testdir):
|
||||
"""#7360"""
|
||||
py_file1 = testdir.makepyfile(
|
||||
test_reevaluate_dynamic_expr1="""
|
||||
import pytest
|
||||
|
||||
skip = True
|
||||
|
||||
@pytest.mark.skipif("skip")
|
||||
def test_should_skip():
|
||||
assert True
|
||||
"""
|
||||
)
|
||||
py_file2 = testdir.makepyfile(
|
||||
test_reevaluate_dynamic_expr2="""
|
||||
import pytest
|
||||
|
||||
skip = False
|
||||
|
||||
@pytest.mark.skipif("skip")
|
||||
def test_should_not_skip():
|
||||
assert True
|
||||
"""
|
||||
)
|
||||
|
||||
file_name1 = os.path.basename(py_file1.strpath)
|
||||
file_name2 = os.path.basename(py_file2.strpath)
|
||||
reprec = testdir.inline_run(file_name1, file_name2)
|
||||
reprec.assertoutcome(passed=1, skipped=1)
|
||||
|
||||
|
||||
class TestKeywordSelection:
|
||||
def test_select_simple(self, testdir):
|
||||
|
|
Loading…
Reference in New Issue