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 compiled_eval(expr: str, d: Dict[str, object]) -> Any:
 | 
			
		||||
    import _pytest._code
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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:
 | 
			
		||||
        import _pytest._code
 | 
			
		||||
 | 
			
		||||
        exprcode = _pytest._code.compile(expr, mode="eval")
 | 
			
		||||
        evalcache[expr] = x = eval(exprcode, d)
 | 
			
		||||
        return x
 | 
			
		||||
    exprcode = _pytest._code.compile(expr, mode="eval")
 | 
			
		||||
    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