fix: resolve cross-module import violations with lazy import pattern

- Convert core→optional imports to lazy imports with try/except fallbacks
- cms/media_service: use TYPE_CHECKING for ProductMedia type hints
- customers/customer_service: wrap Order imports in try/except
- tenancy/admin_platform_users: wrap stats_service import in try/except
- Enhance validate_architecture.py to recognize lazy import patterns
- Add module_dependency_graph.py script for dependency visualization

The lazy import pattern allows optional modules to be truly optional while
maintaining type safety through TYPE_CHECKING blocks.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-04 19:22:11 +01:00
parent 5afc0fdfae
commit 37942ae02b
5 changed files with 574 additions and 40 deletions

View File

@@ -4541,6 +4541,9 @@ class ArchitectureValidator:
# Track if we're inside a docstring
in_docstring = False
docstring_delimiter = None
# Track if we're inside a TYPE_CHECKING block
in_type_checking = False
type_checking_indent = 0
for i, line in enumerate(lines, 1):
# Skip comments and empty lines
@@ -4571,9 +4574,37 @@ class ArchitectureValidator:
if in_docstring:
continue
# Skip TYPE_CHECKING blocks (these are fine for type hints)
if "TYPE_CHECKING" in line:
# Track TYPE_CHECKING blocks
current_indent = len(line) - len(line.lstrip())
if "if TYPE_CHECKING:" in stripped or "if TYPE_CHECKING" in stripped:
in_type_checking = True
type_checking_indent = current_indent
continue
# Exit TYPE_CHECKING block when we see code at same or lower indentation
if in_type_checking and current_indent <= type_checking_indent and stripped:
in_type_checking = False
# Skip lines inside TYPE_CHECKING blocks (these are fine for type hints)
if in_type_checking:
continue
# Skip lazy imports inside try/except blocks
# These are the approved pattern for cross-module imports
# Check if line is indented (inside function) and look for nearby try:
if stripped.startswith(("from ", "import ")) and line.startswith(" "):
# Check previous few lines for try: at same or lower indentation
current_indent = len(line) - len(line.lstrip())
is_lazy_import = False
for lookback in range(1, min(10, i)):
prev_line = lines[i - lookback - 1]
prev_stripped = prev_line.strip()
prev_indent = len(prev_line) - len(prev_line.lstrip())
if prev_stripped.startswith("try:") and prev_indent < current_indent:
# This is a lazy import inside a try block - skip it
is_lazy_import = True
break
if is_lazy_import:
continue
# Look for import statements
import_match = re.match(