archetype-py 0.2.3__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {archetype_py-0.2.3 → archetype_py-0.4.0}/.github/workflows/archetype.yml +18 -3
- {archetype_py-0.2.3 → archetype_py-0.4.0}/.github/workflows/ci.yml +10 -1
- {archetype_py-0.2.3 → archetype_py-0.4.0}/.github/workflows/publish.yml +12 -2
- {archetype_py-0.2.3 → archetype_py-0.4.0}/CHANGELOG.md +41 -7
- archetype_py-0.4.0/PKG-INFO +104 -0
- archetype_py-0.4.0/PYPI.md +80 -0
- archetype_py-0.2.3/PKG-INFO → archetype_py-0.4.0/README.md +236 -24
- {archetype_py-0.2.3 → archetype_py-0.4.0}/archetype/__init__.py +1 -2
- {archetype_py-0.2.3 → archetype_py-0.4.0}/archetype/analysis/cache.py +13 -1
- {archetype_py-0.2.3 → archetype_py-0.4.0}/archetype/analysis/git_utils.py +40 -1
- {archetype_py-0.2.3 → archetype_py-0.4.0}/archetype/analysis/imports.py +128 -5
- {archetype_py-0.2.3 → archetype_py-0.4.0}/archetype/analysis/models.py +1 -0
- archetype_py-0.4.0/archetype/analysis/path_filters.py +92 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/archetype/analysis/pattern.py +20 -0
- archetype_py-0.4.0/archetype/baseline.py +186 -0
- archetype_py-0.4.0/archetype/check.py +740 -0
- archetype_py-0.4.0/archetype/config.py +145 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/archetype/dsl/query.py +83 -12
- {archetype_py-0.2.3 → archetype_py-0.4.0}/archetype/reporter.py +93 -3
- {archetype_py-0.2.3 → archetype_py-0.4.0}/archetype/rule.py +85 -63
- {archetype_py-0.2.3 → archetype_py-0.4.0}/archetype/rules/boundaries.py +8 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/archetype/rules/cycles.py +13 -4
- {archetype_py-0.2.3 → archetype_py-0.4.0}/archetype/rules/layers.py +21 -4
- {archetype_py-0.2.3 → archetype_py-0.4.0}/archetype/rules/naming.py +4 -1
- {archetype_py-0.2.3 → archetype_py-0.4.0}/pyproject.toml +2 -2
- archetype_py-0.4.0/tests/fixtures/monorepo_project/libs/shared/src/acme/shared/utils.py +5 -0
- archetype_py-0.4.0/tests/fixtures/monorepo_project/services/billing/src/acme/billing/api.py +7 -0
- archetype_py-0.4.0/tests/fixtures/namespace_project/company/payments/api.py +7 -0
- archetype_py-0.4.0/tests/fixtures/namespace_project/company/shared/utils.py +5 -0
- archetype_py-0.4.0/tests/test_cli.py +1480 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/tests/test_decorator_since.py +10 -2
- {archetype_py-0.2.3 → archetype_py-0.4.0}/tests/test_dsl.py +13 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/tests/test_graph.py +125 -11
- archetype_py-0.4.0/tests/test_public_api.py +12 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/tests/test_reporter.py +113 -1
- {archetype_py-0.2.3 → archetype_py-0.4.0}/tests/test_rules_cycles.py +14 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/tests/test_rules_layers.py +2 -0
- archetype_py-0.2.3/README.md +0 -321
- archetype_py-0.2.3/archetype/check.py +0 -182
- archetype_py-0.2.3/tests/test_cli.py +0 -668
- {archetype_py-0.2.3 → archetype_py-0.4.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/.github/pull_request_template.md +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/.gitignore +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/BENCHMARKS.md +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/CODE_OF_CONDUCT.md +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/CONTRIBUTING.md +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/LICENSE +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/archetype/analysis/__init__.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/archetype/analysis/ast_utils.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/archetype/analysis/init.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/archetype/dsl/__init__.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/archetype/dsl/init.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/archetype/init.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/archetype/plugin/__init__.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/archetype/plugin/init.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/archetype/plugin/pytest_plugin.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/archetype/rules/__init__.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/architecture.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/assets/Pytest.png +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/assets/Rule_Execution_Flow.png +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/assets/Violation_Lifecycle.png +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/assets/architecture.png +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/assets/ci_integration.png +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/assets/logo.png +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/benchmarks/README.md +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/benchmarks/fixtures.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/benchmarks/init.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/benchmarks/run_benchmarks.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/benchmarks/test_performance_regression.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/tests/fixtures/simple_project/.gitignore +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/tests/fixtures/simple_project/simple_project/api.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/tests/fixtures/simple_project/simple_project/db.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/tests/fixtures/simple_project/simple_project/internal/init.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/tests/fixtures/simple_project/simple_project/internal/tokens.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/tests/fixtures/simple_project/simple_project/main.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/tests/fixtures/simple_project/simple_project/services.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/tests/test_grouping.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/tests/test_init.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/tests/test_pattern.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/tests/test_plugin.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/tests/test_rule.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/tests/test_rules_boundaries.py +0 -0
- {archetype_py-0.2.3 → archetype_py-0.4.0}/tests/test_rules_naming.py +0 -0
|
@@ -4,8 +4,13 @@ on:
|
|
|
4
4
|
push:
|
|
5
5
|
branches:
|
|
6
6
|
- main
|
|
7
|
+
tags:
|
|
8
|
+
- "v*"
|
|
7
9
|
pull_request:
|
|
8
10
|
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
9
14
|
jobs:
|
|
10
15
|
archetype:
|
|
11
16
|
runs-on: ubuntu-latest
|
|
@@ -13,7 +18,11 @@ jobs:
|
|
|
13
18
|
steps:
|
|
14
19
|
# Pull down your repository code so CI can inspect it.
|
|
15
20
|
- name: Checkout repository
|
|
16
|
-
uses: actions/checkout@
|
|
21
|
+
uses: actions/checkout@v5
|
|
22
|
+
with:
|
|
23
|
+
token: ${{ github.token }}
|
|
24
|
+
ref: ${{ github.ref }}
|
|
25
|
+
fetch-depth: 0
|
|
17
26
|
|
|
18
27
|
# Install Python 3.11 so the Archetype CLI can run.
|
|
19
28
|
- name: Set up Python
|
|
@@ -28,9 +37,15 @@ jobs:
|
|
|
28
37
|
pip install archetype-py
|
|
29
38
|
|
|
30
39
|
# Run architecture rules defined in architecture.py.
|
|
31
|
-
#
|
|
40
|
+
# If the installed Archetype supports GitHub annotations, emit inline
|
|
41
|
+
# PR annotations. Otherwise, fall back to standard checks.
|
|
32
42
|
- name: Run architecture checks
|
|
33
|
-
run:
|
|
43
|
+
run: |
|
|
44
|
+
if archetype check --help | grep -q -- '--github-annotations'; then
|
|
45
|
+
archetype check . --github-annotations
|
|
46
|
+
else
|
|
47
|
+
archetype check .
|
|
48
|
+
fi
|
|
34
49
|
|
|
35
50
|
# If your team already runs pytest in CI, you can skip this workflow file.
|
|
36
51
|
# Archetype's pytest plugin runs architecture.py rules automatically during pytest.
|
|
@@ -4,8 +4,13 @@ on:
|
|
|
4
4
|
push:
|
|
5
5
|
branches:
|
|
6
6
|
- main
|
|
7
|
+
tags:
|
|
8
|
+
- "v*"
|
|
7
9
|
pull_request:
|
|
8
10
|
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
9
14
|
jobs:
|
|
10
15
|
test:
|
|
11
16
|
runs-on: ubuntu-latest
|
|
@@ -16,7 +21,11 @@ jobs:
|
|
|
16
21
|
|
|
17
22
|
steps:
|
|
18
23
|
- name: Checkout repository
|
|
19
|
-
uses: actions/checkout@
|
|
24
|
+
uses: actions/checkout@v5
|
|
25
|
+
with:
|
|
26
|
+
token: ${{ github.token }}
|
|
27
|
+
ref: ${{ github.ref }}
|
|
28
|
+
fetch-depth: 0
|
|
20
29
|
|
|
21
30
|
- name: Set up Python
|
|
22
31
|
uses: actions/setup-python@v5
|
|
@@ -8,11 +8,17 @@ on:
|
|
|
8
8
|
jobs:
|
|
9
9
|
test:
|
|
10
10
|
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
11
13
|
|
|
12
14
|
steps:
|
|
13
15
|
# Checkout repository contents for test execution.
|
|
14
16
|
- name: Checkout repository
|
|
15
|
-
uses: actions/checkout@
|
|
17
|
+
uses: actions/checkout@v5
|
|
18
|
+
with:
|
|
19
|
+
token: ${{ github.token }}
|
|
20
|
+
ref: ${{ github.ref }}
|
|
21
|
+
fetch-depth: 0
|
|
16
22
|
|
|
17
23
|
# Install Python runtime used for tests and packaging checks.
|
|
18
24
|
- name: Set up Python
|
|
@@ -40,7 +46,11 @@ jobs:
|
|
|
40
46
|
steps:
|
|
41
47
|
# Checkout repository contents so the package can be built.
|
|
42
48
|
- name: Checkout repository
|
|
43
|
-
uses: actions/checkout@
|
|
49
|
+
uses: actions/checkout@v5
|
|
50
|
+
with:
|
|
51
|
+
token: ${{ github.token }}
|
|
52
|
+
ref: ${{ github.ref }}
|
|
53
|
+
fetch-depth: 0
|
|
44
54
|
|
|
45
55
|
# Set up Python for building distribution artifacts.
|
|
46
56
|
- name: Set up Python
|
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0 - 2026-07-05
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- `archetype doctor` command for inspecting detected layout, package roots,
|
|
7
|
+
modules, import edges, config source, excludes, cache status, layers, and
|
|
8
|
+
internal packages.
|
|
9
|
+
- `archetype graph` command for exporting the discovered import graph as
|
|
10
|
+
Mermaid or JSON.
|
|
11
|
+
- Unmatched pattern diagnostics for rule source, target, allowed, layer,
|
|
12
|
+
boundary, cycle, and naming patterns.
|
|
13
|
+
- Pattern suggestions for likely misspellings when a rule pattern matches no
|
|
14
|
+
modules.
|
|
15
|
+
- JSON report schema v2 with violation `file`, `line`, `target`, and per-rule
|
|
16
|
+
`diagnostics` fields.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
- Transitive dependency violations now point to the first import statement in
|
|
20
|
+
the forbidden dependency path.
|
|
21
|
+
- Layering violations now include the source file and line for the offending
|
|
22
|
+
import.
|
|
23
|
+
- Circular import violations now include a source file and line instead of
|
|
24
|
+
reporting `<unknown>`.
|
|
25
|
+
- Rules with unmatched patterns now report as warnings instead of silently
|
|
26
|
+
passing.
|
|
27
|
+
|
|
28
|
+
## 0.3.0 - 2026-05-26
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
- Git pre-commit hook integration via `archetype install-hook`.
|
|
32
|
+
- GitHub PR inline annotations support with `--github-annotations`.
|
|
33
|
+
- Baseline mode for legacy repositories via `--write-baseline` and `--baseline`.
|
|
34
|
+
- Project config defaults through `archetype.toml`.
|
|
35
|
+
- Exclude paths support via CLI (`--exclude`) and config.
|
|
36
|
+
- Versioned JSON contract with explicit `schema_version`.
|
|
37
|
+
- Namespace package and monorepo layout support improvements.
|
|
38
|
+
- Changed-files mode with `--changed-from <git-ref>`.
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
- CI/release workflows expanded to cover new check and packaging behaviors.
|
|
42
|
+
|
|
3
43
|
## 0.1.0 - 2026-05-09
|
|
4
44
|
|
|
5
45
|
### Added
|
|
@@ -48,12 +88,6 @@
|
|
|
48
88
|
## 0.2.3 — 2026-05-16
|
|
49
89
|
|
|
50
90
|
### Added
|
|
51
|
-
- @warn decorator for non-blocking rule violations
|
|
52
|
-
- @skip decorator to temporarily disable rules
|
|
53
|
-
- @since decorator for date-scoped enforcement
|
|
54
|
-
- @rule timeout parameter for pathological graphs
|
|
55
|
-
- Glob pattern support in module matching
|
|
56
|
-
- Rule grouping with group context manager
|
|
57
91
|
- archetype init command for scaffolding
|
|
58
92
|
- --quiet flag to show only failures and warnings
|
|
59
93
|
- --format json flag for machine-readable output
|
|
@@ -67,4 +101,4 @@
|
|
|
67
101
|
- src layout detection in archetype init
|
|
68
102
|
- Verbose violation messages now concise and scannable
|
|
69
103
|
- --quiet flag correctly filters JSON output
|
|
70
|
-
- Naming convention violation message format cleaned up
|
|
104
|
+
- Naming convention violation message format cleaned up
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: archetype-py
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Enforce architectural rules as code. Catch structural violations before they merge.
|
|
5
|
+
Project-URL: Homepage, https://github.com/MossabArektout/archetype-py
|
|
6
|
+
Project-URL: Documentation, https://github.com/MossabArektout/archetype-py
|
|
7
|
+
Author-email: Mossab Arektout <mossabarektout2000@gmail.com>
|
|
8
|
+
License: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
15
|
+
Requires-Python: >=3.11
|
|
16
|
+
Requires-Dist: click
|
|
17
|
+
Requires-Dist: networkx
|
|
18
|
+
Requires-Dist: rich
|
|
19
|
+
Provides-Extra: benchmarks
|
|
20
|
+
Provides-Extra: dev
|
|
21
|
+
Requires-Dist: hatch; extra == 'dev'
|
|
22
|
+
Requires-Dist: pytest; extra == 'dev'
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# archetype-py
|
|
26
|
+
|
|
27
|
+
Enforce architectural rules as code. Catch structural violations before they merge.
|
|
28
|
+
|
|
29
|
+
[GitHub Repository](https://github.com/MossabArektout/archetype-py)
|
|
30
|
+
[Documentation](https://github.com/MossabArektout/archetype-py#readme)
|
|
31
|
+
|
|
32
|
+
## Why archetype-py
|
|
33
|
+
|
|
34
|
+
Most tooling checks formatting, typing, and tests, but not architecture drift.
|
|
35
|
+
`archetype-py` lets you codify structural boundaries and enforce them in local runs, CI, and pytest.
|
|
36
|
+
|
|
37
|
+
## When to use / When not to use
|
|
38
|
+
|
|
39
|
+
Use archetype-py when:
|
|
40
|
+
- You want architecture rules to run automatically in CI and pytest.
|
|
41
|
+
- You need to prevent forbidden imports, layer violations, or import cycles.
|
|
42
|
+
- You are adopting architecture checks incrementally in a legacy codebase (baseline mode).
|
|
43
|
+
|
|
44
|
+
Do not use archetype-py when:
|
|
45
|
+
- You only need style/type checks (linters and type checkers are enough).
|
|
46
|
+
- Your project is a very small script with no meaningful module boundaries.
|
|
47
|
+
- You are looking for runtime policy enforcement instead of static import-graph checks.
|
|
48
|
+
|
|
49
|
+
## Install
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pip install archetype-py
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Quick Start
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
archetype init .
|
|
59
|
+
archetype check .
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Create an `architecture.py` file and define your rules:
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from archetype import rule
|
|
66
|
+
from archetype.rules import layers
|
|
67
|
+
|
|
68
|
+
@rule("layers are ordered")
|
|
69
|
+
def layer_order() -> None:
|
|
70
|
+
layers(["myapp.api", "myapp.services", "myapp.db"]).are_ordered()
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Core Features
|
|
74
|
+
|
|
75
|
+
- Architecture rules for forbidden imports, allowlisted imports, and protected boundaries
|
|
76
|
+
- Transitive dependency checks with `must_not_depend_on`
|
|
77
|
+
- Layer order enforcement with `layers(...).are_ordered()`
|
|
78
|
+
- Import cycle detection with `no_cycles(...)`
|
|
79
|
+
- Rule decorators: `@rule`, `@warn`, `@skip`, `@since`
|
|
80
|
+
- Rule grouping via `group("...")` and targeted execution with `--group`
|
|
81
|
+
- `archetype init` scaffolding for starter `architecture.py`
|
|
82
|
+
- JSON and text reporting (`--format json|text`) with stable JSON contract versioning
|
|
83
|
+
- Quiet output mode (`--quiet`) for CI-friendly logs
|
|
84
|
+
- Import graph caching for faster repeated runs (`--cache`, `--no-cache`)
|
|
85
|
+
- Parallel execution control with `--workers`
|
|
86
|
+
- Baseline adoption for legacy codebases (`--write-baseline`, `--baseline`)
|
|
87
|
+
- Changed-files scope mode (`--changed-from <git-ref>`)
|
|
88
|
+
- GitHub Actions inline PR annotations (`--github-annotations`)
|
|
89
|
+
- Project diagnostics with `archetype doctor`
|
|
90
|
+
- Import graph export with `archetype graph --format mermaid|json`
|
|
91
|
+
- Unmatched pattern warnings with suggestions for likely misspellings
|
|
92
|
+
- Path exclusions via CLI (`--exclude`) and config
|
|
93
|
+
- Project config defaults through `archetype.toml`
|
|
94
|
+
- Git pre-commit hook installer (`archetype install-hook`)
|
|
95
|
+
- Project layout support for flat, `src/`, namespace packages (PEP 420), and monorepos
|
|
96
|
+
- CLI command and pytest plugin support for local and CI enforcement
|
|
97
|
+
|
|
98
|
+
## CI Example
|
|
99
|
+
|
|
100
|
+
```yaml
|
|
101
|
+
- run: archetype check .
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
For full guides, examples, and release notes, use the GitHub README and changelog.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# archetype-py
|
|
2
|
+
|
|
3
|
+
Enforce architectural rules as code. Catch structural violations before they merge.
|
|
4
|
+
|
|
5
|
+
[GitHub Repository](https://github.com/MossabArektout/archetype-py)
|
|
6
|
+
[Documentation](https://github.com/MossabArektout/archetype-py#readme)
|
|
7
|
+
|
|
8
|
+
## Why archetype-py
|
|
9
|
+
|
|
10
|
+
Most tooling checks formatting, typing, and tests, but not architecture drift.
|
|
11
|
+
`archetype-py` lets you codify structural boundaries and enforce them in local runs, CI, and pytest.
|
|
12
|
+
|
|
13
|
+
## When to use / When not to use
|
|
14
|
+
|
|
15
|
+
Use archetype-py when:
|
|
16
|
+
- You want architecture rules to run automatically in CI and pytest.
|
|
17
|
+
- You need to prevent forbidden imports, layer violations, or import cycles.
|
|
18
|
+
- You are adopting architecture checks incrementally in a legacy codebase (baseline mode).
|
|
19
|
+
|
|
20
|
+
Do not use archetype-py when:
|
|
21
|
+
- You only need style/type checks (linters and type checkers are enough).
|
|
22
|
+
- Your project is a very small script with no meaningful module boundaries.
|
|
23
|
+
- You are looking for runtime policy enforcement instead of static import-graph checks.
|
|
24
|
+
|
|
25
|
+
## Install
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pip install archetype-py
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
archetype init .
|
|
35
|
+
archetype check .
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Create an `architecture.py` file and define your rules:
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
from archetype import rule
|
|
42
|
+
from archetype.rules import layers
|
|
43
|
+
|
|
44
|
+
@rule("layers are ordered")
|
|
45
|
+
def layer_order() -> None:
|
|
46
|
+
layers(["myapp.api", "myapp.services", "myapp.db"]).are_ordered()
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Core Features
|
|
50
|
+
|
|
51
|
+
- Architecture rules for forbidden imports, allowlisted imports, and protected boundaries
|
|
52
|
+
- Transitive dependency checks with `must_not_depend_on`
|
|
53
|
+
- Layer order enforcement with `layers(...).are_ordered()`
|
|
54
|
+
- Import cycle detection with `no_cycles(...)`
|
|
55
|
+
- Rule decorators: `@rule`, `@warn`, `@skip`, `@since`
|
|
56
|
+
- Rule grouping via `group("...")` and targeted execution with `--group`
|
|
57
|
+
- `archetype init` scaffolding for starter `architecture.py`
|
|
58
|
+
- JSON and text reporting (`--format json|text`) with stable JSON contract versioning
|
|
59
|
+
- Quiet output mode (`--quiet`) for CI-friendly logs
|
|
60
|
+
- Import graph caching for faster repeated runs (`--cache`, `--no-cache`)
|
|
61
|
+
- Parallel execution control with `--workers`
|
|
62
|
+
- Baseline adoption for legacy codebases (`--write-baseline`, `--baseline`)
|
|
63
|
+
- Changed-files scope mode (`--changed-from <git-ref>`)
|
|
64
|
+
- GitHub Actions inline PR annotations (`--github-annotations`)
|
|
65
|
+
- Project diagnostics with `archetype doctor`
|
|
66
|
+
- Import graph export with `archetype graph --format mermaid|json`
|
|
67
|
+
- Unmatched pattern warnings with suggestions for likely misspellings
|
|
68
|
+
- Path exclusions via CLI (`--exclude`) and config
|
|
69
|
+
- Project config defaults through `archetype.toml`
|
|
70
|
+
- Git pre-commit hook installer (`archetype install-hook`)
|
|
71
|
+
- Project layout support for flat, `src/`, namespace packages (PEP 420), and monorepos
|
|
72
|
+
- CLI command and pytest plugin support for local and CI enforcement
|
|
73
|
+
|
|
74
|
+
## CI Example
|
|
75
|
+
|
|
76
|
+
```yaml
|
|
77
|
+
- run: archetype check .
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
For full guides, examples, and release notes, use the GitHub README and changelog.
|
|
@@ -1,27 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: archetype-py
|
|
3
|
-
Version: 0.2.3
|
|
4
|
-
Summary: Enforce architectural rules as code. Catch structural violations before they merge.
|
|
5
|
-
Project-URL: Homepage, https://github.com/MossabArektout/archetype-py
|
|
6
|
-
Project-URL: Documentation, https://github.com/MossabArektout/archetype-py
|
|
7
|
-
Author-email: Mossab Arektout <mossabarektout2000@gmail.com>
|
|
8
|
-
License: MIT
|
|
9
|
-
License-File: LICENSE
|
|
10
|
-
Classifier: Development Status :: 3 - Alpha
|
|
11
|
-
Classifier: Intended Audience :: Developers
|
|
12
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
-
Classifier: Programming Language :: Python :: 3
|
|
14
|
-
Classifier: Topic :: Software Development :: Quality Assurance
|
|
15
|
-
Requires-Python: >=3.11
|
|
16
|
-
Requires-Dist: click
|
|
17
|
-
Requires-Dist: networkx
|
|
18
|
-
Requires-Dist: rich
|
|
19
|
-
Provides-Extra: benchmarks
|
|
20
|
-
Provides-Extra: dev
|
|
21
|
-
Requires-Dist: hatch; extra == 'dev'
|
|
22
|
-
Requires-Dist: pytest; extra == 'dev'
|
|
23
|
-
Description-Content-Type: text/markdown
|
|
24
|
-
|
|
25
1
|
[](https://pypi.org/project/archetype-py/)
|
|
26
2
|
[](https://pypi.org/project/archetype-py/)
|
|
27
3
|
[](https://github.com/MossabArektout/archetype-py/blob/main/LICENSE)
|
|
@@ -40,6 +16,7 @@ Description-Content-Type: text/markdown
|
|
|
40
16
|
- [Minimum `architecture.py` Example](#minimum-architecturepy-example)
|
|
41
17
|
- [Features](#features)
|
|
42
18
|
- [Decorators and Commands](#decorators-and-commands)
|
|
19
|
+
- [Baseline Mode](#baseline-mode)
|
|
43
20
|
- [Perfect For](#perfect-for)
|
|
44
21
|
- [Installation](#installation)
|
|
45
22
|
- [Build & Test](#build--test)
|
|
@@ -229,11 +206,24 @@ def no_import_cycles() -> None:
|
|
|
229
206
|
- Import cycle detection
|
|
230
207
|
- Protected module boundaries
|
|
231
208
|
|
|
209
|
+
### Project Layout Support
|
|
210
|
+
- Flat package layouts
|
|
211
|
+
- Single `src/` layouts
|
|
212
|
+
- Namespace packages (PEP 420, without `__init__.py`)
|
|
213
|
+
- Monorepos with multiple `src` roots
|
|
214
|
+
|
|
232
215
|
### Workflow Features
|
|
233
216
|
- Rule grouping
|
|
234
217
|
- Warning-level rules
|
|
235
218
|
- Temporary rule skips with context
|
|
236
219
|
- Changed-file enforcement (`since`)
|
|
220
|
+
- Legacy baseline snapshot/suppression (`--write-baseline`, `--baseline`)
|
|
221
|
+
- Diff-scoped checks (`--changed-from <ref>`)
|
|
222
|
+
- Project diagnostics (`archetype doctor`)
|
|
223
|
+
- Import graph export (`archetype graph --format mermaid|json`)
|
|
224
|
+
- Unmatched pattern warnings with suggestions
|
|
225
|
+
- First-class project config defaults (`archetype.toml`)
|
|
226
|
+
- Path exclusions (`--exclude`, `archetype.toml`, legacy `[tool.archetype].exclude`)
|
|
237
227
|
- Pytest integration
|
|
238
228
|
- CI-friendly exit codes
|
|
239
229
|
|
|
@@ -251,13 +241,232 @@ Rules are written in `architecture.py` with decorators. Below are all decorator-
|
|
|
251
241
|
|
|
252
242
|
Decorator order tip: place `@rule(...)` first, then wrappers like `@warn`, `@skip`, or `@since`.
|
|
253
243
|
|
|
244
|
+
### `@since` Date Format
|
|
245
|
+
|
|
246
|
+
`@since(...)` only accepts ISO calendar dates in `YYYY-MM-DD` format. The
|
|
247
|
+
decorator validates this when `architecture.py` is loaded, so invalid values
|
|
248
|
+
raise a clear `ValueError` instead of being ignored.
|
|
249
|
+
|
|
250
|
+
```python
|
|
251
|
+
@since("2026-01-01") # valid
|
|
252
|
+
def recent_violations_only() -> None:
|
|
253
|
+
...
|
|
254
|
+
|
|
255
|
+
@since("01-01-2026") # invalid: expected YYYY-MM-DD
|
|
256
|
+
def ambiguous_date() -> None:
|
|
257
|
+
...
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Invalid dates show the expectation in the error message:
|
|
261
|
+
|
|
262
|
+
```text
|
|
263
|
+
Invalid date '01-01-2026'. Expected format: YYYY-MM-DD.
|
|
264
|
+
```
|
|
265
|
+
|
|
254
266
|
| Command | Description | Example |
|
|
255
267
|
|---|---|---|
|
|
256
268
|
| `archetype init [path]` | Detects project structure and generates a starter `architecture.py` file. | `archetype init .` |
|
|
257
269
|
| `archetype check [path]` | Loads `architecture.py` and runs all registered architecture rules. | `archetype check .` |
|
|
258
270
|
| `archetype check [path] --group <name>` | Runs only rules that belong to the specified group. | `archetype check . --group core` |
|
|
271
|
+
| `archetype check [path] --exclude <pattern>` | Excludes paths from analysis and reporting (repeatable). | `archetype check . --exclude /vendor/ --exclude /migrations/` |
|
|
272
|
+
| `archetype check [path] --write-baseline <file> --baseline <file>` | Writes a baseline snapshot and suppresses matching legacy violations so only new ones fail. | `archetype check . --baseline archetype-baseline.json` |
|
|
273
|
+
| `archetype check [path] --changed-from <ref>` | Limits reported violations to files changed since `<ref>` (branch name or commit SHA). | `archetype check . --changed-from origin/main` |
|
|
274
|
+
| `archetype check [path] --github-annotations` | Emits GitHub Actions inline annotations (`::error`/`::warning`) for PR diffs. | `archetype check . --github-annotations` |
|
|
275
|
+
| `archetype doctor [path]` | Shows detected layout, package roots, modules, import edges, config, cache status, and architecture file status. | `archetype doctor .` |
|
|
276
|
+
| `archetype graph [path] --format mermaid\|json` | Exports the discovered local import graph for docs, debugging, or integrations. | `archetype graph . --format mermaid` |
|
|
277
|
+
| `archetype install-hook [path]` | Installs (or updates) a managed git pre-commit hook that runs `archetype check` before each commit. | `archetype install-hook .` |
|
|
278
|
+
|
|
279
|
+
### Diagnostics
|
|
280
|
+
|
|
281
|
+
When a rule does not behave as expected, inspect what Archetype sees:
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
archetype doctor .
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
To inspect or document module dependencies, export the import graph:
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
archetype graph . --format mermaid
|
|
291
|
+
archetype graph . --format json
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
If a source, target, layer, boundary, cycle, or naming pattern matches no
|
|
295
|
+
modules, Archetype reports a warning with likely suggestions instead of letting
|
|
296
|
+
the rule silently pass.
|
|
297
|
+
|
|
298
|
+
### Excluding Paths
|
|
299
|
+
|
|
300
|
+
Exclude noisy folders such as generated code, migrations, or vendored dependencies:
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
archetype check . --exclude /vendor/ --exclude /migrations/
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
You can also define defaults in `archetype.toml`:
|
|
307
|
+
|
|
308
|
+
```toml
|
|
309
|
+
exclude = ["/vendor/", "/migrations/"]
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
Legacy compatibility: if `archetype.toml` is missing, Archetype still reads
|
|
313
|
+
`[tool.archetype]` from `pyproject.toml`.
|
|
314
|
+
|
|
315
|
+
### Project Config (`archetype.toml`)
|
|
316
|
+
|
|
317
|
+
Archetype auto-discovers `archetype.toml` in the project root passed to
|
|
318
|
+
`archetype check [path]`.
|
|
319
|
+
|
|
320
|
+
Supported defaults:
|
|
321
|
+
|
|
322
|
+
- `format` (`"text"` or `"json"`)
|
|
323
|
+
- `quiet` (`true`/`false`)
|
|
324
|
+
- `group` (`string`)
|
|
325
|
+
- `exclude` (`string` or `string[]`)
|
|
326
|
+
- `workers` (`int >= 1`)
|
|
327
|
+
- `cache` (`true`/`false`)
|
|
328
|
+
|
|
329
|
+
Example:
|
|
330
|
+
|
|
331
|
+
```toml
|
|
332
|
+
format = "json"
|
|
333
|
+
quiet = true
|
|
334
|
+
group = "Layer boundaries"
|
|
335
|
+
exclude = ["/vendor/", "/migrations/"]
|
|
336
|
+
workers = 4
|
|
337
|
+
cache = true
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
Precedence:
|
|
341
|
+
|
|
342
|
+
- CLI flags override `archetype.toml`.
|
|
343
|
+
- `archetype.toml` overrides built-in defaults.
|
|
344
|
+
- If config is missing, behavior remains unchanged.
|
|
345
|
+
|
|
346
|
+
### Pre-commit Hook
|
|
347
|
+
|
|
348
|
+
Install a git pre-commit hook in one command:
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
archetype install-hook .
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
Behavior:
|
|
355
|
+
|
|
356
|
+
- Creates `.git/hooks/pre-commit` if missing.
|
|
357
|
+
- Appends an Archetype-managed block if a custom pre-commit hook already exists.
|
|
358
|
+
- Updates the managed block if Archetype already installed it.
|
|
359
|
+
- Blocks the commit when `archetype check` fails, and prints violations directly in the commit terminal output.
|
|
360
|
+
|
|
361
|
+
### Changed-files Mode
|
|
362
|
+
|
|
363
|
+
Use diff scope to speed up checks in large repositories:
|
|
364
|
+
|
|
365
|
+
```bash
|
|
366
|
+
archetype check . --changed-from origin/main
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
`<ref>` can be a branch name (for example `origin/main`) or a commit SHA.
|
|
370
|
+
|
|
371
|
+
When enabled:
|
|
372
|
+
- Text output shows a scope banner with mode, ref, and changed file count.
|
|
373
|
+
- JSON output includes a `scope` object with mode/ref/file metadata.
|
|
374
|
+
|
|
375
|
+
### GitHub PR Annotations
|
|
376
|
+
|
|
377
|
+
Use GitHub Actions annotations to surface violations directly on PR diff lines:
|
|
259
378
|
|
|
379
|
+
```bash
|
|
380
|
+
archetype check . --github-annotations
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
In GitHub Actions, these appear as inline file/line annotations for each violation
|
|
384
|
+
while preserving the normal non-zero exit code when checks fail.
|
|
385
|
+
|
|
386
|
+
## Baseline Mode
|
|
387
|
+
|
|
388
|
+
Use baseline mode to adopt archetype in legacy repos without failing on pre-existing violations.
|
|
260
389
|
|
|
390
|
+
Create a baseline snapshot:
|
|
391
|
+
|
|
392
|
+
```bash
|
|
393
|
+
archetype check . --write-baseline archetype-baseline.json
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
Run checks against that baseline (matching old violations are suppressed):
|
|
397
|
+
|
|
398
|
+
```bash
|
|
399
|
+
archetype check . --baseline archetype-baseline.json
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
You can combine with JSON output to track counts:
|
|
403
|
+
|
|
404
|
+
```bash
|
|
405
|
+
archetype check . --baseline archetype-baseline.json --format json
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
JSON output includes:
|
|
409
|
+
- `schema_version`: top-level contract version for machine consumers
|
|
410
|
+
- `summary`: rule-level pass/fail/warn/skip counts
|
|
411
|
+
- `violations.total`: total current violations before suppression
|
|
412
|
+
- `violations.new`: violations not found in the baseline
|
|
413
|
+
- `violations.suppressed`: violations matched and suppressed by baseline
|
|
414
|
+
|
|
415
|
+
### JSON Contract (Versioned)
|
|
416
|
+
|
|
417
|
+
Archetype JSON output is versioned for CI and other integrations.
|
|
418
|
+
|
|
419
|
+
Current contract version:
|
|
420
|
+
|
|
421
|
+
- `schema_version: 1`
|
|
422
|
+
|
|
423
|
+
Versioning policy:
|
|
424
|
+
|
|
425
|
+
- Non-breaking additions (for example new optional fields) keep the same `schema_version`.
|
|
426
|
+
- Breaking shape changes (rename/remove/type changes) must increment `schema_version`.
|
|
427
|
+
- Contract tests in CI enforce the current schema shape.
|
|
428
|
+
|
|
429
|
+
Field definitions:
|
|
430
|
+
|
|
431
|
+
- `schema_version` (`int`): machine-readable contract version.
|
|
432
|
+
- `summary` (`object`): counts by rule status.
|
|
433
|
+
- `violations` (`object`): aggregate violation counts.
|
|
434
|
+
- `rules` (`array`): per-rule results with status and violations.
|
|
435
|
+
- `scope` (`object`, optional): present when `--changed-from` is used.
|
|
436
|
+
|
|
437
|
+
Example (`--format json`):
|
|
438
|
+
|
|
439
|
+
```json
|
|
440
|
+
{
|
|
441
|
+
"schema_version": 1,
|
|
442
|
+
"summary": {
|
|
443
|
+
"passed": 2,
|
|
444
|
+
"failed": 1,
|
|
445
|
+
"warned": 0,
|
|
446
|
+
"skipped": 0,
|
|
447
|
+
"total": 3
|
|
448
|
+
},
|
|
449
|
+
"violations": {
|
|
450
|
+
"total": 1,
|
|
451
|
+
"new": 1,
|
|
452
|
+
"suppressed": 0
|
|
453
|
+
},
|
|
454
|
+
"rules": [
|
|
455
|
+
{
|
|
456
|
+
"name": "api-must-not-import-db",
|
|
457
|
+
"status": "failed",
|
|
458
|
+
"group": "core",
|
|
459
|
+
"since_date": null,
|
|
460
|
+
"violations": [
|
|
461
|
+
{
|
|
462
|
+
"module": "simple_project.api",
|
|
463
|
+
"message": "Module 'simple_project.api' must not import 'simple_project.db'"
|
|
464
|
+
}
|
|
465
|
+
]
|
|
466
|
+
}
|
|
467
|
+
]
|
|
468
|
+
}
|
|
469
|
+
```
|
|
261
470
|
|
|
262
471
|
## Perfect For
|
|
263
472
|
|
|
@@ -298,6 +507,8 @@ archetype check .
|
|
|
298
507
|
- `0`: no blocking failures (passes and warnings only)
|
|
299
508
|
- `1`: one or more blocking rule failures
|
|
300
509
|
|
|
510
|
+
When `--baseline` is used, exit code `1` means there are **new** blocking violations not present in the baseline.
|
|
511
|
+
|
|
301
512
|
---
|
|
302
513
|
|
|
303
514
|
## Troubleshooting
|
|
@@ -306,6 +517,7 @@ archetype check .
|
|
|
306
517
|
- Rules seem to do nothing: confirm your rules are decorated with `@rule("...")`; undecorated functions are not registered.
|
|
307
518
|
- `@since(...)` behavior is unexpected: verify the date format is `YYYY-MM-DD` and that your git history is available in the checked path.
|
|
308
519
|
- Import path mismatches: use fully qualified module paths (`myapp.api`, not file paths like `src/api.py`).
|
|
520
|
+
- Namespace package imports not showing up: ensure modules live under discovered package roots (repo root, top-level `src/`, or nested monorepo `*/src` roots).
|
|
309
521
|
|
|
310
522
|
---
|
|
311
523
|
|