PyPI / pytest / 9.1.1

pytest 9.1.1

Source
https://github.com/pytest-dev/pytest
Artifact scanned
pytest-9.1.1-py3-none-any.whl (wheel · 377.5 KB · SHA-256 37a86b45efb9…)
Compared with
pytest-9.1.0-py3-none-any.whl (0 signals introduced since)
Files
83 scanned, 6 skipped (binary, oversized, or unrecognised)
Signals
0 critical · 0 warn · 20 info
Scan time
17.7 s
LLM review
Reviewed by claude-haiku-5-5 (Anthropic): 20 of 20 warn and critical signals; 20 demoted to info.
Disclude version
4.3.0
Scanned (UTC)
2026-10-23 00:09

Signals

Ordered by severity, then signals introduced in this release. Hidden characters are shown as ⟨U+…⟩.

  1. info warn → info by review dynamic-execution _pytest/_code/code.py:173:16

    `eval` called on a non-literal expression (ast pass, confidence 0.70)

            f_locals.update(vars)
            return eval(code, self.f_globals, f_locals)
    
        def repr(self, object: object) -> str:
    likely benign LLM, confidence 0.90 Evaluates an expression in a captured frame context for pytest's code-inspection repr.
    Reasoning

    This eval runs a pytest expression against a frame's globals and locals, as used when rendering or repr-ing values in tracebacks. The expression comes from pytest's own code path, not from untrusted input, so this is a legitimate use of eval.

  2. info critical → info by review dynamic-import _pytest/_py/path.py:626:23

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

                        hashtype = "sha"
                    mod = __import__(hashtype)
                hash = getattr(mod, hashtype)()
            except (AttributeError, ImportError):
    likely benign LLM, confidence 0.92 Dynamically imports a hashlib-style module by name to compute a file hash.
    Reasoning

    The module name comes from a fixed set of hash type names such as 'sha' or 'md5', chosen from a small internal list, and the result is used to compute a file checksum. This is an ordinary dynamic import of a standard hashing module.

  3. info critical → info by review dynamic-import _pytest/_py/path.py:1118:13

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

                self._ensuresyspath(ensuresyspath, pkgroot)
                __import__(modname)
                mod = sys.modules[modname]
                if self.basename == "__init__.py":
    likely benign LLM, confidence 0.90 Imports the module corresponding to a Python file during pyimport.
    Reasoning

    This is the pyimport helper, which imports a module by its computed dotted name from a package root so the file can be loaded as a module. Dynamic import by name is the expected mechanism here.

  4. info warn → info by review decoder-import-with-exec _pytest/_py/path.py:1153:25

    file imports decoder module(s) pickle and calls `exec`/`eval`/`compile` — multi-stage payload shape (ast pass, confidence 0.80)

                        with open(str(self), "rb") as f:
                            exec(f.read(), mod.__dict__)
                    except BaseException:
                        del sys.modules[modname]
    likely benign LLM, confidence 0.85 Reads a module's source file and executes it into the module namespace during pyimport.
    Reasoning

    This is the py.path pyimport fallback that reads the module's source file and executes it into the module's namespace. Executing a module's own source is what importing a file means. The decoder-import signal fires on a pattern, not on any decoding or payload behaviour, and the file being read is the module under import.

  5. info warn → info by review dynamic-execution _pytest/_py/path.py:1153:25

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

                        with open(str(self), "rb") as f:
                            exec(f.read(), mod.__dict__)
                    except BaseException:
                        del sys.modules[modname]
    likely benign LLM, confidence 0.85 Executes a module file's contents into its namespace during pyimport.
    Reasoning

    This is the same exec of a module's own file contents into its __dict__ during pyimport. It is the normal behaviour of loading a Python file as a module.

  6. info warn → info by review decoder-import-with-exec _pytest/assertion/rewrite.py:188:9

    file imports decoder module(s) marshal and calls `exec`/`eval`/`compile` — multi-stage payload shape (ast pass, confidence 0.80)

                state.trace(f"found cached rewritten pyc for {fn}")
            exec(co, module.__dict__)
    
        def _early_rewrite_bailout(self, name: str, state: AssertionState) -> bool:
    likely benign LLM, confidence 0.92 Executes a cached rewritten code object into a test module during assertion-rewrite import.
    Reasoning

    This executes the cached rewritten code object into the module's dictionary, which is how pytest's assertion-rewriting import hook loads test modules. The bytecode is produced locally by pytest's own rewriter or read from its pyc cache, so the marshal/exec pattern is the expected import mechanism.

  7. info warn → info by review dynamic-execution _pytest/assertion/rewrite.py:188:9

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

                state.trace(f"found cached rewritten pyc for {fn}")
            exec(co, module.__dict__)
    
        def _early_rewrite_bailout(self, name: str, state: AssertionState) -> bool:
    likely benign LLM, confidence 0.92 Runs the rewritten test module code object in the module namespace.
    Reasoning

    This is the same exec of the rewritten code object into the module namespace, the standard step of pytest's import hook. The code originates from pytest's own compilation of the test source.

  8. info warn → info by review dynamic-execution _pytest/assertion/rewrite.py:350:10

    `compile` called on a non-literal expression (ast pass, confidence 0.70)

        rewrite_asserts(tree, source, strfn, config)
        co = compile(tree, strfn, "exec", dont_inherit=True)
        return stat, co
    likely benign LLM, confidence 0.93 Compiles the assertion-rewritten AST of a test module into a code object.
    Reasoning

    This compiles an AST that pytest's assertion rewriter produced from the test source it is loading. Compiling a rewritten AST is the core of the rewrite hook.

  9. info warn → info by review dynamic-execution _pytest/assertion/rewrite.py:393:18

    `marshal.load` deserializes Python bytecode from bytes — code-object sink (ast pass, confidence 0.75)

            try:
                co = marshal.load(fp)
            except Exception as e:
                trace(f"_read_pyc({source}): marshal.load error {e}")
    likely benign LLM, confidence 0.90 Loads a cached pytest rewrite .pyc via marshal to reuse compiled test bytecode.
    Reasoning

    This reads a pytest-generated .pyc cache file via marshal.load, with error handling and a trace message. Reading a local bytecode cache is ordinary behaviour for the rewrite hook, and nothing here fetches or decodes an external payload.

  10. info critical → info by review dynamic-import _pytest/config/__init__.py:917:17

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

                    # testing/test_config.py::test_disable_plugin_autoload.
                    __import__(importspec)
                    mod = sys.modules[importspec]
            except ImportError as e:
    likely benign LLM, confidence 0.90 Imports a pytest plugin module by its configured import spec.
    Reasoning

    This imports a plugin module named by a configuration spec, such as an entry point or the -p option, and then looks it up in sys.modules. Dynamic plugin import is the expected pytest plugin-loading mechanism.

  11. info warn → info by review frame-introspection _pytest/config/__init__.py:1657:21

    `sys._getframe` — call-stack frame introspection (ast pass, confidence 0.70)

            if records:
                frame = sys._getframe(stacklevel - 1)
                location = frame.f_code.co_filename, frame.f_lineno, frame.f_code.co_name
                self.hook.pytest_warning_recorded.call_historic(
    likely benign LLM, confidence 0.95 Reads the caller's frame location to attach to a recorded pytest warning.
    Reasoning

    This walks the caller's stack frame to record the file and line for a warning. Frame introspection with sys._getframe is routine for warning-location reporting.

  12. info warn → info by review frame-introspection _pytest/debugging.py:281:17

    `sys._getframe` — call-stack frame introspection (ast pass, confidence 0.70)

            """Invoke debugging via ``Pdb.set_trace``, dropping any IO capturing."""
            frame = sys._getframe().f_back
            _pdb = cls._init_pdb("set_trace", *args, **kwargs)
            _pdb.set_trace(frame)
    likely benign LLM, confidence 0.95 Gets the caller's frame so pytest's pdb set_trace starts at the right location.
    Reasoning

    This takes the caller's frame so the pdb debugger can start at the test location, which is the standard pytest breakpoint behaviour. It is interactive debugging support, not stealthy execution.

  13. info warn → info by review frame-introspection _pytest/fixtures.py:745:21

    `inspect.stack` — call-stack frame introspection (ast pass, confidence 0.70)

            if has_params:
                frame = inspect.stack()[3]
                frameinfo = inspect.getframeinfo(frame[0])
                source_path = absolutepath(frameinfo.filename)
    likely benign LLM, confidence 0.93 Inspects the call stack to find the source location of a fixture definition.
    Reasoning

    This uses inspect.stack to locate the source file and line of a fixture's definition for reporting and caching keys. It is a common, local introspection pattern in pytest's fixture machinery.

  14. info warn → info by review dynamic-execution _pytest/mark/expression.py:333:16

    `compile` called on a non-literal expression (ast pass, confidence 0.70)

            astexpr = expression(Scanner(input))
            code = compile(
                astexpr,
                filename="<pytest match expression>",
    likely benign LLM, confidence 0.94 Compiles a parsed pytest -k/-m match expression into a code object.
    Reasoning

    This compiles the AST of a -k or -m match expression that the user supplies on the command line, using a fixed filename. Compiling a parsed match expression is the intended behaviour.

  15. info warn → info by review dynamic-execution _pytest/mark/expression.py:353:21

    `eval` called on a non-literal expression (ast pass, confidence 0.70)

            """
            return bool(eval(self._code, {"__builtins__": {}}, MatcherAdapter(matcher)))
    likely benign LLM, confidence 0.90 Evaluates a pytest mark-selection expression with restricted builtins.
    Reasoning

    This is pytest's mark expression evaluator, which compiles a user-supplied -k/-m boolean expression and evaluates it with empty builtins and a restricted matcher adapter. It is a documented, intentional feature of pytest, not obfuscation or malicious intent.

  16. info warn → info by review dynamic-execution _pytest/outcomes.py:249:5

    `compile` called on a non-literal expression (ast pass, confidence 0.70)

        __tracebackhide__ = True
        compile(modname, "", "eval")  # to catch syntaxerrors
    
        # Keep the public signature compatible while using the pytest 9.1 default behavior.
    likely benign LLM, confidence 0.85 Syntax-checks a module name via compile to surface SyntaxErrors in importorskip.
    Reasoning

    compile(modname, '', 'eval') is a syntax-validation check on a module name string, a common pattern in pytest's importorskip to catch syntax errors. The result is discarded and nothing is executed.

  17. info critical → info by review frame-introspection _pytest/pytester.py:290:27

    `sys._getframe` — call-stack frame introspection — file also calls `sys.exit`/`exec`/`eval` (anti-analysis shape) (ast pass, confidence 0.85)

            # Since Python 3.13, f_locals is not a dict, but eval requires a dict.
            backlocals = dict(sys._getframe(1).f_locals)
            while entries:
                name, check = entries.pop(0)
    likely benign LLM, confidence 0.85 Captures caller frame locals to evaluate check expressions in the pytester test helper.
    Reasoning

    sys._getframe(1).f_locals is used to capture the caller's locals so that pytester's assert_outcomes-style checks can be evaluated as expressions. This is test-framework introspection, and the 'anti-analysis' label is a heuristic match on co-occurrence with eval/exit in a large test utility file, not evidence of evasion.

  18. info warn → info by review dynamic-execution _pytest/pytester.py:296:24

    `eval` called on a non-literal expression (ast pass, confidence 0.70)

                        print("NAMEMATCH", name, call)
                        if eval(check, backlocals, call.__dict__):
                            print("CHECKERMATCH", repr(check), "->", call)
                        else:
    likely benign LLM, confidence 0.85 Evaluates test-authored check expressions against parsed call attributes in pytester.
    Reasoning

    eval(check, backlocals, call.__dict__) evaluates check expressions supplied by the test author within pytester's LineMatcher/ParsedCall checking helper. This is developer-facing test tooling operating on test-authored strings, not an attack path.

  19. info warn → info by review dynamic-execution _pytest/skipping.py:118:30

    `compile` called on a non-literal expression (ast pass, confidence 0.70)

                filename = f"<{mark.name} condition>"
                condition_code = compile(condition, filename, "eval")
                result = eval(condition_code, globals_)
            except SyntaxError as exc:
    likely benign LLM, confidence 0.90 Compiles the skipif condition string from a pytest marker for evaluation.
    Reasoning

    pytest's skipif marker compiles the user-provided condition string and evaluates it with the module's globals. This is the documented skipif(condition-string) feature and is expected behavior for a test framework.

  20. info warn → info by review dynamic-execution _pytest/skipping.py:119:22

    `eval` called on a non-literal expression (ast pass, confidence 0.70)

                condition_code = compile(condition, filename, "eval")
                result = eval(condition_code, globals_)
            except SyntaxError as exc:
                msglines = [
    likely benign LLM, confidence 0.90 Evaluates the compiled skipif/xfail condition string within pytest's skipping logic.
    Reasoning

    The eval of the compiled condition is the same documented string-condition feature of pytest skipif/xfail markers. The code is in a try block that handles SyntaxError to produce a readable error, consistent with legitimate framework code.

Reproduce This Scan

Run disclude locally to verify. These commands scan the published file; the "new in this release" marks come from comparing it with the previous release's file, which they don't repeat. Add --format sarif for SARIF output. Add --llm (with an API key in the environment) to include the LLM review.

cargo install disclude --version 4.3.0
curl -fsSL -o pytest-9.1.1-py3-none-any.whl https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl
printf '%s  %s\n' 37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c pytest-9.1.1-py3-none-any.whl | shasum -a 256 -c -
unzip -q pytest-9.1.1-py3-none-any.whl -d pkg
disclude scan --untrusted --severity info pkg