Skip to content

Commit 235f4a3

Browse files
committed
chore: fix metadata config and add backlog
1 parent b134c0c commit 235f4a3

6 files changed

Lines changed: 157 additions & 7 deletions

File tree

BACKLOG.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Backlog
2+
3+
This backlog merges the existing `TODO.md` items with research findings from `docs/architecture-testing-comparison.md`.
4+
5+
## P0 - Maintenance And Correctness
6+
7+
- Keep package metadata synchronized across `pyproject.toml`, `CHANGELOG.md`, and `src/archunitpython/__init__.py`.
8+
- Keep tool configuration valid for the supported Python range, especially mypy and Ruff target versions.
9+
- Add a release metadata check that fails when the exported `__version__` differs from the project version.
10+
- Add CI jobs that run tests, Ruff, mypy, and a package build from a clean checkout.
11+
12+
## P1 - Adoption Workflow
13+
14+
- Add an `.archignore` or similar file, modeled after `.gitignore`, for files that should never be analyzed.
15+
- Add a `.because(...)` API so rules can carry user-facing rationale into failure messages and generated architecture documentation.
16+
- Add a freeze/baseline mechanism for known violations so teams can adopt ArchUnitPython incrementally.
17+
- Add configuration-file support for common rules, while keeping the fluent Python API as the primary interface.
18+
- Add support for monorepo and multi-package Python projects.
19+
20+
## P1 - Python Import Semantics
21+
22+
- Add support for namespace packages that do not contain `__init__.py`.
23+
- Detect dynamic imports such as `importlib.import_module()` and `__import__()`.
24+
- Detect conditional imports such as `try/except ImportError`.
25+
- Add better `TYPE_CHECKING` import handling, including options to ignore, include, or report type-only imports separately.
26+
- Improve external dependency rules so users can express allowed and forbidden third-party packages at module or slice level.
27+
- Consider a public-interface rule inspired by Tach, where modules may only import through declared package APIs.
28+
29+
## P1 - Reporting And Documentation
30+
31+
- Add comprehensive HTML reports with dependency graphs, metric charts, and zone visualization.
32+
- Auto-generate architecture documentation based on tests and rule rationales.
33+
- Make logged paths clickable in IDEs and common terminal integrations.
34+
- Add PlantUML or Mermaid export for discovered architecture graphs.
35+
- Improve metric export examples and document how metric thresholds should be selected.
36+
37+
## P2 - Rule Surface
38+
39+
- Add first-class layered architecture helpers so common clean/hexagonal/layered rules require less boilerplate.
40+
- Add slice isolation helpers for bounded contexts and modular monoliths.
41+
- Add richer custom rule hooks for dependency edges, files, classes, and metrics.
42+
- Add transitive dependency checks, especially for "domain must not transitively reach infrastructure" style rules.
43+
- Add naming and placement conventions for classes/functions, not only files.
44+
45+
## P2 - Performance And Scale
46+
47+
- Improve performance for very large projects through parallel file parsing.
48+
- Add persistent graph caching with invalidation based on file mtimes or content hashes.
49+
- Add benchmarks for small, medium, large, and monorepo-style projects.
50+
51+
## P2 - Metrics
52+
53+
- Add more LCOM edge case handling.
54+
- Add metric documentation with examples for good, suspicious, and failing values.
55+
- Add trend-friendly metric exports for CI artifacts.
56+
- Consider additional architecture metrics such as coupling counts per slice, fan-in/fan-out summaries, and instability per package.
57+
58+
## P3 - Packaging And Docs
59+
60+
- Publish to PyPI as part of the release pipeline if this is not already automated.
61+
- Add a Sphinx or MkDocs documentation site.
62+
- Add a complete example repository or examples folder covering pytest, unittest, PlantUML, metrics, and CI.
63+
- Add contribution guidance for new rule types and metric implementations.
64+
65+
## Existing TODO Coverage
66+
67+
The previous `TODO.md` items are represented above:
68+
69+
- `.archignore`: P1 Adoption Workflow
70+
- Auto-generated architecture documentation: P1 Reporting And Documentation
71+
- `.because(...)`: P1 Adoption Workflow
72+
- Namespace packages: P1 Python Import Semantics
73+
- Dynamic imports: P1 Python Import Semantics
74+
- Conditional imports: P1 Python Import Semantics
75+
- `TYPE_CHECKING` imports: P1 Python Import Semantics
76+
- Clickable IDE paths: P1 Reporting And Documentation
77+
- Large-project performance: P2 Performance And Scale
78+
- HTML report with charts and zone visualization: P1 Reporting And Documentation
79+
- LCOM edge cases: P2 Metrics
80+
- Monorepo / multi-package support: P1 Adoption Workflow
81+
- Publish to PyPI: P3 Packaging And Docs
82+
- Sphinx/MkDocs documentation site: P3 Packaging And Docs
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Architecture Testing Landscape
2+
3+
Research date: 2026-05-23
4+
5+
This document compares ArchUnitPython with architecture testing tools in the broader ecosystem and with Python-specific alternatives. It focuses on user-facing features that can inform product direction.
6+
7+
## Current ArchUnitPython Position
8+
9+
ArchUnitPython already covers three valuable surfaces:
10+
11+
- File-level architecture rules through `project_files(...)`: dependency direction, cycle detection, naming/path conventions, external dependency checks, and custom file predicates.
12+
- Slice-level architecture rules through `project_slices(...)`: slice extraction from path patterns or regexes, PlantUML diagram adherence, and forbidden slice dependencies.
13+
- Code metrics through `metrics(...)`: count metrics, LCOM variants, abstractness, instability, distance from the main sequence, zone checks, and custom metrics.
14+
15+
That breadth makes the project closer to ArchUnit-style libraries than to pure import linters. The main gaps are around configuration ergonomics, reporting, incremental adoption, IDE/CI workflow polish, and deeper Python import semantics.
16+
17+
## General Architecture Testing Players
18+
19+
| Tool | Ecosystem | Rule definition style | Dependency/layer rules | Cycles | Diagram support | Metrics | Reports/visualization | Notable strengths | ArchUnitPython comparison |
20+
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
21+
| [ArchUnit](https://www.archunit.org/userguide/html/000_Index.html) | Java | Fluent Java API, JUnit integrations | Yes: packages, classes, layers, slices | Yes | PlantUML component diagrams | Yes: software architecture metrics | Strong test failure output; mature JUnit support | Mature reference implementation; broad rule model and advanced adoption features such as freezing/ignoring violations | ArchUnitPython mirrors the core idea and already has files/slices/metrics, but lacks class/member/annotation richness and mature freeze/import options |
22+
| [ArchUnitNET](https://github.com/TNG/ArchUnitNET) | .NET | Fluent C# API with xUnit/NUnit/MSTest integrations | Yes: assemblies, namespaces, types, members | Yes | PlantUML support and diagram generation in the project ecosystem | Limited compared with ArchUnit | Test framework integrations | Strong .NET analogue to ArchUnit with many framework adapters | ArchUnitPython has stronger built-in code metrics, but less type/member-level expressiveness |
23+
| [NetArchTest](https://github.com/BenMorris/NetArchTest) | .NET | Fluent C# API | Yes: namespace/type dependency and conventions | Not a primary differentiator | No first-class PlantUML in core | No | Policy results; test framework agnostic | Simple, widely adopted dependency/convention tests for .NET | ArchUnitPython is broader on cycles, slices, PlantUML, and metrics |
24+
| [ts-arch](https://github.com/ts-arch/ts-arch) | TypeScript/JavaScript | Fluent API, Jest matcher | Yes: files, folders, slices | Yes | PlantUML diagram adherence | No | Jest-oriented failure output | Very close conceptual sibling: file API, slice API, PlantUML, NX monorepo support | ArchUnitPython has a similar surface plus metrics; ts-arch has stronger monorepo/NX positioning |
25+
| [jQAssistant](https://jqassistant.github.io/jqassistant/current/) | Mostly JVM, plugin-based | Scanner + graph database + rule concepts/constraints | Yes, via graph rules and plugins | Yes, rule-dependent | Documentation validation and living documentation workflows | Software analytics via graph queries | Reports, server/explore mode, graph-backed analysis | Enterprise-scale scanning, graph exploration, living documentation, baseline management | ArchUnitPython is much lighter and easier to embed in tests, but lacks graph database exploration and living-doc workflows |
26+
27+
## Python Architecture Testing Libraries
28+
29+
| Tool | Rule definition style | Dependency/layer rules | Cycles | External dependency rules | Diagram support | Metrics | Reports/visualization | Adoption workflow | How ArchUnitPython stacks up |
30+
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
31+
| [ArchUnitPython](https://github.com/LukasNiessen/ArchUnitPython) | Fluent Python API used from pytest/unittest/any test framework | Yes: file dependencies, external modules, slices, forbidden slice dependencies | Yes: file-level cycles | Yes: external module matching | Yes: PlantUML slice adherence | Yes: count, LCOM, distance, custom metrics | Experimental metric export; no full HTML report yet | Plain test functions; `assert_passes()` or `.check()` | Broadest feature mix among the Python tools reviewed, especially because metrics and PlantUML are built in |
32+
| [Import Linter](https://import-linter.readthedocs.io/en/stable/index.html) | `.importlinter` configuration contracts plus CLI | Yes: forbidden, protected, layers, independence, acyclic siblings, custom contracts | Yes: acyclic siblings | Primarily first-party import contracts | No first-class PlantUML | No | Browser-based architecture UI | CLI, CI, config file, caching | More mature for config-driven import contracts and exploration; ArchUnitPython is more test-native and broader on metrics/PlantUML |
33+
| [Tach](https://docs.gauge.sh/getting-started/introduction/) | `tach.toml` plus CLI commands | Yes: module dependencies and public interfaces | Dependency graph focused | Yes: `check-external` for third-party imports | No | No | `show`, `map`, `report`, VS Code integration | Incremental CLI workflow, sync, pre-commit/CI, public interface enforcement | Tach is stronger for modular-boundary workflow and public APIs; ArchUnitPython is stronger for test-suite rules, metrics, and diagram validation |
34+
| [PyTestArch](https://zyskarch.github.io/pytestarch/latest/features/module_import_checks/) | Python query language evaluated in pytest | Yes: module dependency query language and layered architecture rules | Implicit through dependency rules; not positioned as a primary cycle API | Not a main focus | Yes: generates rules from PlantUML component diagrams | No | Optional matplotlib visualization | Pytest-centered evaluation structures | Similar to ArchUnitPython on Python tests and PlantUML; ArchUnitPython has simpler fluent API and built-in metrics |
35+
| [pytest-archon](https://github.com/jwbargsten/pytest-archon) | Pytest-oriented architecture assertions | Yes: forbidden dependencies and project structure rules | Yes, positioned around avoiding cycles | Not a main differentiator | No | No | Pytest failure output | Lightweight pytest helper | ArchUnitPython is broader and more ArchUnit-like; pytest-archon is smaller and focused |
36+
37+
## Product Takeaways
38+
39+
- ArchUnitPython should lean into being the ArchUnit-style Python test library, not just another import linter.
40+
- The nearest feature gap against Python tools is not raw rule breadth; it is workflow: config files, ignore files, public interfaces, incremental adoption, reporting, and IDE/CI polish.
41+
- Against ArchUnit and ArchUnitNET, the biggest long-term gaps are richer semantic model support, better ignore/freeze mechanisms, and mature documentation/reporting.
42+
- Metrics are a meaningful differentiator in the Python space and should be kept visible in docs and examples.
43+
44+
## Sources
45+
46+
- ArchUnit User Guide: https://www.archunit.org/userguide/html/000_Index.html
47+
- ArchUnitNET repository: https://github.com/TNG/ArchUnitNET
48+
- NetArchTest repository: https://github.com/BenMorris/NetArchTest
49+
- ts-arch repository: https://github.com/ts-arch/ts-arch
50+
- jQAssistant User Manual: https://jqassistant.github.io/jqassistant/current/
51+
- Import Linter documentation: https://import-linter.readthedocs.io/en/stable/index.html
52+
- Tach documentation: https://docs.gauge.sh/getting-started/introduction/
53+
- PyTestArch documentation: https://zyskarch.github.io/pytestarch/latest/features/module_import_checks/
54+
- PyTestArch PlantUML documentation: https://zyskarch.github.io/pytestarch/latest/features/plantuml/
55+
- PyTestArch visualization documentation: https://zyskarch.github.io/pytestarch/latest/features/visualization/
56+
- pytest-archon repository: https://github.com/jwbargsten/pytest-archon

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,13 @@ python_classes = ["Test*"]
6767
python_functions = ["test_*"]
6868

6969
[tool.mypy]
70-
python_version = "1.1.0"
70+
python_version = "3.10"
7171
strict = true
7272
warn_return_any = true
7373
warn_unused_configs = true
7474

7575
[tool.ruff]
76-
target-version = "1.1.0"
76+
target-version = "py310"
7777
line-length = 100
7878

7979
[tool.ruff.lint]

src/archunitpython/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""ArchUnitPython - Architecture testing library for Python projects."""
22

3-
__version__ = "1.0.0"
3+
__version__ = "1.1.0"
44

55
# Files API
66
# Common

tests/integration/test_e2e.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@
1010
format_violations,
1111
metrics,
1212
project_files,
13-
project_slices,
1413
)
15-
from archunitpython.common.assertion.violation import EmptyTestViolation
1614
from archunitpython.files.assertion.cycle_free import ViolatingCycle
1715

1816
FIXTURES_DIR = os.path.join(
@@ -54,7 +52,7 @@ def test_import_format_violations(self):
5452
def test_version(self):
5553
import archunitpython
5654

57-
assert archunitpython.__version__ == "1.0.0"
55+
assert archunitpython.__version__ == "1.1.0"
5856

5957

6058
class TestAssertPasses:

tests/test_setup.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,21 @@
11
"""Verify project setup is correct."""
22

3+
import re
4+
from pathlib import Path
5+
36

47
def test_import():
58
import archunitpython
69

7-
assert archunitpython.__version__ == "1.0.0"
10+
assert archunitpython.__version__ == "1.1.0"
11+
12+
13+
def test_project_version_matches_package_version():
14+
import archunitpython
15+
16+
project_root = Path(__file__).resolve().parents[1]
17+
pyproject = (project_root / "pyproject.toml").read_text()
18+
match = re.search(r'^version = "([^"]+)"$', pyproject, re.MULTILINE)
19+
20+
assert match is not None
21+
assert archunitpython.__version__ == match.group(1)

0 commit comments

Comments
 (0)