Coupling
coupling
Coupling helpers — graph algorithms and config parsing.
Public-internal API: the eight non-underscore functions below are stable
enough to be imported directly by tests within this package. They are
not re-exported in the package root __all__ because they are tools
for rule authors, not application code.
build_coupling_result(fan_out, fan_in, threshold, overrides=None, *, orchestrator_bonus=0, imports_map=None, src_path=None, severity_error_multiplier=_COUPLING_DEFAULT_SEVERITY_MULTIPLIER)
Compute coupling summary from fan-out / fan-in metrics.
Classifies each over-threshold module as "warning" or "error"
based on severity_error_multiplier: fan-out above
effective_threshold * severity_error_multiplier is an error,
otherwise a warning.
Returns a dict with keys max_fan_out, max_fan_in,
avg_coupling, n_over_threshold, and over_threshold
(list of dicts with module, fan_out, role,
effective_threshold, severity).
Source code in packages/axm-audit/src/axm_audit/core/rules/architecture/coupling.py
classify_module_role(module_name, imports, src_path)
Classify a module as "orchestrator" or "leaf".
A module is an orchestrator if it imports from >= 3 distinct sibling subpackages within the project namespace. Only intra-project imports are considered (external/stdlib imports are ignored).
Source code in packages/axm-audit/src/axm_audit/core/rules/architecture/coupling.py
extract_imports(tree)
Extract module-level imported module names from an AST.
Only scans top-level imports to avoid false positives from lazy/deferred imports inside functions (which don't cause circular import issues at runtime).
Counts source modules, not individual imported symbols. For example,
from foo import A, B counts as a single import of foo.
__future__ imports are excluded — they are language directives,
not real dependencies.
Source code in packages/axm-audit/src/axm_audit/core/rules/architecture/coupling.py
parse_overrides(raw)
Parse an overrides mapping, silently dropping invalid entries.
Source code in packages/axm-audit/src/axm_audit/core/rules/architecture/coupling.py
read_coupling_config(project_path)
Read coupling thresholds from [tool.axm-audit.coupling] in pyproject.toml.
Returns:
| Type | Description |
|---|---|
int
|
``(fan_out_threshold, overrides, orchestrator_bonus, |
dict[str, int]
|
severity_error_multiplier)`` — falls back to defaults on any error. |
Source code in packages/axm-audit/src/axm_audit/core/rules/architecture/coupling.py
safe_int(value, default)
Convert value to a non-negative int, returning default on failure.
Source code in packages/axm-audit/src/axm_audit/core/rules/architecture/coupling.py
strip_prefix(modules)
Strip the common top-level package prefix from module names.
All modules in a detected cycle belong to the same package (the graph
only contains modules under src/). Removing the shared prefix
cuts token count by ~49% with zero information loss.
Source code in packages/axm-audit/src/axm_audit/core/rules/architecture/coupling.py
tarjan_scc(graph)
Find strongly connected components using iterative Tarjan's algorithm.
Uses an explicit call stack instead of recursion to avoid hitting Python's recursion limit on large graphs (>1000 modules).