test: two-pass import validation so binding order cannot matter
pytest raises aliases are collected across the whole file FIRST, then every competing import (wherever it appears, even before the genuine binding) is rejected - closing the reversed-order spoof
This commit is contained in:
+24
-21
@@ -666,38 +666,41 @@ def test_dao_matrix_test_file_raw_probes_are_only_constraint_probes() -> None:
|
|||||||
NotIntegrityError and fake.IntegrityError fail).
|
NotIntegrityError and fake.IntegrityError fail).
|
||||||
"""
|
"""
|
||||||
# Names bound to pytest's raises: parse the FILE's actual
|
# Names bound to pytest's raises: parse the FILE's actual
|
||||||
# Import nodes. A bare Name('raises') is trusted only when
|
# Import nodes in TWO passes so order cannot matter — pass
|
||||||
# an alias binds it from the pytest module; ANY other import
|
# one collects every binding pytest's raises gets (whatever
|
||||||
# (Import or ImportFrom) binding 'raises', 'pytest', or any
|
# alias), pass two rejects ANY competing binding of those
|
||||||
# raises alias from a non-pytest module fails closed, so a
|
# names (or of 'pytest' itself) from a non-pytest import,
|
||||||
# spoofed module or shadowed alias cannot defeat the check.
|
# wherever it appears. A spoof imported BEFORE the genuine
|
||||||
raises_bindings: set[str] = set()
|
# binding therefore still fails.
|
||||||
|
pytest_raises_aliases: set[str] = set()
|
||||||
|
for file_node in ast.walk(tree):
|
||||||
|
if (
|
||||||
|
isinstance(file_node, ast.ImportFrom)
|
||||||
|
and file_node.module == "pytest"
|
||||||
|
):
|
||||||
|
for alias in file_node.names:
|
||||||
|
if alias.name == "raises":
|
||||||
|
pytest_raises_aliases.add(
|
||||||
|
alias.asname or alias.name
|
||||||
|
)
|
||||||
|
raises_bindings: set[str] = set(pytest_raises_aliases)
|
||||||
for file_node in ast.walk(tree):
|
for file_node in ast.walk(tree):
|
||||||
if isinstance(file_node, ast.ImportFrom):
|
if isinstance(file_node, ast.ImportFrom):
|
||||||
if file_node.module == "pytest":
|
if file_node.module == "pytest":
|
||||||
for alias in file_node.names:
|
continue
|
||||||
if alias.name == "raises":
|
|
||||||
raises_bindings.add(
|
|
||||||
alias.asname or alias.name
|
|
||||||
)
|
|
||||||
# Any ImportFrom binding the guarded names from a
|
|
||||||
# non-pytest module fails closed.
|
|
||||||
for alias in file_node.names:
|
for alias in file_node.names:
|
||||||
bound = alias.asname or alias.name
|
bound = alias.asname or alias.name
|
||||||
if (
|
if bound in raises_bindings | {"pytest"}:
|
||||||
bound in raises_bindings | {"pytest"}
|
|
||||||
and file_node.module != "pytest"
|
|
||||||
):
|
|
||||||
raise AssertionError(
|
raise AssertionError(
|
||||||
f"shadowed import of {bound!r} from "
|
f"shadowed import of {bound!r} from "
|
||||||
f"{file_node.module!r} defeats the "
|
f"{file_node.module!r} defeats the "
|
||||||
"pytest.raises probe validation"
|
"pytest.raises probe validation"
|
||||||
)
|
)
|
||||||
elif isinstance(file_node, ast.Import):
|
elif isinstance(file_node, ast.Import):
|
||||||
# import fake_module as pytest (or as anything the
|
# import fake_module as pytest (or as any raises
|
||||||
# raises machinery trusts) fails closed. A plain
|
# alias) fails closed. A plain `import pytest`
|
||||||
# `import pytest` (alias.name == 'pytest', no asname)
|
# (alias.name == 'pytest', no asname) is the genuine
|
||||||
# is the genuine module binding and is allowed.
|
# module binding and is allowed.
|
||||||
for alias in file_node.names:
|
for alias in file_node.names:
|
||||||
bound = alias.asname or alias.name
|
bound = alias.asname or alias.name
|
||||||
genuine_pytest = (
|
genuine_pytest = (
|
||||||
|
|||||||
Reference in New Issue
Block a user