archunitpython 1.0.0__py3-none-any.whl → 1.1.0__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.
- archunitpython/__init__.py +1 -1
- archunitpython/common/extraction/extract_graph.py +37 -6
- archunitpython/common/fluentapi/checkable.py +1 -0
- archunitpython/common/projection/edge_projections.py +17 -0
- archunitpython/files/assertion/__init__.py +6 -0
- archunitpython/files/assertion/depend_on_external_modules.py +64 -0
- archunitpython/files/fluentapi/files.py +80 -1
- archunitpython/testing/common/violation_factory.py +12 -0
- {archunitpython-1.0.0.dist-info → archunitpython-1.1.0.dist-info}/METADATA +17 -6
- {archunitpython-1.0.0.dist-info → archunitpython-1.1.0.dist-info}/RECORD +12 -11
- {archunitpython-1.0.0.dist-info → archunitpython-1.1.0.dist-info}/WHEEL +0 -0
- {archunitpython-1.0.0.dist-info → archunitpython-1.1.0.dist-info}/licenses/LICENSE +0 -0
archunitpython/__init__.py
CHANGED
|
@@ -8,7 +8,9 @@ import os
|
|
|
8
8
|
from archunitpython.common.extraction.graph import Edge, Graph, ImportKind
|
|
9
9
|
from archunitpython.common.fluentapi.checkable import CheckOptions
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
GraphCacheKey = tuple[str, tuple[str, ...], bool]
|
|
12
|
+
|
|
13
|
+
_graph_cache: dict[GraphCacheKey, Graph] = {}
|
|
12
14
|
|
|
13
15
|
_DEFAULT_EXCLUDE = [
|
|
14
16
|
"__pycache__",
|
|
@@ -56,7 +58,13 @@ def extract_graph(
|
|
|
56
58
|
project_path = os.getcwd()
|
|
57
59
|
|
|
58
60
|
project_path = os.path.abspath(project_path)
|
|
59
|
-
|
|
61
|
+
excludes = list(exclude_patterns) if exclude_patterns is not None else list(_DEFAULT_EXCLUDE)
|
|
62
|
+
ignore_type_checking_imports = bool(
|
|
63
|
+
options and options.ignore_type_checking_imports
|
|
64
|
+
)
|
|
65
|
+
cache_key = _build_cache_key(
|
|
66
|
+
project_path, excludes, ignore_type_checking_imports
|
|
67
|
+
)
|
|
60
68
|
|
|
61
69
|
if options and options.clear_cache:
|
|
62
70
|
_graph_cache.pop(cache_key, None)
|
|
@@ -64,18 +72,36 @@ def extract_graph(
|
|
|
64
72
|
if cache_key in _graph_cache:
|
|
65
73
|
return _graph_cache[cache_key]
|
|
66
74
|
|
|
67
|
-
result = _extract_graph_uncached(
|
|
75
|
+
result = _extract_graph_uncached(
|
|
76
|
+
project_path,
|
|
77
|
+
excludes,
|
|
78
|
+
ignore_type_checking_imports=ignore_type_checking_imports,
|
|
79
|
+
)
|
|
68
80
|
_graph_cache[cache_key] = result
|
|
69
81
|
return result
|
|
70
82
|
|
|
71
83
|
|
|
84
|
+
def _build_cache_key(
|
|
85
|
+
project_path: str,
|
|
86
|
+
exclude_patterns: list[str],
|
|
87
|
+
ignore_type_checking_imports: bool,
|
|
88
|
+
) -> GraphCacheKey:
|
|
89
|
+
"""Build a stable cache key for graph extraction options."""
|
|
90
|
+
return (
|
|
91
|
+
project_path,
|
|
92
|
+
tuple(sorted(exclude_patterns)),
|
|
93
|
+
ignore_type_checking_imports,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
|
|
72
97
|
def _extract_graph_uncached(
|
|
73
98
|
project_path: str,
|
|
74
|
-
exclude_patterns: list[str]
|
|
99
|
+
exclude_patterns: list[str],
|
|
100
|
+
*,
|
|
101
|
+
ignore_type_checking_imports: bool = False,
|
|
75
102
|
) -> Graph:
|
|
76
103
|
"""Extract graph without caching."""
|
|
77
|
-
|
|
78
|
-
py_files = _find_python_files(project_path, excludes)
|
|
104
|
+
py_files = _find_python_files(project_path, exclude_patterns)
|
|
79
105
|
|
|
80
106
|
edges: list[Edge] = []
|
|
81
107
|
py_files_set = set(py_files)
|
|
@@ -93,6 +119,11 @@ def _extract_graph_uncached(
|
|
|
93
119
|
# Extract and resolve imports
|
|
94
120
|
imports = _extract_imports(file_path)
|
|
95
121
|
for module_name, import_kind in imports:
|
|
122
|
+
if (
|
|
123
|
+
ignore_type_checking_imports
|
|
124
|
+
and import_kind == ImportKind.TYPE_IMPORT
|
|
125
|
+
):
|
|
126
|
+
continue
|
|
96
127
|
resolved, is_external = _resolve_import(
|
|
97
128
|
module_name, file_path, project_path, import_kind
|
|
98
129
|
)
|
|
@@ -34,3 +34,20 @@ def per_edge() -> MapFunction:
|
|
|
34
34
|
return MappedEdge(source_label=edge.source, target_label=edge.target)
|
|
35
35
|
|
|
36
36
|
return mapper
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def per_external_edge() -> MapFunction:
|
|
40
|
+
"""Create a mapper that only passes external edges.
|
|
41
|
+
|
|
42
|
+
Self-referencing edges are filtered out, though they are not expected for
|
|
43
|
+
external imports.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
def mapper(edge: Edge) -> MappedEdge | None:
|
|
47
|
+
if not edge.external:
|
|
48
|
+
return None
|
|
49
|
+
if edge.source == edge.target:
|
|
50
|
+
return None
|
|
51
|
+
return MappedEdge(source_label=edge.source, target_label=edge.target)
|
|
52
|
+
|
|
53
|
+
return mapper
|
|
@@ -5,6 +5,10 @@ from archunitpython.files.assertion.custom_file_logic import (
|
|
|
5
5
|
gather_custom_file_violations,
|
|
6
6
|
)
|
|
7
7
|
from archunitpython.files.assertion.cycle_free import ViolatingCycle, gather_cycle_violations
|
|
8
|
+
from archunitpython.files.assertion.depend_on_external_modules import (
|
|
9
|
+
ViolatingExternalModuleDependency,
|
|
10
|
+
gather_depend_on_external_module_violations,
|
|
11
|
+
)
|
|
8
12
|
from archunitpython.files.assertion.depend_on_files import (
|
|
9
13
|
ViolatingFileDependency,
|
|
10
14
|
gather_depend_on_file_violations,
|
|
@@ -20,9 +24,11 @@ __all__ = [
|
|
|
20
24
|
"FileInfo",
|
|
21
25
|
"ViolatingCycle",
|
|
22
26
|
"ViolatingFileDependency",
|
|
27
|
+
"ViolatingExternalModuleDependency",
|
|
23
28
|
"ViolatingNode",
|
|
24
29
|
"gather_custom_file_violations",
|
|
25
30
|
"gather_cycle_violations",
|
|
26
31
|
"gather_depend_on_file_violations",
|
|
32
|
+
"gather_depend_on_external_module_violations",
|
|
27
33
|
"gather_regex_matching_violations",
|
|
28
34
|
]
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""Violation gathering for external module dependency rules."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
|
|
7
|
+
from archunitpython.common.assertion.violation import Violation
|
|
8
|
+
from archunitpython.common.pattern_matching import matches_pattern
|
|
9
|
+
from archunitpython.common.projection.types import ProjectedEdge
|
|
10
|
+
from archunitpython.common.types import Filter
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class ViolatingExternalModuleDependency(Violation):
|
|
15
|
+
"""An external module dependency that violates a rule."""
|
|
16
|
+
|
|
17
|
+
dependency: ProjectedEdge
|
|
18
|
+
is_negated: bool = False
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def gather_depend_on_external_module_violations(
|
|
22
|
+
edges: list[ProjectedEdge],
|
|
23
|
+
subject_filters: list[Filter],
|
|
24
|
+
module_filters: list[Filter],
|
|
25
|
+
is_negated: bool,
|
|
26
|
+
) -> list[Violation]:
|
|
27
|
+
"""Check if files depend on forbidden/allowed external modules.
|
|
28
|
+
|
|
29
|
+
Subject filters use AND semantics. Module filters use OR semantics, which
|
|
30
|
+
makes it possible to express useful allowlists or blocklists for external
|
|
31
|
+
module names.
|
|
32
|
+
"""
|
|
33
|
+
violations: list[Violation] = []
|
|
34
|
+
|
|
35
|
+
for edge in edges:
|
|
36
|
+
source_matches = all(
|
|
37
|
+
matches_pattern(edge.source_label, filter_)
|
|
38
|
+
for filter_ in subject_filters
|
|
39
|
+
)
|
|
40
|
+
if not source_matches:
|
|
41
|
+
continue
|
|
42
|
+
|
|
43
|
+
target_matches = (
|
|
44
|
+
any(matches_pattern(edge.target_label, filter_) for filter_ in module_filters)
|
|
45
|
+
if module_filters
|
|
46
|
+
else False
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
if is_negated:
|
|
50
|
+
if target_matches:
|
|
51
|
+
violations.append(
|
|
52
|
+
ViolatingExternalModuleDependency(
|
|
53
|
+
dependency=edge, is_negated=True
|
|
54
|
+
)
|
|
55
|
+
)
|
|
56
|
+
else:
|
|
57
|
+
if not target_matches:
|
|
58
|
+
violations.append(
|
|
59
|
+
ViolatingExternalModuleDependency(
|
|
60
|
+
dependency=edge, is_negated=False
|
|
61
|
+
)
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
return violations
|
|
@@ -16,7 +16,10 @@ from archunitpython.common.assertion.violation import EmptyTestViolation, Violat
|
|
|
16
16
|
from archunitpython.common.extraction.extract_graph import extract_graph
|
|
17
17
|
from archunitpython.common.fluentapi.checkable import CheckOptions
|
|
18
18
|
from archunitpython.common.pattern_matching import matches_all_patterns
|
|
19
|
-
from archunitpython.common.projection.edge_projections import
|
|
19
|
+
from archunitpython.common.projection.edge_projections import (
|
|
20
|
+
per_external_edge,
|
|
21
|
+
per_internal_edge,
|
|
22
|
+
)
|
|
20
23
|
from archunitpython.common.projection.project_cycles import project_cycles
|
|
21
24
|
from archunitpython.common.projection.project_edges import project_edges
|
|
22
25
|
from archunitpython.common.projection.project_nodes import project_to_nodes
|
|
@@ -28,6 +31,9 @@ from archunitpython.files.assertion.custom_file_logic import (
|
|
|
28
31
|
gather_custom_file_violations,
|
|
29
32
|
)
|
|
30
33
|
from archunitpython.files.assertion.cycle_free import gather_cycle_violations
|
|
34
|
+
from archunitpython.files.assertion.depend_on_external_modules import (
|
|
35
|
+
gather_depend_on_external_module_violations,
|
|
36
|
+
)
|
|
31
37
|
from archunitpython.files.assertion.depend_on_files import gather_depend_on_file_violations
|
|
32
38
|
from archunitpython.files.assertion.matching_files import gather_regex_matching_violations
|
|
33
39
|
|
|
@@ -133,6 +139,14 @@ class PositiveMatchPatternFileConditionBuilder:
|
|
|
133
139
|
self._project_path, self._filters, is_negated=False
|
|
134
140
|
)
|
|
135
141
|
|
|
142
|
+
def depend_on_external_modules(
|
|
143
|
+
self,
|
|
144
|
+
) -> "DependOnExternalModuleConditionBuilder":
|
|
145
|
+
"""Begin external dependency assertion for module names."""
|
|
146
|
+
return DependOnExternalModuleConditionBuilder(
|
|
147
|
+
self._project_path, self._filters, is_negated=False
|
|
148
|
+
)
|
|
149
|
+
|
|
136
150
|
def be_in_folder(self, folder: Pattern) -> "MatchPatternFileCondition":
|
|
137
151
|
"""Assert that files are in a certain folder."""
|
|
138
152
|
return MatchPatternFileCondition(
|
|
@@ -182,6 +196,14 @@ class NegatedMatchPatternFileConditionBuilder:
|
|
|
182
196
|
self._project_path, self._filters, is_negated=True
|
|
183
197
|
)
|
|
184
198
|
|
|
199
|
+
def depend_on_external_modules(
|
|
200
|
+
self,
|
|
201
|
+
) -> "DependOnExternalModuleConditionBuilder":
|
|
202
|
+
"""Begin negative external dependency assertion for module names."""
|
|
203
|
+
return DependOnExternalModuleConditionBuilder(
|
|
204
|
+
self._project_path, self._filters, is_negated=True
|
|
205
|
+
)
|
|
206
|
+
|
|
185
207
|
def be_in_folder(self, folder: Pattern) -> "MatchPatternFileCondition":
|
|
186
208
|
"""Assert that files are NOT in a certain folder."""
|
|
187
209
|
return MatchPatternFileCondition(
|
|
@@ -260,6 +282,31 @@ class DependOnFileConditionBuilder:
|
|
|
260
282
|
)
|
|
261
283
|
|
|
262
284
|
|
|
285
|
+
class DependOnExternalModuleConditionBuilder:
|
|
286
|
+
"""Configure external module dependency target patterns."""
|
|
287
|
+
|
|
288
|
+
def __init__(
|
|
289
|
+
self, project_path: str | None, filters: list[Filter], is_negated: bool
|
|
290
|
+
) -> None:
|
|
291
|
+
self._project_path = project_path
|
|
292
|
+
self._filters = filters
|
|
293
|
+
self._is_negated = is_negated
|
|
294
|
+
self._module_filters: list[Filter] = []
|
|
295
|
+
|
|
296
|
+
def matching(self, module_name: Pattern) -> "DependOnExternalModuleCondition":
|
|
297
|
+
"""Target external modules by dotted module name pattern.
|
|
298
|
+
|
|
299
|
+
Multiple calls are combined with OR semantics.
|
|
300
|
+
"""
|
|
301
|
+
self._module_filters.append(RegexFactory.path_matcher(module_name))
|
|
302
|
+
return DependOnExternalModuleCondition(
|
|
303
|
+
self._project_path,
|
|
304
|
+
self._filters,
|
|
305
|
+
list(self._module_filters),
|
|
306
|
+
self._is_negated,
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
|
|
263
310
|
def _get_filtered_nodes(
|
|
264
311
|
project_path: str | None,
|
|
265
312
|
filters: list[Filter],
|
|
@@ -346,6 +393,38 @@ class DependOnFileCondition:
|
|
|
346
393
|
)
|
|
347
394
|
|
|
348
395
|
|
|
396
|
+
class DependOnExternalModuleCondition:
|
|
397
|
+
"""Checkable that verifies external module dependency rules."""
|
|
398
|
+
|
|
399
|
+
def __init__(
|
|
400
|
+
self,
|
|
401
|
+
project_path: str | None,
|
|
402
|
+
subject_filters: list[Filter],
|
|
403
|
+
module_filters: list[Filter],
|
|
404
|
+
is_negated: bool,
|
|
405
|
+
) -> None:
|
|
406
|
+
self._project_path = project_path
|
|
407
|
+
self._subject_filters = subject_filters
|
|
408
|
+
self._module_filters = module_filters
|
|
409
|
+
self._is_negated = is_negated
|
|
410
|
+
|
|
411
|
+
def matching(self, module_name: Pattern) -> "DependOnExternalModuleCondition":
|
|
412
|
+
"""Add another external module pattern using OR semantics."""
|
|
413
|
+
self._module_filters.append(RegexFactory.path_matcher(module_name))
|
|
414
|
+
return self
|
|
415
|
+
|
|
416
|
+
def check(self, options: CheckOptions | None = None) -> list[Violation]:
|
|
417
|
+
graph = extract_graph(self._project_path, options=options)
|
|
418
|
+
edges = project_edges(graph, per_external_edge())
|
|
419
|
+
|
|
420
|
+
return gather_depend_on_external_module_violations(
|
|
421
|
+
edges,
|
|
422
|
+
self._subject_filters,
|
|
423
|
+
self._module_filters,
|
|
424
|
+
self._is_negated,
|
|
425
|
+
)
|
|
426
|
+
|
|
427
|
+
|
|
349
428
|
class MatchPatternFileCondition:
|
|
350
429
|
"""Checkable that verifies files match/don't match patterns."""
|
|
351
430
|
|
|
@@ -7,6 +7,9 @@ from dataclasses import dataclass
|
|
|
7
7
|
from archunitpython.common.assertion.violation import EmptyTestViolation, Violation
|
|
8
8
|
from archunitpython.files.assertion.custom_file_logic import CustomFileViolation
|
|
9
9
|
from archunitpython.files.assertion.cycle_free import ViolatingCycle
|
|
10
|
+
from archunitpython.files.assertion.depend_on_external_modules import (
|
|
11
|
+
ViolatingExternalModuleDependency,
|
|
12
|
+
)
|
|
10
13
|
from archunitpython.files.assertion.depend_on_files import ViolatingFileDependency
|
|
11
14
|
from archunitpython.files.assertion.matching_files import ViolatingNode
|
|
12
15
|
from archunitpython.metrics.assertion.metric_thresholds import (
|
|
@@ -52,6 +55,15 @@ class ViolationFactory:
|
|
|
52
55
|
f"'{edge.target_label}'",
|
|
53
56
|
)
|
|
54
57
|
|
|
58
|
+
if isinstance(violation, ViolatingExternalModuleDependency):
|
|
59
|
+
edge = violation.dependency
|
|
60
|
+
return TestViolation(
|
|
61
|
+
message="External module dependency violation",
|
|
62
|
+
details=f"'{edge.source_label}' "
|
|
63
|
+
f"{'depends on' if violation.is_negated else 'does not depend on'} "
|
|
64
|
+
f"external module '{edge.target_label}'",
|
|
65
|
+
)
|
|
66
|
+
|
|
55
67
|
if isinstance(violation, ViolatingCycle):
|
|
56
68
|
cycle_str = " -> ".join(
|
|
57
69
|
e.source_label for e in violation.cycle
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: archunitpython
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.0
|
|
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
|
|
@@ -33,6 +33,7 @@ Description-Content-Type: text/markdown
|
|
|
33
33
|
# ArchUnitPython - Architecture Testing
|
|
34
34
|
|
|
35
35
|
<div align="center" name="top">
|
|
36
|
+
<img align="center" src="assets/logo-rounded.png" width="150" height="150" alt="ArchUnitPython Logo">
|
|
36
37
|
|
|
37
38
|
<!-- spacer -->
|
|
38
39
|
<p></p>
|
|
@@ -46,7 +47,7 @@ Description-Content-Type: text/markdown
|
|
|
46
47
|
|
|
47
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.
|
|
48
49
|
|
|
49
|
-
|
|
50
|
+
_Inspired by the amazing ArchUnit library but we are not affiliated with ArchUnit._
|
|
50
51
|
|
|
51
52
|
[Setup](#-setup) • [Use Cases](#-use-cases) • [Features](#-features) • [Contributing](CONTRIBUTING.md)
|
|
52
53
|
|
|
@@ -188,7 +189,7 @@ Ensure services/modules don't have forbidden cross-dependencies.
|
|
|
188
189
|
|
|
189
190
|
Here is a repository with a fully functioning example that uses ArchUnitPython to ensure architectural rules:
|
|
190
191
|
|
|
191
|
-
- **[RAG Pipeline
|
|
192
|
+
- **[RAG Pipeline Test Showcase](https://github.com/LukasNiessen/ArchUnitPython-TestRepo-RAG)**: A test showcase demonstrating ArchUnitPython's architecture testing capabilities on a RAG pipeline
|
|
192
193
|
|
|
193
194
|
## 🐣 Features
|
|
194
195
|
|
|
@@ -636,6 +637,12 @@ ArchUnitPython started as the Python port of [ArchUnitTS](https://github.com/Luk
|
|
|
636
637
|
|
|
637
638
|
- **[LukasNiessen](https://github.com/LukasNiessen)** - Creator and main maintainer
|
|
638
639
|
|
|
640
|
+
### Contributors
|
|
641
|
+
|
|
642
|
+
<a href="https://github.com/LukasNiessen/ArchUnitPython/graphs/contributors">
|
|
643
|
+
<img src="https://contrib.rocks/image?repo=LukasNiessen/ArchUnitPython&max=1000&contributors=10" />
|
|
644
|
+
</a>
|
|
645
|
+
|
|
639
646
|
### Questions
|
|
640
647
|
|
|
641
648
|
Found a bug? Want to discuss features?
|
|
@@ -645,9 +652,13 @@ Found a bug? Want to discuss features?
|
|
|
645
652
|
|
|
646
653
|
If ArchUnitPython helps your project, please consider:
|
|
647
654
|
|
|
648
|
-
- Starring the repository
|
|
649
|
-
- Suggesting new features
|
|
650
|
-
- Contributing code or documentation
|
|
655
|
+
- Starring the repository 💚
|
|
656
|
+
- Suggesting new features 💭
|
|
657
|
+
- Contributing code or documentation ⌨️
|
|
658
|
+
|
|
659
|
+
### Star History
|
|
660
|
+
|
|
661
|
+
[](https://www.star-history.com/#LukasNiessen/ArchUnitPython&Date)
|
|
651
662
|
|
|
652
663
|
## 📄 License
|
|
653
664
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
archunitpython/__init__.py,sha256=
|
|
1
|
+
archunitpython/__init__.py,sha256=Y7boq0Xo0uyEXzfP30N_Jt1ij6Ofy8q8XzinC6E1crU,926
|
|
2
2
|
archunitpython/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
3
|
archunitpython/common/__init__.py,sha256=u8jwbfALwIT_5ZqTrRchpZqkFHG5tTwM21LX5hR9ZSc,593
|
|
4
4
|
archunitpython/common/pattern_matching.py,sha256=zhfglETSJfe5XPzueVflM14EKfllXuazqzd2XH5fuxw,2675
|
|
@@ -9,14 +9,14 @@ 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=
|
|
12
|
+
archunitpython/common/extraction/extract_graph.py,sha256=LNh3gohN3hkzoxBGrMOxqFUVPL3-oYiOU2W6Hja0Mbg,11979
|
|
13
13
|
archunitpython/common/extraction/graph.py,sha256=Rk-0eDDOLoHvScO27J2JzXjyMq3e5eKtrHnFBh5B6SU,1052
|
|
14
14
|
archunitpython/common/fluentapi/__init__.py,sha256=J7PDgqBXQOpXqCMCGRyFNil0dCulufmhfirzvYvh-gk,119
|
|
15
|
-
archunitpython/common/fluentapi/checkable.py,sha256=
|
|
15
|
+
archunitpython/common/fluentapi/checkable.py,sha256=6Tsxtycc27-LaeE6cTtQF6NfepFzhgmCrFJAosN_chs,892
|
|
16
16
|
archunitpython/common/logging/__init__.py,sha256=u3-2_jYmiyoQ-C534SmQXvR1L9h3lbJqA9Yt1Nmv9HA,115
|
|
17
17
|
archunitpython/common/logging/types.py,sha256=wUriZeaUawA3JoBfJVLC6lIMglbLG955nXWdJGwxW4I,425
|
|
18
18
|
archunitpython/common/projection/__init__.py,sha256=-Sx-b80b2N3ap3ahAcLUCXqYYK3ccgTDpV-K1jSOSYQ,797
|
|
19
|
-
archunitpython/common/projection/edge_projections.py,sha256=
|
|
19
|
+
archunitpython/common/projection/edge_projections.py,sha256=Mud8DL6Y8H66CObqyikKYAxdXMRENuAFRtwhCxpwxoU,1524
|
|
20
20
|
archunitpython/common/projection/project_cycles.py,sha256=SA6eXzy599dJMvAOA6K1ONkOaFLiEXw8qixpgybtW-I,3105
|
|
21
21
|
archunitpython/common/projection/project_edges.py,sha256=v7hDMSeghiLz0xHbG4BNF7jNQphcWobU7rgoiuw3fh4,1268
|
|
22
22
|
archunitpython/common/projection/project_nodes.py,sha256=U6sLYvJd6NBgg39V0Ry7r_-57gdXaaXsbH-D12nipCg,1497
|
|
@@ -31,13 +31,14 @@ archunitpython/common/util/__init__.py,sha256=g-W8kWiVqwdohxm74J3yUonPkb_yDUJrp7
|
|
|
31
31
|
archunitpython/common/util/declaration_detector.py,sha256=XgrpgaUIQa9MNFlnhVQz2X_uW7zCO9nrMbGa3tVFyPM,3407
|
|
32
32
|
archunitpython/common/util/logger.py,sha256=QT6ir8caMXu4VQombe0NjaT2NUm58kFdlnps4T5ECCE,3348
|
|
33
33
|
archunitpython/files/__init__.py,sha256=wgl8IOqTeQGpNISu-Q8b_j6rTn8aEgoz6t1S5j8z13g,108
|
|
34
|
-
archunitpython/files/assertion/__init__.py,sha256=
|
|
34
|
+
archunitpython/files/assertion/__init__.py,sha256=K2qiEFfmo6SCgxfOKNrPzYgT5ScKUaw2W2CrDa3jBTw,1068
|
|
35
35
|
archunitpython/files/assertion/custom_file_logic.py,sha256=ygpc2NZghHBD-GTGrQW_dWzGZr_9DSvi0denC-cdwuo,3054
|
|
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
|
|
37
38
|
archunitpython/files/assertion/depend_on_files.py,sha256=B-zyFyXCt2ywCzO0BIH1lRGsre6PkAItv2ZfpM_u2Js,2132
|
|
38
39
|
archunitpython/files/assertion/matching_files.py,sha256=qNbvU2o_MM6rzM-YUdJZzkltVbenWGC0u5kLH7su6CA,2003
|
|
39
40
|
archunitpython/files/fluentapi/__init__.py,sha256=wgl8IOqTeQGpNISu-Q8b_j6rTn8aEgoz6t1S5j8z13g,108
|
|
40
|
-
archunitpython/files/fluentapi/files.py,sha256=
|
|
41
|
+
archunitpython/files/fluentapi/files.py,sha256=uX__VDed_TLNiibK2pTMaPQ8RaCyyFf2ZClqdymvs98,17214
|
|
41
42
|
archunitpython/metrics/__init__.py,sha256=HD72MWF0hCh2LzKfyk3mMJp2tf7TJebpwTtZ_kppjso,84
|
|
42
43
|
archunitpython/metrics/assertion/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
43
44
|
archunitpython/metrics/assertion/metric_thresholds.py,sha256=dijCzOr5-dhkdK-QAE3DAkfiSBgknZlxtp-ZrBj_Dmk,1268
|
|
@@ -67,9 +68,9 @@ archunitpython/testing/__init__.py,sha256=MJm6CHGhBGFg1um2L20-GD2DEHKqg8SiUoI-sR
|
|
|
67
68
|
archunitpython/testing/assertion.py,sha256=YTiNWHIQu4xlSqmlvqj1L-Z2Oo1Z-wOvN0VyZQB-CZE,1430
|
|
68
69
|
archunitpython/testing/common/__init__.py,sha256=Wc4bC-N4t6giChKjj6wuTGKkb39thcYS_xKWG9paYeY,220
|
|
69
70
|
archunitpython/testing/common/color_utils.py,sha256=2I8Z1SZfWhhgudMgmXY6PPydGxGl35cK_To-GXnSyJg,1226
|
|
70
|
-
archunitpython/testing/common/violation_factory.py,sha256=
|
|
71
|
+
archunitpython/testing/common/violation_factory.py,sha256=wrhsQoTmu70cmgXjjTIJNdXFeN9iQerQCZR4-vaAwuQ,4209
|
|
71
72
|
archunitpython/testing/pytest_plugin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
72
|
-
archunitpython-1.
|
|
73
|
-
archunitpython-1.
|
|
74
|
-
archunitpython-1.
|
|
75
|
-
archunitpython-1.
|
|
73
|
+
archunitpython-1.1.0.dist-info/METADATA,sha256=Zx-869M7EX16qfaZJEhmRchJb31X9tB_TyGn7WWmZuk,19810
|
|
74
|
+
archunitpython-1.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
75
|
+
archunitpython-1.1.0.dist-info/licenses/LICENSE,sha256=kaQWfzfHk45CNIx4sIW7Uf1sNW5rmo6BpZ-R8GruuK0,1102
|
|
76
|
+
archunitpython-1.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|