archunitpython 1.2.1__py3-none-any.whl → 1.3.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.
@@ -1,6 +1,6 @@
1
1
  """ArchUnitPython - Architecture testing library for Python projects."""
2
2
 
3
- __version__ = "1.2.1"
3
+ __version__ = "1.3.0"
4
4
 
5
5
  # Files API
6
6
  # Common
@@ -1,6 +1,10 @@
1
1
  from archunitpython.common.assertion.violation import EmptyTestViolation, Violation
2
2
  from archunitpython.common.error.errors import TechnicalError, UserError
3
- from archunitpython.common.fluentapi.checkable import Checkable, CheckOptions
3
+ from archunitpython.common.fluentapi.checkable import (
4
+ Checkable,
5
+ CheckOptions,
6
+ RuleRationaleMixin,
7
+ )
4
8
  from archunitpython.common.logging.types import LoggingOptions
5
9
  from archunitpython.common.types import Filter, Pattern, PatternMatchingOptions
6
10
 
@@ -11,6 +15,7 @@ __all__ = [
11
15
  "UserError",
12
16
  "Checkable",
13
17
  "CheckOptions",
18
+ "RuleRationaleMixin",
14
19
  "LoggingOptions",
15
20
  "Pattern",
16
21
  "Filter",
@@ -1,3 +1,7 @@
1
- from archunitpython.common.fluentapi.checkable import Checkable, CheckOptions
1
+ from archunitpython.common.fluentapi.checkable import (
2
+ Checkable,
3
+ CheckOptions,
4
+ RuleRationaleMixin,
5
+ )
2
6
 
3
- __all__ = ["Checkable", "CheckOptions"]
7
+ __all__ = ["Checkable", "CheckOptions", "RuleRationaleMixin"]
@@ -3,7 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from dataclasses import dataclass
6
- from typing import Protocol
6
+ from typing import Protocol, TypeVar
7
7
 
8
8
  from archunitpython.common.assertion.violation import Violation
9
9
  from archunitpython.common.logging.types import LoggingOptions
@@ -19,6 +19,28 @@ class CheckOptions:
19
19
  ignore_type_checking_imports: bool = False
20
20
 
21
21
 
22
+ T = TypeVar("T", bound="RuleRationaleMixin")
23
+
24
+
25
+ class RuleRationaleMixin:
26
+ """Mixin for checkable rules that can carry a human-readable rationale."""
27
+
28
+ _because_reason: str | None = None
29
+
30
+ def because(self: T, reason: str) -> T:
31
+ """Attach a rationale explaining why the rule exists."""
32
+ reason = reason.strip()
33
+ if not reason:
34
+ raise ValueError("Rule rationale must not be empty.")
35
+ self._because_reason = reason
36
+ return self
37
+
38
+ @property
39
+ def because_reason(self) -> str | None:
40
+ """Return the rationale attached with because(), if any."""
41
+ return self._because_reason
42
+
43
+
22
44
  class Checkable(Protocol):
23
45
  """Protocol for any architecture rule that can be checked.
24
46
 
@@ -14,7 +14,7 @@ from collections.abc import Sequence
14
14
 
15
15
  from archunitpython.common.assertion.violation import EmptyTestViolation, Violation
16
16
  from archunitpython.common.extraction.extract_graph import extract_graph
17
- from archunitpython.common.fluentapi.checkable import CheckOptions
17
+ from archunitpython.common.fluentapi.checkable import CheckOptions, RuleRationaleMixin
18
18
  from archunitpython.common.pattern_matching import matches_all_patterns
19
19
  from archunitpython.common.projection.edge_projections import (
20
20
  per_external_edge,
@@ -322,7 +322,7 @@ def _check_empty_test(
322
322
  return None
323
323
 
324
324
 
325
- class CycleFreeFileCondition:
325
+ class CycleFreeFileCondition(RuleRationaleMixin):
326
326
  """Checkable that verifies no cycles exist among filtered files."""
327
327
 
328
328
  def __init__(self, project_path: str | None, filters: list[Filter]) -> None:
@@ -350,7 +350,7 @@ class CycleFreeFileCondition:
350
350
  return gather_cycle_violations(cycles)
351
351
 
352
352
 
353
- class DependOnFileCondition:
353
+ class DependOnFileCondition(RuleRationaleMixin):
354
354
  """Checkable that verifies file dependency rules."""
355
355
 
356
356
  def __init__(
@@ -377,7 +377,7 @@ class DependOnFileCondition:
377
377
  )
378
378
 
379
379
 
380
- class DependOnExternalModuleCondition:
380
+ class DependOnExternalModuleCondition(RuleRationaleMixin):
381
381
  """Checkable that verifies external module dependency rules."""
382
382
 
383
383
  def __init__(
@@ -409,7 +409,7 @@ class DependOnExternalModuleCondition:
409
409
  )
410
410
 
411
411
 
412
- class MatchPatternFileCondition:
412
+ class MatchPatternFileCondition(RuleRationaleMixin):
413
413
  """Checkable that verifies files match/don't match patterns."""
414
414
 
415
415
  def __init__(
@@ -434,7 +434,7 @@ class MatchPatternFileCondition:
434
434
  return gather_regex_matching_violations(nodes, self._check_filters, self._is_negated)
435
435
 
436
436
 
437
- class CustomFileCheckableCondition:
437
+ class CustomFileCheckableCondition(RuleRationaleMixin):
438
438
  """Checkable that evaluates a custom condition on files."""
439
439
 
440
440
  def __init__(
@@ -11,7 +11,7 @@ from __future__ import annotations
11
11
  from typing import Any, Callable
12
12
 
13
13
  from archunitpython.common.assertion.violation import Violation
14
- from archunitpython.common.fluentapi.checkable import CheckOptions
14
+ from archunitpython.common.fluentapi.checkable import CheckOptions, RuleRationaleMixin
15
15
  from archunitpython.common.pattern_matching import matches_pattern_classname
16
16
  from archunitpython.common.regex_factory import RegexFactory
17
17
  from archunitpython.common.types import Filter, Pattern
@@ -170,7 +170,7 @@ class ClassMetricThresholdBuilder:
170
170
  )
171
171
 
172
172
 
173
- class ClassMetricCondition:
173
+ class ClassMetricCondition(RuleRationaleMixin):
174
174
  """Checkable that verifies a class-level metric threshold."""
175
175
 
176
176
  def __init__(
@@ -230,7 +230,7 @@ class FileMetricThresholdBuilder:
230
230
  )
231
231
 
232
232
 
233
- class FileMetricCondition:
233
+ class FileMetricCondition(RuleRationaleMixin):
234
234
  """Checkable that verifies a file-level metric threshold."""
235
235
 
236
236
  def __init__(
@@ -364,7 +364,7 @@ class DistanceThresholdBuilder:
364
364
  )
365
365
 
366
366
 
367
- class DistanceCondition:
367
+ class DistanceCondition(RuleRationaleMixin):
368
368
  """Checkable for distance metric thresholds."""
369
369
 
370
370
  def __init__(
@@ -404,7 +404,7 @@ class DistanceCondition:
404
404
  return violations
405
405
 
406
406
 
407
- class ZoneCondition:
407
+ class ZoneCondition(RuleRationaleMixin):
408
408
  """Checkable for zone detection (pain/uselessness)."""
409
409
 
410
410
  def __init__(self, project_path: str | None, filters: list[Filter], zone_type: str) -> None:
@@ -485,7 +485,7 @@ class CustomMetricsBuilder:
485
485
  )
486
486
 
487
487
 
488
- class CustomMetricCondition:
488
+ class CustomMetricCondition(RuleRationaleMixin):
489
489
  """Checkable for custom metric thresholds."""
490
490
 
491
491
  def __init__(
@@ -525,7 +525,7 @@ class CustomMetricCondition:
525
525
  return violations
526
526
 
527
527
 
528
- class CustomAssertionCondition:
528
+ class CustomAssertionCondition(RuleRationaleMixin):
529
529
  """Checkable for custom metric assertions."""
530
530
 
531
531
  def __init__(
@@ -14,7 +14,7 @@ import re
14
14
 
15
15
  from archunitpython.common.assertion.violation import Violation
16
16
  from archunitpython.common.extraction.extract_graph import extract_graph
17
- from archunitpython.common.fluentapi.checkable import CheckOptions
17
+ from archunitpython.common.fluentapi.checkable import CheckOptions, RuleRationaleMixin
18
18
  from archunitpython.common.projection.project_edges import project_edges
19
19
  from archunitpython.common.projection.types import MapFunction
20
20
  from archunitpython.slices.assertion.admissible_edges import (
@@ -140,7 +140,7 @@ class NegativeConditionBuilder:
140
140
  )
141
141
 
142
142
 
143
- class PositiveSliceCondition:
143
+ class PositiveSliceCondition(RuleRationaleMixin):
144
144
  """Checkable that verifies slices adhere to a diagram."""
145
145
 
146
146
  def __init__(
@@ -176,7 +176,7 @@ class PositiveSliceCondition:
176
176
  return identity()
177
177
 
178
178
 
179
- class NegativeSliceCondition:
179
+ class NegativeSliceCondition(RuleRationaleMixin):
180
180
  """Checkable that verifies a specific dependency does NOT exist."""
181
181
 
182
182
  def __init__(
@@ -7,7 +7,11 @@ from archunitpython.common.fluentapi.checkable import Checkable, CheckOptions
7
7
  from archunitpython.testing.common.violation_factory import ViolationFactory
8
8
 
9
9
 
10
- def format_violations(violations: list[Violation]) -> str:
10
+ def format_violations(
11
+ violations: list[Violation],
12
+ *,
13
+ because: str | None = None,
14
+ ) -> str:
11
15
  """Format violations into a human-readable string.
12
16
 
13
17
  Args:
@@ -19,7 +23,10 @@ def format_violations(violations: list[Violation]) -> str:
19
23
  if not violations:
20
24
  return "No violations found."
21
25
 
22
- lines = [f"Found {len(violations)} architecture violation(s):", ""]
26
+ lines = [f"Found {len(violations)} architecture violation(s):"]
27
+ if because:
28
+ lines.extend(["", f"Because: {because}"])
29
+ lines.append("")
23
30
  for i, violation in enumerate(violations, 1):
24
31
  tv = ViolationFactory.from_violation(violation)
25
32
  lines.append(f" {i}. {tv.message}")
@@ -44,4 +51,5 @@ def assert_passes(
44
51
  """
45
52
  violations = checkable.check(options)
46
53
  if violations:
47
- raise AssertionError(format_violations(violations))
54
+ because = getattr(checkable, "because_reason", None)
55
+ raise AssertionError(format_violations(violations, because=because))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: archunitpython
3
- Version: 1.2.1
3
+ Version: 1.3.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
@@ -188,6 +188,25 @@ options = CheckOptions(
188
188
  violations = rule.check(options)
189
189
  ```
190
190
 
191
+ ### Explaining Rules With `.because(...)`
192
+
193
+ Attach a rationale to a rule so failing assertions explain why the rule exists:
194
+
195
+ ```python
196
+ rule = (
197
+ project_files("src/")
198
+ .in_folder("**/controllers/**")
199
+ .should_not()
200
+ .depend_on_files()
201
+ .in_folder("**/database/**")
202
+ .because("controllers should stay thin and delegate persistence")
203
+ )
204
+
205
+ assert_passes(rule)
206
+ ```
207
+
208
+ When the rule fails, the rationale is included in the assertion message.
209
+
191
210
  ## 🐹 Use Cases
192
211
 
193
212
  Here is an overview of common use cases.
@@ -431,21 +450,113 @@ def test_no_forbidden_dependency():
431
450
 
432
451
  Generate dependency graph reports in multiple formats and narrow them to the part of the codebase you want to inspect.
433
452
 
453
+ **Using `requests` library repo for example**
454
+
434
455
  ```python
435
456
  from archunitpython import project_graph
436
457
 
437
458
  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
459
+ graph = project_graph("src/requests").titled("Application Architecture")
460
+
461
+ graph.collapse_to_folder_depth(2).export_as_mermaid("reports/dependencies.md")
462
+
463
+ if __name__ == "__main__":
464
+ test_export_dependency_graph_reports()
465
+ ```
466
+ **Rendered mermain diagram**
467
+ ``` mermaid
468
+ flowchart LR
469
+ n0["__init__.py"]
470
+ n1["__version__.py"]
471
+ n2["_internal_utils.py"]
472
+ n3["_types.py"]
473
+ n4["adapters.py"]
474
+ n5["api.py"]
475
+ n6["auth.py"]
476
+ n7["certs.py"]
477
+ n8["compat.py"]
478
+ n9["cookies.py"]
479
+ n10["exceptions.py"]
480
+ n11["help.py"]
481
+ n12["hooks.py"]
482
+ n13["models.py"]
483
+ n14["packages.py"]
484
+ n15["sessions.py"]
485
+ n16["status_codes.py"]
486
+ n17["structures.py"]
487
+ n18["utils.py"]
488
+ n0 --> n1
489
+ n0 --> n5
490
+ n0 --> n10
491
+ n0 --> n13
492
+ n0 --> n15
493
+ n0 --> n16
494
+ n2 --> n8
495
+ n3 --> n6
496
+ n3 --> n9
497
+ n3 --> n13
498
+ n3 --> n17
499
+ n4 --> n0
500
+ n4 --> n3
501
+ n4 --> n6
502
+ n4 --> n8
503
+ n4 --> n9
504
+ n4 --> n10
505
+ n4 --> n13
506
+ n4 --> n17
507
+ n4 --> n18
508
+ n5 --> n0
509
+ n5 --> n13
510
+ n6 --> n2
511
+ n6 --> n8
512
+ n6 --> n9
513
+ n6 --> n13
514
+ n6 --> n18
515
+ n9 --> n2
516
+ n9 --> n3
517
+ n9 --> n8
518
+ n9 --> n13
519
+ n10 --> n8
520
+ n10 --> n13
521
+ n11 --> n0
522
+ n12 --> n0
523
+ n12 --> n13
524
+ n13 --> n0
525
+ n13 --> n2
526
+ n13 --> n4
527
+ n13 --> n6
528
+ n13 --> n8
529
+ n13 --> n9
530
+ n13 --> n10
531
+ n13 --> n12
532
+ n13 --> n16
533
+ n13 --> n17
534
+ n13 --> n18
535
+ n14 --> n8
536
+ n15 --> n0
537
+ n15 --> n2
538
+ n15 --> n3
539
+ n15 --> n4
540
+ n15 --> n6
541
+ n15 --> n8
542
+ n15 --> n9
543
+ n15 --> n10
544
+ n15 --> n12
545
+ n15 --> n13
546
+ n15 --> n16
547
+ n15 --> n17
548
+ n15 --> n18
549
+ n16 --> n17
550
+ n17 --> n8
551
+ n18 --> n0
552
+ n18 --> n1
553
+ n18 --> n2
554
+ n18 --> n3
555
+ n18 --> n8
556
+ n18 --> n9
557
+ n18 --> n10
558
+ n18 --> n13
559
+ n18 --> n17
449
560
  ```
450
561
 
451
562
  Supported formats:
@@ -1,6 +1,6 @@
1
- archunitpython/__init__.py,sha256=w__UDj9GojwOMtYX5eSZCpd4WYiIKjWGJ6c-8nRlPSI,1154
1
+ archunitpython/__init__.py,sha256=alLY-bGp-tUtdb8BRV0r8K-qIZKkWYnJ5K-mTDnFOrQ,1154
2
2
  archunitpython/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- archunitpython/common/__init__.py,sha256=u8jwbfALwIT_5ZqTrRchpZqkFHG5tTwM21LX5hR9ZSc,593
3
+ archunitpython/common/__init__.py,sha256=TKL39Z0kBpWqMH99jU4LsDSUZ5lQ_rcAJfLnmUTDTOI,656
4
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
@@ -11,8 +11,8 @@ archunitpython/common/error/errors.py,sha256=y7mcXoZPyK7uD2dMMO1qBt1y7KcIeGlRYiV
11
11
  archunitpython/common/extraction/__init__.py,sha256=RkJOcxJoLYQxEagh3uWhjsUCprK3Nr3Bn3o7nmzk4_Q,284
12
12
  archunitpython/common/extraction/extract_graph.py,sha256=HIfAZLZiv4Zbi1Nm8jmNnnu8ggn0wQXunBlZP_QK1x8,15254
13
13
  archunitpython/common/extraction/graph.py,sha256=Rk-0eDDOLoHvScO27J2JzXjyMq3e5eKtrHnFBh5B6SU,1052
14
- archunitpython/common/fluentapi/__init__.py,sha256=J7PDgqBXQOpXqCMCGRyFNil0dCulufmhfirzvYvh-gk,119
15
- archunitpython/common/fluentapi/checkable.py,sha256=6Tsxtycc27-LaeE6cTtQF6NfepFzhgmCrFJAosN_chs,892
14
+ archunitpython/common/fluentapi/__init__.py,sha256=LeS7qS2p9-FqqBhDL8xRPex__W5Qk0UWfcpl7nVVLfI,178
15
+ archunitpython/common/fluentapi/checkable.py,sha256=BJFYibVhHLMFlnWdISPCIL3DYI1_3JN2-1jEQOaVaGE,1547
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
@@ -38,7 +38,7 @@ archunitpython/files/assertion/depend_on_external_modules.py,sha256=BXGpN-301YOc
38
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=MsXY-763W9wVrtU50mDs_cuaErWRHk1MehbbAit4Je8,17032
41
+ archunitpython/files/fluentapi/files.py,sha256=oZG0lWV6p0AiGANdoZfYd51H8zY-J4eTSPRTRPBYhs0,17152
42
42
  archunitpython/graph/__init__.py,sha256=vm1jMOoN35IIU7YDs59qPtf_F82YV-QrEGfXhozAOek,756
43
43
  archunitpython/graph/graph_reporter.py,sha256=D_KH01CM7TzeMFB6o5NIQfLVJq0rvKZn9l7WumXV6lo,25598
44
44
  archunitpython/layers/__init__.py,sha256=DCRxqLhluTxTaT9ZM2MbfAdJVgqcOO9jtkZHzBbeLOw,164
@@ -59,25 +59,25 @@ archunitpython/metrics/extraction/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeR
59
59
  archunitpython/metrics/extraction/extract_class_info.py,sha256=IFokUFwNaExmPtKnHW5hgnYWodRtBM3cWhXBGb7lcjs,7751
60
60
  archunitpython/metrics/fluentapi/__init__.py,sha256=HD72MWF0hCh2LzKfyk3mMJp2tf7TJebpwTtZ_kppjso,84
61
61
  archunitpython/metrics/fluentapi/export_utils.py,sha256=1r-zTQAUqn_agp4_lhbcffdzfdASNY3LebYvKAG9kcQ,2333
62
- archunitpython/metrics/fluentapi/metrics.py,sha256=tvaMctIJAjqHhGT62u5LbZImJFCGIsoJ3Z6cdiY6zTs,19198
62
+ archunitpython/metrics/fluentapi/metrics.py,sha256=EaH1seQKppXyx7DiPz1D-S1YYRt48OBWqdKn47BQhoA,19338
63
63
  archunitpython/metrics/projection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
64
  archunitpython/slices/__init__.py,sha256=tb8MoZiEqIdmWy7uyhmEtMNm5Fxjuw6atSvDsD131DE,96
65
65
  archunitpython/slices/assertion/__init__.py,sha256=MRwV3d69ljAJ7hFYdxI6UDNC8U4Dm1ImeuLUVKEC9To,280
66
66
  archunitpython/slices/assertion/admissible_edges.py,sha256=-3o5mGtl81i5I_572x3Z4ZDfqPCyFqjGd7Dg8GRSKhY,3119
67
67
  archunitpython/slices/fluentapi/__init__.py,sha256=tb8MoZiEqIdmWy7uyhmEtMNm5Fxjuw6atSvDsD131DE,96
68
- archunitpython/slices/fluentapi/slices.py,sha256=5Q6HbUqzz3xSyeeI3iLqMYRX-LXbu5xOc806MWqqYro,7103
68
+ archunitpython/slices/fluentapi/slices.py,sha256=vNoyqmleTDTjnf2i35i2nte-Ycjm-oapfgaf3AhN0QI,7163
69
69
  archunitpython/slices/projection/__init__.py,sha256=tVgcK4gw-bqhUq98vU7_iPE0NEhOPUr7vr1-p7JI1A4,237
70
70
  archunitpython/slices/projection/slicing_projections.py,sha256=BHBkuVG80mqzT7N4FlCCfY5U_NvlXmAgTmHf_SPTXVM,4215
71
71
  archunitpython/slices/uml/__init__.py,sha256=GQFA5WBKfi_YElWiNWNm9c9IM-VaW83_Cg6kpwkzxkw,196
72
72
  archunitpython/slices/uml/export_diagram.py,sha256=FeBRV8Vt8LuhLqEbg5JzZOmEk2i49JPkozMcI5r335g,818
73
73
  archunitpython/slices/uml/generate_rules.py,sha256=D9vvqDzHAM0F80z4u5yBalEqIiNfJJ5HGXP0fVlSzHw,2136
74
74
  archunitpython/testing/__init__.py,sha256=MJm6CHGhBGFg1um2L20-GD2DEHKqg8SiUoI-sRsoXQk,128
75
- archunitpython/testing/assertion.py,sha256=YTiNWHIQu4xlSqmlvqj1L-Z2Oo1Z-wOvN0VyZQB-CZE,1430
75
+ archunitpython/testing/assertion.py,sha256=7cXlNwBklIGAyUJlPGFGAw97xZ9UgpkZvoO_QBdqm1c,1637
76
76
  archunitpython/testing/common/__init__.py,sha256=Wc4bC-N4t6giChKjj6wuTGKkb39thcYS_xKWG9paYeY,220
77
77
  archunitpython/testing/common/color_utils.py,sha256=2I8Z1SZfWhhgudMgmXY6PPydGxGl35cK_To-GXnSyJg,1226
78
78
  archunitpython/testing/common/violation_factory.py,sha256=yWlvv2U7u-7KoTMfp1QCeJXxTLpPEagKqDHZmPSyrlk,4677
79
79
  archunitpython/testing/pytest_plugin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
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,,
80
+ archunitpython-1.3.0.dist-info/METADATA,sha256=79jbCuDyAMQr3aY3A_fesygIwS8hF8ceYaPRzJvUmrU,30275
81
+ archunitpython-1.3.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
82
+ archunitpython-1.3.0.dist-info/licenses/LICENSE,sha256=kaQWfzfHk45CNIx4sIW7Uf1sNW5rmo6BpZ-R8GruuK0,1102
83
+ archunitpython-1.3.0.dist-info/RECORD,,