r/PythonProgramming • u/127001-sweet-127001 • 2h ago
Should an architecture test count imports inside TYPE_CHECKING?
Consider this in src/app/domain/pricing.py:
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from app.adapters.store import Store
def price(store: Store):
return 12The adapter isn't imported by that guarded block at runtime. But the domain still names Store, and moving or renaming that type can still require changing the domain code.
So whether this should fail an architecture test depends on the policy you're trying to enforce. If domain code mustn't know about adapters at all, the type-only edge matters. If you're deliberately allowing those annotations while checking the other imports, you need to exclude it explicitly.
In ArchUnitPython, which I work on, imports inside TYPE_CHECKING count by default. The same boundary can be checked with them excluded:
from archunitpython import CheckOptions, assert_passes, project_files
rule = (
project_files("src")
.in_path("**/domain/**")
.should_not()
.depend_on_files()
.in_path("**/adapters/**")
)
assert_passes(
rule,
CheckOptions(ignore_type_checking_imports=True),
)That passes for the snippet above. Move the Store import outside the guard and it fails again, even with the option enabled. Without the option, the guarded version fails too.
A small distinction with quite different consequences
I would choose the policy first, rather than switch the option on just to make a failing test green. This is still static import analysis; excluding typing guards doesn't turn it into a trace of everything Python will execute.
ArchUnitPython source. Free, MIT-licensed; the example works with archunitpython==1.8.1.