Skip to content

Commit a67c553

Browse files
authored
Disable caching when evaluating expressions in marks (#7373)
1 parent b6fd89e commit a67c553

File tree

3 files changed

+37
-16
lines changed

3 files changed

+37
-16
lines changed

changelog/7360.bugfix.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix possibly incorrect evaluation of string expressions passed to ``pytest.mark.skipif`` and ``pytest.mark.xfail``,
2+
in rare circumstances where the exact same string is used but refers to different global values.

src/_pytest/mark/evaluate.py

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,14 @@
1010
from ..outcomes import fail
1111
from ..outcomes import TEST_OUTCOME
1212
from .structures import Mark
13-
from _pytest.config import Config
1413
from _pytest.nodes import Item
15-
from _pytest.store import StoreKey
1614

1715

18-
evalcache_key = StoreKey[Dict[str, Any]]()
16+
def compiled_eval(expr: str, d: Dict[str, object]) -> Any:
17+
import _pytest._code
1918

20-
21-
def cached_eval(config: Config, expr: str, d: Dict[str, object]) -> Any:
22-
default = {} # type: Dict[str, object]
23-
evalcache = config._store.setdefault(evalcache_key, default)
24-
try:
25-
return evalcache[expr]
26-
except KeyError:
27-
import _pytest._code
28-
29-
exprcode = _pytest._code.compile(expr, mode="eval")
30-
evalcache[expr] = x = eval(exprcode, d)
31-
return x
19+
exprcode = _pytest._code.compile(expr, mode="eval")
20+
return eval(exprcode, d)
3221

3322

3423
class MarkEvaluator:
@@ -98,7 +87,7 @@ def _istrue(self) -> bool:
9887
self.expr = expr
9988
if isinstance(expr, str):
10089
d = self._getglobals()
101-
result = cached_eval(self.item.config, expr, d)
90+
result = compiled_eval(expr, d)
10291
else:
10392
if "reason" not in mark.kwargs:
10493
# XXX better be checked at collection time

testing/test_mark.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,36 @@ def test_1(parameter):
706706
reprec = testdir.inline_run()
707707
reprec.assertoutcome(skipped=1)
708708

709+
def test_reevaluate_dynamic_expr(self, testdir):
710+
"""#7360"""
711+
py_file1 = testdir.makepyfile(
712+
test_reevaluate_dynamic_expr1="""
713+
import pytest
714+
715+
skip = True
716+
717+
@pytest.mark.skipif("skip")
718+
def test_should_skip():
719+
assert True
720+
"""
721+
)
722+
py_file2 = testdir.makepyfile(
723+
test_reevaluate_dynamic_expr2="""
724+
import pytest
725+
726+
skip = False
727+
728+
@pytest.mark.skipif("skip")
729+
def test_should_not_skip():
730+
assert True
731+
"""
732+
)
733+
734+
file_name1 = os.path.basename(py_file1.strpath)
735+
file_name2 = os.path.basename(py_file2.strpath)
736+
reprec = testdir.inline_run(file_name1, file_name2)
737+
reprec.assertoutcome(passed=1, skipped=1)
738+
709739

710740
class TestKeywordSelection:
711741
def test_select_simple(self, testdir):

0 commit comments

Comments
 (0)