-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy path.importlinter
More file actions
81 lines (75 loc) · 2.98 KB
/
Copy path.importlinter
File metadata and controls
81 lines (75 loc) · 2.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# Import Linter configuration for Adapt
#
# Purpose:
# Enforce architectural boundaries so the codebase stays modular,
# testable, and free of accidental coupling.
#
# Run:
# lint-imports
#
# Philosophy:
# - The layer stack below is the architecture. A package may import only
# packages in layers BELOW its own; siblings on one layer (joined by |)
# are independent and never import each other.
# - `exhaustive = true` means every top-level package under adapt MUST be
# placed in a layer. Adding a new package fails this check until it is
# deliberately assigned a home — that is the point.
# - This file is mirrored in ARCHITECTURE.md; tests/test_architecture.py
# asserts the two stay identical and match the real source tree.
# - Scientific-module independence (adapt.modules.X never imports
# adapt.modules.Y) is enforced by tests/test_architecture.py, which
# auto-discovers module subpackages at runtime.
[importlinter]
root_packages =
adapt
include_external_packages = False
# ==========================================================
# 1. The layer stack
# ==========================================================
#
# cli outermost shell; may import anything
# consumers dashboards/TSE — read ONLY via adapt.api (see contract 2)
# visualization plotting; core never imports it
# runtime composition root: orchestrates everything below
# configuration pydantic schemas + resolution; builds module configs
# api StoreClient read facade over the store
# execution graph + nodes: the one sanctioned wiring layer over modules
# modules science; deterministic; no I/O to the store
# persistence SQLite/NetCDF store; no science, no orchestration
# contracts types + check_* validators; zero adapt imports
# downloaders boto3/S3 isolation; zero adapt imports
# utils shared pure functions; zero adapt imports
[importlinter:contract:layers]
name = Adapt layer stack
type = layers
containers =
adapt
exhaustive = true
layers =
cli
consumers | visualization
runtime
configuration
api | execution
modules | persistence
contracts | downloaders | utils
# ==========================================================
# 2. Consumers speak only through the public API
# ==========================================================
#
# The layer stack alone would let consumers import any lower layer.
# Consumers (dashboard, target selection) must not reach persistence,
# runtime, or execution directly — reaching them THROUGH adapt.api is
# the sanctioned path, hence allow_indirect_imports. StoreClient is the
# only read surface (I/O side doors are closed by
# tests/test_architecture.py::test_consumers_read_only_through_the_store_api).
[importlinter:contract:consumers_use_public_api_only]
name = Consumers do not import persistence, runtime, or execution
type = forbidden
source_modules =
adapt.consumers
forbidden_modules =
adapt.persistence
adapt.runtime
adapt.execution
allow_indirect_imports = True