Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions BACKLOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ This backlog collects product and maintenance ideas from project research.
## P1 - Python Import Semantics

- Add support for namespace packages that do not contain `__init__.py`.
- Detect dynamic imports such as `importlib.import_module()` and `__import__()`.
- [x] Detect dynamic imports such as `importlib.import_module()` and `__import__()`.
- Detect conditional imports such as `try/except ImportError`.
- Add better `TYPE_CHECKING` import handling, including options to ignore, include, or report type-only imports separately.
- Improve external dependency rules so users can express allowed and forbidden third-party packages at module or slice level.
Expand All @@ -30,12 +30,12 @@ This backlog collects product and maintenance ideas from project research.
- Add comprehensive HTML reports with dependency graphs, metric charts, and zone visualization.
- Auto-generate architecture documentation based on tests and rule rationales.
- Make logged paths clickable in IDEs and common terminal integrations.
- Add PlantUML or Mermaid export for discovered architecture graphs.
- [x] Add PlantUML or Mermaid export for discovered architecture graphs.
- Improve metric export examples and document how metric thresholds should be selected.

## P2 - Rule Surface

- Add first-class layered architecture helpers so common clean/hexagonal/layered rules require less boilerplate.
- [x] Add first-class layered architecture helpers so common clean/hexagonal/layered rules require less boilerplate.
- Add slice isolation helpers for bounded contexts and modular monoliths.
- Add richer custom rule hooks for dependency edges, files, classes, and metrics.
- Add transitive dependency checks, especially for "domain must not transitively reach infrastructure" style rules.
Expand All @@ -56,7 +56,7 @@ This backlog collects product and maintenance ideas from project research.

## P3 - Packaging And Docs

- Publish to PyPI as part of the release pipeline if this is not already automated.
- [x] Publish to PyPI as part of the release pipeline if this is not already automated.
- Add a Sphinx or MkDocs documentation site.
- Add a complete example repository or examples folder covering pytest, unittest, PlantUML, metrics, and CI.
- Add contribution guidance for new rule types and metric implementations.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -479,13 +479,13 @@ from archunitpython import project_graph
def test_export_dependency_graph_reports():
graph = project_graph("src/requests").titled("Application Architecture")

graph.collapse_to_folder_depth(2).export_as_mermaid("reports/dependencies.md")
graph.collapse_to_folder_depth(2).export_as_mermaid("reports/dependencies.mmd")

if __name__ == "__main__":
test_export_dependency_graph_reports()
```
**Exported mermaid diagram**
``` mermaid
**Exported Mermaid diagram**
```mermaid
flowchart LR
n0["__init__.py"]
n1["__version__.py"]
Expand Down
6 changes: 3 additions & 3 deletions src/archunitpython/files/assertion/custom_file_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ def gather_custom_file_violations(
nodes: All projected nodes.
condition: Custom function that returns True if the file passes.
message: Message to include in violation.
is_negated: If False (should adhere), violation when condition returns False.
If True (shouldNot adhere), violation when condition returns True.
is_negated: If False (positive assertion), violation when condition returns False.
If True (negated assertion), violation when condition returns True.
pre_filters: Filters to apply before checking the condition.

Returns:
Expand All @@ -90,7 +90,7 @@ def gather_custom_file_violations(
result = condition(file_info)

if is_negated:
# shouldNot: violation if condition IS True
# Negated assertion: violation if condition IS True
if result:
violations.append(CustomFileViolation(message=message, file_info=file_info))
else:
Expand Down
6 changes: 3 additions & 3 deletions src/archunitpython/files/assertion/depend_on_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ def gather_depend_on_file_violations(
edges: Projected dependency edges.
subject_filters: Patterns for the source files (subject of the rule).
object_filters: Patterns for the target files (dependency targets).
is_negated: If False (should), files matching subject MUST depend on
is_negated: If False (`should()`), files matching subject MUST depend on
files matching object.
If True (shouldNot), files matching subject must NOT
If True (`should_not()`), files matching subject must NOT
depend on files matching object.

Returns:
Expand All @@ -48,7 +48,7 @@ def gather_depend_on_file_violations(
target_matches = all(matches_pattern(edge.target_label, f) for f in object_filters)

if is_negated:
# shouldNot: violation if dependency EXISTS
# should_not(): violation if dependency EXISTS
if target_matches:
violations.append(ViolatingFileDependency(dependency=edge, is_negated=True))
else:
Expand Down
6 changes: 3 additions & 3 deletions src/archunitpython/files/assertion/matching_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ def gather_regex_matching_violations(
Args:
nodes: Files to check.
check_filters: Patterns to match against.
is_negated: If False (should), files MUST match all patterns.
If True (shouldNot), files must NOT match any pattern.
is_negated: If False (`should()`), files MUST match all patterns.
If True (`should_not()`), files must NOT match any pattern.

Returns:
List of violations.
Expand All @@ -41,7 +41,7 @@ def gather_regex_matching_violations(
for filter_ in check_filters:
matched = matches_pattern(node.label, filter_)
if is_negated:
# shouldNot: violation if file DOES match
# should_not(): violation if file DOES match
if matched:
violations.append(
ViolatingNode(
Expand Down
2 changes: 1 addition & 1 deletion src/archunitpython/slices/assertion/admissible_edges.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def gather_violations(
edges: list[ProjectedEdge],
rules: list[Rule],
) -> list[Violation]:
"""Check for forbidden dependencies (used with shouldNot).
"""Check for forbidden dependencies (used with `should_not()`).

Args:
edges: Projected dependency edges between slices.
Expand Down