Skip to content

Commit ce42ba8

Browse files
Add secondary AST import-helper usage guard
Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent a83410b commit ce42ba8

9 files changed

Lines changed: 112 additions & 15 deletions

CONTRIBUTING.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ This runs lint, format checks, compile checks, tests, and package build.
100100
- `tests/test_ast_import_utils_module_import_boundary.py` (shared AST import-helper module import boundary enforcement across test modules),
101101
- `tests/test_ast_module_import_helper_import_boundary.py` (shared AST module-import helper import boundary enforcement across test modules),
102102
- `tests/test_ast_module_import_helper_usage.py` (shared AST module-import helper usage enforcement across AST boundary guard suites),
103+
- `tests/test_ast_secondary_import_helper_usage.py` (shared AST secondary import-helper usage enforcement across AST boundary guard suites),
103104
- `tests/test_ast_symbol_import_helper_import_boundary.py` (shared AST symbol-import helper import boundary enforcement across test modules),
104105
- `tests/test_ast_symbol_import_helper_usage.py` (shared AST symbol-import helper usage enforcement across AST boundary guard suites),
105106
- `tests/test_binary_file_open_helper_usage.py` (shared binary file open helper usage enforcement),

tests/ast_import_utils.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,11 @@ def imports_imports_collect_function_sources(module_text: str) -> bool:
5252
module="tests.ast_import_utils",
5353
symbol="imports_collect_function_sources",
5454
)
55+
56+
57+
def imports_imports_imports_collect_function_sources(module_text: str) -> bool:
58+
return imports_symbol_from_module(
59+
module_text,
60+
module="tests.ast_import_utils",
61+
symbol="imports_imports_collect_function_sources",
62+
)

tests/test_architecture_marker_usage.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"tests/test_ast_import_utils_module_import_boundary.py",
3030
"tests/test_ast_module_import_helper_import_boundary.py",
3131
"tests/test_ast_module_import_helper_usage.py",
32+
"tests/test_ast_secondary_import_helper_usage.py",
3233
"tests/test_ast_symbol_import_helper_import_boundary.py",
3334
"tests/test_ast_symbol_import_helper_usage.py",
3435
"tests/test_guardrail_ast_utils.py",

tests/test_ast_call_symbol_helper_usage.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"tests/test_ast_function_source_helper_usage.py",
1212
"tests/test_ast_import_helper_usage.py",
1313
"tests/test_ast_module_import_helper_usage.py",
14+
"tests/test_ast_secondary_import_helper_usage.py",
1415
"tests/test_ast_symbol_import_helper_usage.py",
1516
)
1617

tests/test_ast_import_helper_secondary_import_boundary.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22

33
import pytest
44

5-
from tests.ast_import_utils import imports_symbol_from_module
5+
from tests.ast_import_utils import imports_imports_imports_collect_function_sources
6+
from tests.test_ast_secondary_import_helper_usage import (
7+
AST_SECONDARY_IMPORT_GUARD_MODULES,
8+
)
69

710
pytestmark = pytest.mark.architecture
811

912

10-
EXPECTED_SECONDARY_AST_IMPORT_HELPER_IMPORTERS = (
11-
"tests/test_ast_import_helper_import_boundary.py",
12-
"tests/test_ast_import_helper_usage.py",
13+
EXPECTED_EXTRA_IMPORTERS = (
1314
"tests/test_ast_import_utils.py",
1415
)
1516

@@ -18,12 +19,9 @@ def test_secondary_ast_import_helper_imports_are_centralized():
1819
discovered_modules: list[str] = []
1920
for module_path in sorted(Path("tests").glob("test_*.py")):
2021
module_text = module_path.read_text(encoding="utf-8")
21-
if not imports_symbol_from_module(
22-
module_text,
23-
module="tests.ast_import_utils",
24-
symbol="imports_imports_collect_function_sources",
25-
):
22+
if not imports_imports_imports_collect_function_sources(module_text):
2623
continue
2724
discovered_modules.append(module_path.as_posix())
2825

29-
assert discovered_modules == list(EXPECTED_SECONDARY_AST_IMPORT_HELPER_IMPORTERS)
26+
expected_modules = sorted([*AST_SECONDARY_IMPORT_GUARD_MODULES, *EXPECTED_EXTRA_IMPORTERS])
27+
assert discovered_modules == expected_modules

tests/test_ast_import_utils.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
calls_symbol,
55
imports_collect_function_sources,
66
imports_from_module,
7+
imports_imports_imports_collect_function_sources,
78
imports_imports_collect_function_sources,
89
imports_symbol_from_module,
910
)
@@ -174,6 +175,42 @@ def test_imports_imports_collect_function_sources_ignores_non_from_imports():
174175
assert imports_imports_collect_function_sources(module_text) is False
175176

176177

178+
def test_imports_imports_imports_collect_function_sources_detects_expected_import():
179+
module_text = (
180+
"from tests.ast_import_utils import imports_imports_collect_function_sources\n"
181+
"imports_imports_collect_function_sources('dummy')\n"
182+
)
183+
184+
assert imports_imports_imports_collect_function_sources(module_text) is True
185+
186+
187+
def test_imports_imports_imports_collect_function_sources_ignores_non_matching_imports():
188+
module_text = (
189+
"from tests.ast_import_utils import imports_collect_function_sources\n"
190+
"imports_collect_function_sources('dummy')\n"
191+
)
192+
193+
assert imports_imports_imports_collect_function_sources(module_text) is False
194+
195+
196+
def test_imports_imports_imports_collect_function_sources_supports_aliased_import():
197+
module_text = (
198+
"from tests.ast_import_utils import imports_imports_collect_function_sources as helper\n"
199+
"helper('dummy')\n"
200+
)
201+
202+
assert imports_imports_imports_collect_function_sources(module_text) is True
203+
204+
205+
def test_imports_imports_imports_collect_function_sources_ignores_non_from_imports():
206+
module_text = (
207+
"import tests.ast_import_utils as import_utils\n"
208+
"import_utils.imports_imports_collect_function_sources('dummy')\n"
209+
)
210+
211+
assert imports_imports_imports_collect_function_sources(module_text) is False
212+
213+
177214
def test_calls_symbol_detects_direct_function_call():
178215
module_text = (
179216
"from tests.ast_function_source_utils import collect_function_sources\n"

tests/test_ast_import_utils_module_import_boundary.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
from tests.ast_import_utils import imports_from_module
66
from tests.test_ast_call_symbol_helper_usage import AST_CALL_SYMBOL_GUARD_MODULES
7-
from tests.test_ast_import_helper_secondary_import_boundary import (
8-
EXPECTED_SECONDARY_AST_IMPORT_HELPER_IMPORTERS,
9-
)
107
from tests.test_ast_import_helper_usage import AST_IMPORT_GUARD_MODULES
8+
from tests.test_ast_secondary_import_helper_usage import (
9+
AST_SECONDARY_IMPORT_GUARD_MODULES,
10+
)
1111

1212
pytestmark = pytest.mark.architecture
1313

@@ -19,6 +19,7 @@
1919
"tests/test_ast_import_helper_secondary_import_boundary.py",
2020
"tests/test_ast_module_import_helper_import_boundary.py",
2121
"tests/test_ast_module_import_helper_usage.py",
22+
"tests/test_ast_secondary_import_helper_usage.py",
2223
"tests/test_ast_symbol_import_helper_import_boundary.py",
2324
"tests/test_ast_symbol_import_helper_usage.py",
2425
"tests/test_ast_import_utils.py",
@@ -38,7 +39,7 @@ def test_ast_import_utils_imports_are_centralized():
3839
{
3940
*AST_IMPORT_GUARD_MODULES,
4041
*AST_CALL_SYMBOL_GUARD_MODULES,
41-
*EXPECTED_SECONDARY_AST_IMPORT_HELPER_IMPORTERS,
42+
*AST_SECONDARY_IMPORT_GUARD_MODULES,
4243
*EXPECTED_EXTRA_IMPORTERS,
4344
}
4445
)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
from pathlib import Path
2+
3+
import pytest
4+
5+
from tests.ast_import_utils import (
6+
calls_symbol,
7+
imports_imports_imports_collect_function_sources,
8+
)
9+
10+
pytestmark = pytest.mark.architecture
11+
12+
13+
AST_SECONDARY_IMPORT_GUARD_MODULES = (
14+
"tests/test_ast_import_helper_import_boundary.py",
15+
"tests/test_ast_import_helper_usage.py",
16+
)
17+
18+
19+
def test_ast_secondary_import_guard_modules_reuse_shared_helper():
20+
violating_modules: list[str] = []
21+
for module_path in AST_SECONDARY_IMPORT_GUARD_MODULES:
22+
module_text = Path(module_path).read_text(encoding="utf-8")
23+
if not imports_imports_imports_collect_function_sources(module_text):
24+
violating_modules.append(module_path)
25+
continue
26+
if not calls_symbol(module_text, "imports_imports_collect_function_sources"):
27+
violating_modules.append(module_path)
28+
continue
29+
if "def _imports_imports_collect_function_sources" in module_text:
30+
violating_modules.append(module_path)
31+
32+
assert violating_modules == []
33+
34+
35+
def test_ast_secondary_import_guard_inventory_stays_in_sync():
36+
excluded_modules = {
37+
"tests/test_ast_import_helper_secondary_import_boundary.py",
38+
"tests/test_ast_import_utils.py",
39+
"tests/test_ast_secondary_import_helper_usage.py",
40+
}
41+
discovered_modules: list[str] = []
42+
for module_path in sorted(Path("tests").glob("test_*.py")):
43+
normalized_path = module_path.as_posix()
44+
if normalized_path in excluded_modules:
45+
continue
46+
module_text = module_path.read_text(encoding="utf-8")
47+
if not imports_imports_imports_collect_function_sources(module_text):
48+
continue
49+
discovered_modules.append(normalized_path)
50+
51+
assert sorted(AST_SECONDARY_IMPORT_GUARD_MODULES) == discovered_modules

tests/test_ast_symbol_import_helper_usage.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
AST_SYMBOL_IMPORT_GUARD_MODULES = (
1111
"tests/test_ast_call_symbol_helper_import_boundary.py",
1212
"tests/test_ast_call_symbol_helper_usage.py",
13-
"tests/test_ast_import_helper_secondary_import_boundary.py",
1413
"tests/test_ast_import_helper_usage.py",
1514
"tests/test_ast_module_import_helper_import_boundary.py",
1615
)

0 commit comments

Comments
 (0)