archunitpython 1.1.2__py3-none-any.whl → 1.2.1__py3-none-any.whl

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.
Files changed (30) hide show
  1. archunitpython/__init__.py +9 -1
  2. archunitpython/common/extraction/extract_graph.py +122 -29
  3. archunitpython/common/pattern_matching.py +1 -3
  4. archunitpython/common/projection/cycles/johnsons_apsp.py +4 -9
  5. archunitpython/common/projection/cycles/tarjan_scc.py +2 -6
  6. archunitpython/common/projection/project_cycles.py +1 -2
  7. archunitpython/common/util/logger.py +1 -3
  8. archunitpython/files/assertion/custom_file_logic.py +3 -9
  9. archunitpython/files/assertion/depend_on_external_modules.py +3 -8
  10. archunitpython/files/assertion/depend_on_files.py +4 -12
  11. archunitpython/files/fluentapi/files.py +9 -27
  12. archunitpython/graph/__init__.py +35 -0
  13. archunitpython/graph/graph_reporter.py +795 -0
  14. archunitpython/layers/__init__.py +8 -0
  15. archunitpython/layers/assertion/__init__.py +9 -0
  16. archunitpython/layers/assertion/layer_dependencies.py +83 -0
  17. archunitpython/layers/fluentapi/__init__.py +6 -0
  18. archunitpython/layers/fluentapi/layers.py +116 -0
  19. archunitpython/metrics/assertion/metric_thresholds.py +1 -3
  20. archunitpython/metrics/calculation/distance.py +1 -3
  21. archunitpython/metrics/extraction/extract_class_info.py +3 -9
  22. archunitpython/metrics/fluentapi/export_utils.py +2 -6
  23. archunitpython/metrics/fluentapi/metrics.py +12 -38
  24. archunitpython/slices/fluentapi/slices.py +4 -12
  25. archunitpython/slices/uml/generate_rules.py +2 -6
  26. archunitpython/testing/common/violation_factory.py +11 -3
  27. {archunitpython-1.1.2.dist-info → archunitpython-1.2.1.dist-info}/METADATA +161 -6
  28. {archunitpython-1.1.2.dist-info → archunitpython-1.2.1.dist-info}/RECORD +30 -23
  29. {archunitpython-1.1.2.dist-info → archunitpython-1.2.1.dist-info}/WHEEL +0 -0
  30. {archunitpython-1.1.2.dist-info → archunitpython-1.2.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: archunitpython
3
- Version: 1.1.2
3
+ Version: 1.2.1
4
4
  Summary: Architecture testing library for Python projects. Enforce dependency rules, detect cycles, validate metrics.
5
5
  Project-URL: Homepage, https://github.com/LukasNiessen/ArchUnitPython
6
6
  Project-URL: Repository, https://github.com/LukasNiessen/ArchUnitPython.git
@@ -39,18 +39,19 @@ Description-Content-Type: text/markdown
39
39
  <!-- spacer -->
40
40
  <p></p>
41
41
 
42
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
43
- [![PyPI version](https://img.shields.io/pypi/v/archunitpython.svg)](https://pypi.org/project/archunitpython/)
44
- [![Python versions](https://img.shields.io/pypi/pyversions/archunitpython.svg)](https://pypi.org/project/archunitpython/)
45
- [![GitHub stars](https://img.shields.io/github/stars/LukasNiessen/ArchUnitPython.svg)](https://github.com/LukasNiessen/ArchUnitPython)
42
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Build & tests](https://img.shields.io/github/actions/workflow/status/LukasNiessen/ArchUnitPython/integrate.yaml?branch=main&label=build%20%26%20tests)](https://github.com/LukasNiessen/ArchUnitPython/actions/workflows/integrate.yaml) [![GitHub stars](https://img.shields.io/github/stars/LukasNiessen/ArchUnitPython.svg)](https://github.com/LukasNiessen/ArchUnitPython)<br>
43
+ [![PyPI downloads](https://static.pepy.tech/badge/archunitpython/month)](https://pepy.tech/project/archunitpython) [![PyPI total downloads](https://img.shields.io/pepy/dt/archunitpython?label=total%20downloads&color=007ec6)](https://pepy.tech/project/archunitpython)
44
+ <!-- [![PyPI version](https://img.shields.io/pypi/v/archunitpython.svg)](https://pypi.org/project/archunitpython/) -->
46
45
 
47
46
  </div>
48
47
 
49
48
  Enforce architecture rules in Python projects. Check for dependency directions, detect circular dependencies, enforce coding standards and much more. Integrates with pytest and any other testing framework. Very simple setup and pipeline integration. Zero runtime dependencies.
50
49
 
50
+ The #1 ArchUnit-style architecture testing library for Python, measured by GitHub stars.
51
+
51
52
  _Inspired by the amazing ArchUnit library but we are not affiliated with ArchUnit._
52
53
 
53
- [Setup](#-setup) • [Use Cases](#-use-cases) • [Features](#-features) • [Contributing](CONTRIBUTING.md)
54
+ [Setup](#-setup) • [Use Cases](#-use-cases) • [Features](#-features) • [Why ArchUnitPython?](#-library-comparison) • [Sponsor](https://github.com/sponsors/LukasNiessen) • [Contributing](CONTRIBUTING.md)
54
55
 
55
56
  ## ⚡ 5 min Quickstart
56
57
 
@@ -121,6 +122,22 @@ These tests run automatically in your testing setup, for example in your CI pipe
121
122
  run: pytest tests/test_architecture.py -v
122
123
  ```
123
124
 
125
+ You can also export dependency graph reports as CI artifacts:
126
+
127
+ ```python
128
+ from archunitpython import project_graph
129
+
130
+ def test_generate_dependency_graph_reports():
131
+ graph = project_graph("src/").titled("Application Architecture")
132
+
133
+ graph.collapse_to_folder_depth(2).export_as_html(
134
+ "reports/dependency-graph.html"
135
+ )
136
+ graph.export_as_mermaid("reports/dependency-graph.mmd")
137
+
138
+ assert graph.snapshot().summary.node_count >= 0
139
+ ```
140
+
124
141
  ## 🚐 Setup
125
142
 
126
143
  Installation:
@@ -165,6 +182,7 @@ from archunitpython import CheckOptions
165
182
  options = CheckOptions(
166
183
  allow_empty_tests=True, # Don't fail when no files match
167
184
  clear_cache=True, # Clear the graph cache
185
+ ignore_type_checking_imports=True, # Ignore imports inside if TYPE_CHECKING
168
186
  )
169
187
 
170
188
  violations = rule.check(options)
@@ -228,6 +246,65 @@ def test_business_not_depend_on_presentation():
228
246
  assert_passes(rule)
229
247
  ```
230
248
 
249
+ ### Named Layer Rules
250
+
251
+ ```python
252
+ from archunitpython import project_layers
253
+
254
+ def test_clean_architecture_layers():
255
+ rule = (
256
+ project_layers("src/")
257
+ .layer("presentation").defined_by_folder("**/presentation/**")
258
+ .layer("business").defined_by_folder("**/business/**")
259
+ .layer("database").defined_by_folder("**/database/**")
260
+ .where_layer("presentation")
261
+ .may_only_depend_on_layers("business")
262
+ .where_layer("business")
263
+ .may_only_depend_on_layers()
264
+ .where_layer("database")
265
+ .may_only_depend_on_layers()
266
+ )
267
+ assert_passes(rule)
268
+ ```
269
+
270
+ ### External Dependencies
271
+
272
+ ```python
273
+ def test_domain_does_not_import_requests():
274
+ rule = (
275
+ project_files("src/")
276
+ .in_folder("**/domain/**")
277
+ .should_not()
278
+ .depend_on_external_modules()
279
+ .matching("requests")
280
+ )
281
+ assert_passes(rule)
282
+ ```
283
+
284
+ ### TYPE_CHECKING-aware Analysis
285
+
286
+ ```python
287
+ from archunitpython import CheckOptions
288
+
289
+ def test_type_only_dependencies_do_not_count_as_runtime_coupling():
290
+ rule = (
291
+ project_files("src/")
292
+ .in_folder("**/api/**")
293
+ .should_not()
294
+ .depend_on_files()
295
+ .in_folder("**/infrastructure/**")
296
+ )
297
+ assert_passes(rule, CheckOptions(ignore_type_checking_imports=True))
298
+ ```
299
+
300
+ ### Dynamic Imports and Ignore Directives
301
+
302
+ ArchUnitPython detects string-based dynamic imports such as `importlib.import_module("my_app.adapters.sql")` and `__import__("my_app.adapters.sql")`. For known migration shims, you can suppress one import edge locally:
303
+
304
+ ```python
305
+ from my_app.adapters.sql import Repository # archunit: ignore
306
+ ```
307
+
231
308
  ### Naming Conventions
232
309
 
233
310
  ```python
@@ -350,6 +427,48 @@ def test_no_forbidden_dependency():
350
427
  assert_passes(rule)
351
428
  ```
352
429
 
430
+ ### Dependency Graph Reports
431
+
432
+ Generate dependency graph reports in multiple formats and narrow them to the part of the codebase you want to inspect.
433
+
434
+ ```python
435
+ from archunitpython import project_graph
436
+
437
+ def test_export_dependency_graph_reports():
438
+ graph = project_graph("src/").titled("Application Architecture")
439
+
440
+ graph.collapse_to_folder_depth(2).export_as_mermaid(
441
+ "reports/dependencies.mmd"
442
+ )
443
+
444
+ graph.focus_on("**/domain/**", 1).export_as_html(
445
+ "reports/domain-dependencies.html"
446
+ )
447
+
448
+ assert graph.snapshot().summary.node_count >= 0
449
+ ```
450
+
451
+ Supported formats:
452
+
453
+ - DOT (`export_as_dot`, `to_dot`)
454
+ - Mermaid (`export_as_mermaid`, `to_mermaid`)
455
+ - D2 (`export_as_d2`, `to_d2`)
456
+ - CSV (`export_as_csv`, `to_csv`)
457
+ - JSON (`export_as_json`, `to_json`)
458
+ - HTML (`export_as_html`, `to_html`)
459
+
460
+ Graph exploration options:
461
+
462
+ - `focus_on(pattern, depth)` keeps matching files and their neighbors.
463
+ - `reachable_from(pattern)` keeps matching files and their transitive dependencies.
464
+ - `dependents_of(pattern)` keeps files that transitively depend on the matching files.
465
+ - `collapse_to_folder_depth(depth)` aggregates files to folder-level graph nodes.
466
+ - `collapse_by_pattern(pattern, replacement)` maps files to custom graph nodes.
467
+ - `include_external_dependencies()` includes imports to external modules such as `requests` or `sqlalchemy`.
468
+ - `include_self_dependencies()` keeps self edges that are normally hidden in reports.
469
+
470
+ When you create reports through `project_graph("src/")`, internal file paths are displayed relative to that project root so the output stays readable.
471
+
353
472
  ### Reports
354
473
 
355
474
  Generate HTML reports for your metrics. _Note that this feature is in beta._
@@ -529,6 +648,40 @@ def test_from_file():
529
648
  assert_passes(rule)
530
649
  ```
531
650
 
651
+ ## 📊 Library Comparison
652
+
653
+ Here's how ArchUnitPython compares to other Python architecture-enforcement libraries.
654
+
655
+ ArchUnitPython is optimized for **architecture rules as tests**: rules live next to your normal unit tests, run in pytest/unittest/CI, and fail with test-style violation messages. Broader CLI-first tools such as [Tach](https://github.com/tach-org/tach) and [Import Linter](https://github.com/seddonym/import-linter) are excellent adjacent tools, but they solve the problem through separate configuration and commands rather than a test-native ArchUnit-style API.
656
+
657
+ | Feature | **ArchUnitPython** | **Tach** | **Import Linter** | **PyTestArch** |
658
+ | ------- | ------------------ | -------- | ----------------- | -------------- |
659
+ | **Primary workflow** | ✅ Architecture rules as unit tests | ⚠️ CLI + `tach.toml` | ⚠️ CLI + contracts config | ⚠️ pytest-oriented evaluable architecture |
660
+ | **ArchUnit-style fluent API** | ✅ Yes | ❌ No | ❌ No | ⚠️ Partial |
661
+ | **Testing framework integration** | ✅ pytest, unittest, any runner | ⚠️ CI/pre-commit CLI | ⚠️ CI/pre-commit CLI | ⚠️ pytest-focused |
662
+ | **Zero runtime dependencies** | ✅ Standard library only | ⚠️ No app runtime impact, Rust-backed tool | ❌ Tool dependencies | ❌ Tool dependencies |
663
+ | **Circular dependency detection** | ✅ First-class | ✅ First-class | ⚠️ Contract/graph based | ⚠️ Import-rule based |
664
+ | **File/folder dependency rules** | ✅ Glob + regex | ✅ Module config | ✅ Import contracts | ✅ Module rules |
665
+ | **Named layer rules** | ✅ `project_layers()` | ✅ Supported | ✅ Supported | ✅ Supported |
666
+ | **External dependency rules** | ✅ `depend_on_external_modules()` | ⚠️ Internal module focus | ⚠️ Import contract focus | ⚠️ Internal import focus |
667
+ | **TYPE_CHECKING-aware analysis** | ✅ Configurable | ⚠️ Not the core API | ⚠️ Not the core API | ⚠️ Not the core API |
668
+ | **Dynamic import detection** | ✅ `importlib` + `__import__` string calls | ⚠️ Not the core workflow | ⚠️ Not the core workflow | ⚠️ Import analysis focused |
669
+ | **Inline ignore directives** | ✅ `# archunit: ignore` | ✅ Supported | ⚠️ Config-based ignores | ⚠️ Rule/exclusion based |
670
+ | **Naming convention checks** | ✅ Files and paths | ❌ No | ❌ No | ⚠️ Module-name oriented |
671
+ | **Code metrics** | ✅ Counts, LCOM, distance metrics | ❌ No | ❌ No | ❌ No |
672
+ | **Custom rules and metrics** | ✅ Full support | ❌ No | ⚠️ Custom contracts | ⚠️ Limited custom rule composition |
673
+ | **PlantUML diagram validation** | ✅ Supported | ❌ No | ❌ No | ❌ No |
674
+ | **Empty test protection** | ✅ Fails by default | ⚠️ Config validation | ⚠️ Contract validation | ⚠️ Not the main focus |
675
+ | **Graph/reporting** | ✅ DOT, Mermaid, D2, CSV, JSON, HTML graph reports + metrics HTML | ✅ DOT, JSON, web graph | ✅ Browser UI | ⚠️ Optional graph visualization |
676
+ | **Best fit** | Architecture tests, CI fitness functions, metrics, diagrams | Modular monolith dependency governance | Config-driven import contracts | pytest import-boundary checks |
677
+
678
+ The most important differences:
679
+
680
+ - **Test-native by design**: ArchUnitPython rules are just Python tests, so architecture decisions are reviewed, run, and debugged in the same workflow as the rest of your test suite.
681
+ - **Broader rule surface**: dependency direction, cycles, layer policies, external modules, type-only imports, dynamic imports, naming, metrics, custom rules, and PlantUML validation live in one API.
682
+ - **False-positive protection**: empty checks fail by default, which helps catch typos in file and folder patterns before they silently make your architecture tests meaningless.
683
+ - **Quality beyond imports**: ArchUnitPython can enforce code metrics such as LCOM cohesion, field/method counts, abstractness, instability, and distance from the main sequence.
684
+
532
685
  ## 📢 Informative Error Messages
533
686
 
534
687
  When tests fail, you get helpful output with file paths and violation details:
@@ -590,6 +743,7 @@ The features of ArchUnitPython can very well be used as architectural fitness fu
590
743
  | **Files** | File and folder based rules | Stable |
591
744
  | **Metrics** | Code quality metrics | Stable |
592
745
  | **Slices** | Architecture slicing | Stable |
746
+ | **Graph** | Dependency graph reports | Experimental |
593
747
  | **Testing** | Test framework integration | Stable |
594
748
  | **Common** | Shared utilities | Stable |
595
749
  | **Reports** | Generate HTML reports | Experimental |
@@ -659,6 +813,7 @@ Found a bug? Want to discuss features?
659
813
  If ArchUnitPython helps your project, please consider:
660
814
 
661
815
  - Starring the repository 💚
816
+ - Sponsoring development via [GitHub Sponsors](https://github.com/sponsors/LukasNiessen)
662
817
  - Suggesting new features 💭
663
818
  - Contributing code or documentation ⌨️
664
819
 
@@ -1,7 +1,7 @@
1
- archunitpython/__init__.py,sha256=Kj602wsdxapRIJHnd6ig-ksHtzWfupm-Rpo7HKALKYU,926
1
+ archunitpython/__init__.py,sha256=w__UDj9GojwOMtYX5eSZCpd4WYiIKjWGJ6c-8nRlPSI,1154
2
2
  archunitpython/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  archunitpython/common/__init__.py,sha256=u8jwbfALwIT_5ZqTrRchpZqkFHG5tTwM21LX5hR9ZSc,593
4
- archunitpython/common/pattern_matching.py,sha256=zhfglETSJfe5XPzueVflM14EKfllXuazqzd2XH5fuxw,2675
4
+ archunitpython/common/pattern_matching.py,sha256=HMAfo8GsooHvA4d2IxCi3btrYTdwfOQXw4bDNr117P0,2669
5
5
  archunitpython/common/regex_factory.py,sha256=UtlElM0Uty3SuD7tPZeoDnpbFipFUuYDpWfuV-Xq4c4,2459
6
6
  archunitpython/common/types.py,sha256=aA6hxCvmOy7_q74pE0sDRILNB8KxmHx9G4j5ql87mWs,755
7
7
  archunitpython/common/assertion/__init__.py,sha256=qpFkUrRoJWbwL7KPWaVTqlx70fhUJtwjyY0elsm8tv0,131
@@ -9,7 +9,7 @@ archunitpython/common/assertion/violation.py,sha256=TnMOykN3kPoGrSf1KcxBXYRfaxfX
9
9
  archunitpython/common/error/__init__.py,sha256=UWcdIKpGAJvo4WEGOVSaUjQQnKoPi8R496uDGXBWKsE,116
10
10
  archunitpython/common/error/errors.py,sha256=y7mcXoZPyK7uD2dMMO1qBt1y7KcIeGlRYiVeI6bjms4,249
11
11
  archunitpython/common/extraction/__init__.py,sha256=RkJOcxJoLYQxEagh3uWhjsUCprK3Nr3Bn3o7nmzk4_Q,284
12
- archunitpython/common/extraction/extract_graph.py,sha256=qt6wJI9alZZyoWmwggvPkTDubnppneY2pHaATJbGzdk,12000
12
+ archunitpython/common/extraction/extract_graph.py,sha256=HIfAZLZiv4Zbi1Nm8jmNnnu8ggn0wQXunBlZP_QK1x8,15254
13
13
  archunitpython/common/extraction/graph.py,sha256=Rk-0eDDOLoHvScO27J2JzXjyMq3e5eKtrHnFBh5B6SU,1052
14
14
  archunitpython/common/fluentapi/__init__.py,sha256=J7PDgqBXQOpXqCMCGRyFNil0dCulufmhfirzvYvh-gk,119
15
15
  archunitpython/common/fluentapi/checkable.py,sha256=6Tsxtycc27-LaeE6cTtQF6NfepFzhgmCrFJAosN_chs,892
@@ -17,60 +17,67 @@ archunitpython/common/logging/__init__.py,sha256=u3-2_jYmiyoQ-C534SmQXvR1L9h3lbJ
17
17
  archunitpython/common/logging/types.py,sha256=wUriZeaUawA3JoBfJVLC6lIMglbLG955nXWdJGwxW4I,425
18
18
  archunitpython/common/projection/__init__.py,sha256=-Sx-b80b2N3ap3ahAcLUCXqYYK3ccgTDpV-K1jSOSYQ,797
19
19
  archunitpython/common/projection/edge_projections.py,sha256=Mud8DL6Y8H66CObqyikKYAxdXMRENuAFRtwhCxpwxoU,1524
20
- archunitpython/common/projection/project_cycles.py,sha256=SA6eXzy599dJMvAOA6K1ONkOaFLiEXw8qixpgybtW-I,3105
20
+ archunitpython/common/projection/project_cycles.py,sha256=TQ4Ok1hT4T_znqFbwV4VTj-BXmlFr1O7TtZdVOd5oPg,3081
21
21
  archunitpython/common/projection/project_edges.py,sha256=v7hDMSeghiLz0xHbG4BNF7jNQphcWobU7rgoiuw3fh4,1268
22
22
  archunitpython/common/projection/project_nodes.py,sha256=U6sLYvJd6NBgg39V0Ry7r_-57gdXaaXsbH-D12nipCg,1497
23
23
  archunitpython/common/projection/types.py,sha256=EP5yJd-uXYdACFdFzeID8bUVsg_vdhgiOzshrC-CC8Y,937
24
24
  archunitpython/common/projection/cycles/__init__.py,sha256=giGUcwpEMr91XST-biyCmLUjP5okhwTA4CcCaxjZdmg,217
25
25
  archunitpython/common/projection/cycles/cycle_utils.py,sha256=eoVyZAapTWwpELGV9rY8e4ug2khmsGiEUz-3fD-JKBM,1746
26
26
  archunitpython/common/projection/cycles/cycles.py,sha256=lHocmN7xnlfbrz6ZqKwuECHynnJNBe8Zb2nVcFVyOhA,906
27
- archunitpython/common/projection/cycles/johnsons_apsp.py,sha256=vbAmR8QqGmM7hRgphngJvQ5yU8Og4RxYkGUQmKOWT2U,4087
27
+ archunitpython/common/projection/cycles/johnsons_apsp.py,sha256=lfnTMIvv3mTeIlh0D9QzwJUGPgz9spcDvwSgPJhz69s,3993
28
28
  archunitpython/common/projection/cycles/model.py,sha256=sgpb0HpYzQND0KPb56BWlnrv683UkE3MZ3NfAJ9ePK0,483
29
- archunitpython/common/projection/cycles/tarjan_scc.py,sha256=49LnVrcFIRQr2yPi034YIdIBjmrFotrXsoS000Qz9Mc,2843
29
+ archunitpython/common/projection/cycles/tarjan_scc.py,sha256=pIj1ub8XgcqVLj8skdZdOvXqwX10U8kOmlnUIIHYCME,2789
30
30
  archunitpython/common/util/__init__.py,sha256=g-W8kWiVqwdohxm74J3yUonPkb_yDUJrp73S5s4jpgI,117
31
31
  archunitpython/common/util/declaration_detector.py,sha256=XgrpgaUIQa9MNFlnhVQz2X_uW7zCO9nrMbGa3tVFyPM,3407
32
- archunitpython/common/util/logger.py,sha256=QT6ir8caMXu4VQombe0NjaT2NUm58kFdlnps4T5ECCE,3348
32
+ archunitpython/common/util/logger.py,sha256=2did2mRAlkrElH9SYgv9xYiSzr4A-jXHg3cp6TodhoA,3326
33
33
  archunitpython/files/__init__.py,sha256=wgl8IOqTeQGpNISu-Q8b_j6rTn8aEgoz6t1S5j8z13g,108
34
34
  archunitpython/files/assertion/__init__.py,sha256=K2qiEFfmo6SCgxfOKNrPzYgT5ScKUaw2W2CrDa3jBTw,1068
35
- archunitpython/files/assertion/custom_file_logic.py,sha256=ygpc2NZghHBD-GTGrQW_dWzGZr_9DSvi0denC-cdwuo,3054
35
+ archunitpython/files/assertion/custom_file_logic.py,sha256=1v5D80QX_NnAKBwKwyhetY4rA8rrXyxN2BsHlvnLgq8,2956
36
36
  archunitpython/files/assertion/cycle_free.py,sha256=Ib3tmVVErmTpORmRn_rZqOqY0gk54crN_d_IapeWqdI,738
37
- archunitpython/files/assertion/depend_on_external_modules.py,sha256=d16mK6lpr5MhxndigSZsGEOPF51UY0Gl5HddqP_MdXs,1949
38
- archunitpython/files/assertion/depend_on_files.py,sha256=B-zyFyXCt2ywCzO0BIH1lRGsre6PkAItv2ZfpM_u2Js,2132
37
+ archunitpython/files/assertion/depend_on_external_modules.py,sha256=BXGpN-301YOcB446e3U0i2rNNliQuaSJCfdZwKVzs0U,1845
38
+ archunitpython/files/assertion/depend_on_files.py,sha256=EGMtDD8KT09BJQwOEMoKj-yTQfY3KLLYWN5SM1BCmpY,2012
39
39
  archunitpython/files/assertion/matching_files.py,sha256=qNbvU2o_MM6rzM-YUdJZzkltVbenWGC0u5kLH7su6CA,2003
40
40
  archunitpython/files/fluentapi/__init__.py,sha256=wgl8IOqTeQGpNISu-Q8b_j6rTn8aEgoz6t1S5j8z13g,108
41
- archunitpython/files/fluentapi/files.py,sha256=uX__VDed_TLNiibK2pTMaPQ8RaCyyFf2ZClqdymvs98,17214
41
+ archunitpython/files/fluentapi/files.py,sha256=MsXY-763W9wVrtU50mDs_cuaErWRHk1MehbbAit4Je8,17032
42
+ archunitpython/graph/__init__.py,sha256=vm1jMOoN35IIU7YDs59qPtf_F82YV-QrEGfXhozAOek,756
43
+ archunitpython/graph/graph_reporter.py,sha256=D_KH01CM7TzeMFB6o5NIQfLVJq0rvKZn9l7WumXV6lo,25598
44
+ archunitpython/layers/__init__.py,sha256=DCRxqLhluTxTaT9ZM2MbfAdJVgqcOO9jtkZHzBbeLOw,164
45
+ archunitpython/layers/assertion/__init__.py,sha256=_VRKjO86psSnmX29EfikDe3RIpJMczTyn6nkSM7xQwc,226
46
+ archunitpython/layers/assertion/layer_dependencies.py,sha256=I8Y3DJnWhCsJfhgQB4lTHBobFG3_bB9a_ljqCNcYeBM,2646
47
+ archunitpython/layers/fluentapi/__init__.py,sha256=psKFB-5IXS1SJ8g62HthExKYJio3bgdVzIleOSiF1gA,125
48
+ archunitpython/layers/fluentapi/layers.py,sha256=Wl926_aWpNrlbWatDi3QDR-8geDflbYFEivWJv-X9dI,4438
42
49
  archunitpython/metrics/__init__.py,sha256=HD72MWF0hCh2LzKfyk3mMJp2tf7TJebpwTtZ_kppjso,84
43
50
  archunitpython/metrics/assertion/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
- archunitpython/metrics/assertion/metric_thresholds.py,sha256=dijCzOr5-dhkdK-QAE3DAkfiSBgknZlxtp-ZrBj_Dmk,1268
51
+ archunitpython/metrics/assertion/metric_thresholds.py,sha256=kwX1iRFnF7oLaLMlQsYrDsNRrivDE8pI6nrrZYAafvg,1262
45
52
  archunitpython/metrics/calculation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
46
53
  archunitpython/metrics/calculation/count.py,sha256=tMbAi51hkrViW7dM8SM1Qhh09kuwI3UeWmytAWNLEq0,3997
47
- archunitpython/metrics/calculation/distance.py,sha256=zXwNrXxmgwBaexvjbODZ1VOSxJx_fZjy5jU0FbNjQcM,3611
54
+ archunitpython/metrics/calculation/distance.py,sha256=W2agAQVmGJftPbHDUToKy66Fp8-h7WZspg15skyYWnc,3589
48
55
  archunitpython/metrics/calculation/lcom.py,sha256=LK_kNT-BM6yuR5TUOLWQLkVvMpqR6q207p7RR9Rb35o,5040
49
56
  archunitpython/metrics/common/__init__.py,sha256=xtEyAhS4X0UbJXHxnpdiXljVZmKIKKekZAZ1zflSPFE,335
50
57
  archunitpython/metrics/common/types.py,sha256=w1BUlw6p_3K8qZDoQXv50P_CcKixGYiyS_YBGYILySA,1601
51
58
  archunitpython/metrics/extraction/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
- archunitpython/metrics/extraction/extract_class_info.py,sha256=eCNoHvOdQGenGDQcd9iucO9PqNv1hYhW9HTOUaZMFio,7825
59
+ archunitpython/metrics/extraction/extract_class_info.py,sha256=IFokUFwNaExmPtKnHW5hgnYWodRtBM3cWhXBGb7lcjs,7751
53
60
  archunitpython/metrics/fluentapi/__init__.py,sha256=HD72MWF0hCh2LzKfyk3mMJp2tf7TJebpwTtZ_kppjso,84
54
- archunitpython/metrics/fluentapi/export_utils.py,sha256=qpv01BeoARhciyN7J05JIn-xMxbmxnoXGKBLwMYtlhM,2381
55
- archunitpython/metrics/fluentapi/metrics.py,sha256=0oo2EUEV8YWBiV1-v84LzPXX9sBBPOmmzgA34ZP0uQQ,19488
61
+ archunitpython/metrics/fluentapi/export_utils.py,sha256=1r-zTQAUqn_agp4_lhbcffdzfdASNY3LebYvKAG9kcQ,2333
62
+ archunitpython/metrics/fluentapi/metrics.py,sha256=tvaMctIJAjqHhGT62u5LbZImJFCGIsoJ3Z6cdiY6zTs,19198
56
63
  archunitpython/metrics/projection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
64
  archunitpython/slices/__init__.py,sha256=tb8MoZiEqIdmWy7uyhmEtMNm5Fxjuw6atSvDsD131DE,96
58
65
  archunitpython/slices/assertion/__init__.py,sha256=MRwV3d69ljAJ7hFYdxI6UDNC8U4Dm1ImeuLUVKEC9To,280
59
66
  archunitpython/slices/assertion/admissible_edges.py,sha256=-3o5mGtl81i5I_572x3Z4ZDfqPCyFqjGd7Dg8GRSKhY,3119
60
67
  archunitpython/slices/fluentapi/__init__.py,sha256=tb8MoZiEqIdmWy7uyhmEtMNm5Fxjuw6atSvDsD131DE,96
61
- archunitpython/slices/fluentapi/slices.py,sha256=KpkIKV9RDLwTFe05cmksIVEAgoYGoJwlHd35KmN2EOc,7183
68
+ archunitpython/slices/fluentapi/slices.py,sha256=5Q6HbUqzz3xSyeeI3iLqMYRX-LXbu5xOc806MWqqYro,7103
62
69
  archunitpython/slices/projection/__init__.py,sha256=tVgcK4gw-bqhUq98vU7_iPE0NEhOPUr7vr1-p7JI1A4,237
63
70
  archunitpython/slices/projection/slicing_projections.py,sha256=BHBkuVG80mqzT7N4FlCCfY5U_NvlXmAgTmHf_SPTXVM,4215
64
71
  archunitpython/slices/uml/__init__.py,sha256=GQFA5WBKfi_YElWiNWNm9c9IM-VaW83_Cg6kpwkzxkw,196
65
72
  archunitpython/slices/uml/export_diagram.py,sha256=FeBRV8Vt8LuhLqEbg5JzZOmEk2i49JPkozMcI5r335g,818
66
- archunitpython/slices/uml/generate_rules.py,sha256=zxiRW4PjVZHXdkQcXAycosbZ1do96SwpuqUoB2h0vDc,2180
73
+ archunitpython/slices/uml/generate_rules.py,sha256=D9vvqDzHAM0F80z4u5yBalEqIiNfJJ5HGXP0fVlSzHw,2136
67
74
  archunitpython/testing/__init__.py,sha256=MJm6CHGhBGFg1um2L20-GD2DEHKqg8SiUoI-sRsoXQk,128
68
75
  archunitpython/testing/assertion.py,sha256=YTiNWHIQu4xlSqmlvqj1L-Z2Oo1Z-wOvN0VyZQB-CZE,1430
69
76
  archunitpython/testing/common/__init__.py,sha256=Wc4bC-N4t6giChKjj6wuTGKkb39thcYS_xKWG9paYeY,220
70
77
  archunitpython/testing/common/color_utils.py,sha256=2I8Z1SZfWhhgudMgmXY6PPydGxGl35cK_To-GXnSyJg,1226
71
- archunitpython/testing/common/violation_factory.py,sha256=wrhsQoTmu70cmgXjjTIJNdXFeN9iQerQCZR4-vaAwuQ,4209
78
+ archunitpython/testing/common/violation_factory.py,sha256=yWlvv2U7u-7KoTMfp1QCeJXxTLpPEagKqDHZmPSyrlk,4677
72
79
  archunitpython/testing/pytest_plugin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
73
- archunitpython-1.1.2.dist-info/METADATA,sha256=hKP1bPzVqKt5QaUdbi5FYp1QdLW5-rL8ydHULR-P_08,20063
74
- archunitpython-1.1.2.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
75
- archunitpython-1.1.2.dist-info/licenses/LICENSE,sha256=kaQWfzfHk45CNIx4sIW7Uf1sNW5rmo6BpZ-R8GruuK0,1102
76
- archunitpython-1.1.2.dist-info/RECORD,,
80
+ archunitpython-1.2.1.dist-info/METADATA,sha256=0kFzgCIGfYVHduyDa7U4njL_cGzoMoThpd255uf_Eh8,28498
81
+ archunitpython-1.2.1.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
82
+ archunitpython-1.2.1.dist-info/licenses/LICENSE,sha256=kaQWfzfHk45CNIx4sIW7Uf1sNW5rmo6BpZ-R8GruuK0,1102
83
+ archunitpython-1.2.1.dist-info/RECORD,,