forked from pytest-dev/pytest
-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
bugSomething isn't workingSomething isn't working
Description
User Request
Pytest crashes the interpreter on Python debug builds for 3.8+ when compiling mark expressions that contain certain identifiers.
Short reproducer:
>>> Expression.compile("False")
python: Python/compile.c:3559: compiler_nameop: Assertion `!_PyUnicode_EqualToASCIIString(name, "None") && !_PyUnicode_EqualToASCIIString(name, "True") && !_PyUnicode_EqualToASCIIString(name, "False")' failed.
[1] 29440 abort (core dumped) pythonRelated upstream: bpo-40870 — https://bugs.python.org/issue40870
Researcher Specification
Root cause: mark expression parsing builds an AST using ast.Name nodes for identifiers, including the special names "True", "False", and "None". On CPython debug builds (3.8+), compiling such an AST triggers an assertion in compiler_nameop because these are meant to be literal constants, not names.
Proposed fix:
- Add
_ident_to_name(name: str) -> ast.exprinsrc/_pytest/compat.pythat:- For "True"/"False"/"None": returns a literal constant node —
ast.Constanton Python >= 3.8;ast.NameConstanton Python < 3.8. - For any other identifier: returns
ast.Name(name, ast.Load()).
- For "True"/"False"/"None": returns a literal constant node —
- Update
src/_pytest/mark/expression.pyto:- Use
_ident_to_name("False")as the default for an empty expression (instead ofast.NameConstant(False)). - Use
_ident_to_name(ident.value)wherever identifiers are turned into AST nodes (instead ofast.Name(...)).
- Use
Compatibility notes:
- Aligns literals with Python semantics across versions (3.4–3.7 use
ast.NameConstant; 3.8+ useast.Constant). - Slight behavior change: exact identifiers "True", "False", and "None" now behave as literals and are not resolved through the matcher. Lowercase variants remain identifiers.
Observed Failure / Stack Trace
- As above, CPython debug build (3.8+) assertion failure in
compiler_nameopwhen compiling an expression containing "False" (applies similarly to "True"/"None").
Reproduction Steps
- Use a CPython debug build (3.8+):
python-dbgor equivalent. - Run:
from _pytest.mark.expression import Expression
Expression.compile("False")- Prior behavior: crashes with an assertion as shown above.
- Expected behavior after fix: compiles cleanly; evaluating should yield
False.
Testing Plan
- Add tests asserting that "True"/"False"/"None" are treated as literals and not looked up in the matcher.
- Ensure lowercase variants (e.g., "true") remain identifiers.
- Optional: version-aware structural checks to confirm AST node types (
ast.Constantvsast.NameConstant).
Links
- CPython: https://bugs.python.org/issue40870
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working