pytestarch 3.1.0__tar.gz → 4.0.0__tar.gz
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.
- {pytestarch-3.1.0 → pytestarch-4.0.0}/PKG-INFO +13 -17
- pytestarch-4.0.0/pyproject.toml +79 -0
- pytestarch-4.0.0/src/pytestarch/__init__.py +22 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/diagram_extension/dependency_to_rule_converter.py +1 -1
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/diagram_extension/diagram_rule.py +1 -1
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure/breadth_first_searches.py +10 -4
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure/module_name_converter.py +3 -2
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure_generation/file_import/converter.py +18 -2
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/query_language/base_language.py +1 -2
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/query_language/layered_architecture_rule.py +8 -2
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/query_language/multiple_rule_applier.py +1 -1
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/query_language/rule.py +10 -8
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/rule_assessment/rule_check/rule_matcher.py +3 -9
- pytestarch-3.1.0/pyproject.toml +0 -63
- pytestarch-3.1.0/setup.py +0 -48
- pytestarch-3.1.0/src/pytestarch/__init__.py +0 -13
- {pytestarch-3.1.0 → pytestarch-4.0.0}/LICENSE +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/README.md +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/diagram_extension/__init__.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/diagram_extension/diagram_parser.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/diagram_extension/exceptions.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/diagram_extension/parsed_dependencies.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure/__init__.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure/evaluable_architecture.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure/evaluable_graph.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure/evaluable_structures.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure/exceptions.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure/networkxgraph.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure/types.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure/utils.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure_generation/__init__.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure_generation/file_import/__init__.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure_generation/file_import/config.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure_generation/file_import/exceptions.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure_generation/file_import/file_filter.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure_generation/file_import/import_filter.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure_generation/file_import/import_types.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure_generation/file_import/importee_module_calculator.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure_generation/file_import/parser.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure_generation/graph_generation/__init__.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure_generation/graph_generation/graph_generator.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/py.typed +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/pytestarch.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/query_language/LANGUAGE_DEFINTION.md +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/query_language/__init__.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/query_language/exceptions.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/rule_assessment/__init__.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/rule_assessment/error_message/__init__.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/rule_assessment/error_message/message_generator.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/rule_assessment/exceptions.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/rule_assessment/rule_check/__init__.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/rule_assessment/rule_check/behavior_requirement.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/rule_assessment/rule_check/layer_rule_violation_detector.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/rule_assessment/rule_check/module_requirement.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/rule_assessment/rule_check/rule_violation_detector.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/rule_assessment/rule_check/rule_violations.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/utils/__init__.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/utils/decorators.py +0 -0
- {pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/utils/partial_match_to_regex_converter.py +0 -0
|
@@ -1,34 +1,30 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
2
|
-
Name:
|
|
3
|
-
Version:
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: PyTestArch
|
|
3
|
+
Version: 4.0.0
|
|
4
4
|
Summary: Test framework for software architecture based on imports between modules
|
|
5
|
-
Home-page: https://github.com/zyskarch/pytestarch
|
|
6
5
|
License: Apache-2.0
|
|
7
6
|
Keywords: architecture,test
|
|
8
7
|
Author: zyskarch
|
|
9
8
|
Author-email: zyskarch@gmail.com
|
|
10
9
|
Maintainer: zyskarch
|
|
11
10
|
Maintainer-email: zyskarch@gmail.com
|
|
12
|
-
Requires-Python: >=3.9
|
|
13
|
-
Classifier:
|
|
14
|
-
Classifier:
|
|
15
|
-
Classifier: Operating System :: OS Independent
|
|
16
|
-
Classifier: Programming Language :: Python :: 3
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Requires-Python: >=3.9
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
20
15
|
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
23
16
|
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Intended Audience :: Developers
|
|
24
20
|
Classifier: Topic :: Software Development :: Testing
|
|
25
21
|
Classifier: Topic :: Software Development :: Testing :: Unit
|
|
26
22
|
Provides-Extra: visualization
|
|
27
|
-
Requires-Dist: matplotlib (>=3.9
|
|
28
|
-
Requires-Dist: networkx (>=3.2
|
|
29
|
-
Project-URL:
|
|
30
|
-
Project-URL: Documentation, https://zyskarch.github.io/pytestarch/
|
|
23
|
+
Requires-Dist: matplotlib (>=3.9) ; extra == "visualization"
|
|
24
|
+
Requires-Dist: networkx (>=3.2)
|
|
25
|
+
Project-URL: Documentation, https://zyskarch.github.io/pytestarch/latest
|
|
31
26
|
Project-URL: Repository, https://github.com/zyskarch/pytestarch
|
|
27
|
+
Project-URL: issues, https://github.com/zyskarch/pytestarch/issues
|
|
32
28
|
Description-Content-Type: text/markdown
|
|
33
29
|
|
|
34
30
|
# Welcome to PyTestArch
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "PyTestArch"
|
|
3
|
+
version = "4.0.0"
|
|
4
|
+
requires-python = ">=3.9"
|
|
5
|
+
description = "Test framework for software architecture based on imports between modules"
|
|
6
|
+
authors = [{ name = "zyskarch", email = "zyskarch@gmail.com" }]
|
|
7
|
+
maintainers = [{ name = "zyskarch", email = "zyskarch@gmail.com" }]
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
license = "Apache-2.0"
|
|
10
|
+
|
|
11
|
+
keywords = ["architecture", "test"]
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Programming Language :: Python :: 3.13",
|
|
14
|
+
"Programming Language :: Python :: 3.12",
|
|
15
|
+
"Programming Language :: Python :: 3.11",
|
|
16
|
+
"Programming Language :: Python :: 3.10",
|
|
17
|
+
"Programming Language :: Python :: 3.9",
|
|
18
|
+
"License :: OSI Approved :: Apache Software License",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Intended Audience :: Developers",
|
|
21
|
+
"Topic :: Software Development :: Testing",
|
|
22
|
+
"Topic :: Software Development :: Testing :: Unit",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
dependencies = ["networkx>=3.2"]
|
|
26
|
+
|
|
27
|
+
[project.optional-dependencies]
|
|
28
|
+
visualization = ["matplotlib>=3.9"]
|
|
29
|
+
|
|
30
|
+
[project.urls]
|
|
31
|
+
issues = "https://github.com/zyskarch/pytestarch/issues"
|
|
32
|
+
documentation = "https://zyskarch.github.io/pytestarch/latest"
|
|
33
|
+
repository = "https://github.com/zyskarch/pytestarch"
|
|
34
|
+
|
|
35
|
+
[tool.poetry.group.dev.dependencies]
|
|
36
|
+
mkdocs = "1.6.0"
|
|
37
|
+
mkdocstrings-python = "1.10.3"
|
|
38
|
+
mkdocs-material = "9.5.25"
|
|
39
|
+
mkdocs-autorefs = "1.0.1"
|
|
40
|
+
mkdocs-material-extensions = "1.3.1"
|
|
41
|
+
mkdocstrings = "0.25.1"
|
|
42
|
+
griffe = "0.45.2"
|
|
43
|
+
nox = "2024.4.15"
|
|
44
|
+
pre-commit = "3.7.1"
|
|
45
|
+
pytest = "^8.2.1"
|
|
46
|
+
coverage = "^7.5.2"
|
|
47
|
+
mike = "2.1.1"
|
|
48
|
+
ruff = "^0.7.0"
|
|
49
|
+
|
|
50
|
+
[build-system]
|
|
51
|
+
requires = ["poetry-core>=2.0"]
|
|
52
|
+
build-backend = "poetry.core.masonry.api"
|
|
53
|
+
|
|
54
|
+
[tool.ruff]
|
|
55
|
+
line-length = 88
|
|
56
|
+
|
|
57
|
+
[tool.ruff.lint]
|
|
58
|
+
select = [
|
|
59
|
+
"F", # Pyflakes
|
|
60
|
+
"E",
|
|
61
|
+
"W", # Pylint Error, Warning
|
|
62
|
+
"UP", # pyupgrade
|
|
63
|
+
"FURB", # refurb
|
|
64
|
+
"S", # flake8-bandit
|
|
65
|
+
"I", # isort
|
|
66
|
+
"RUF100", # Unneeded noqa
|
|
67
|
+
]
|
|
68
|
+
ignore = [
|
|
69
|
+
"E501", # line too long -> handled by formatter
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
[tool.ruff.lint.per-file-ignores]
|
|
73
|
+
"tests/*.py" = [
|
|
74
|
+
"S101", # assert statement
|
|
75
|
+
"E743", # ambiguous function name
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
[tool.ruff.lint.isort]
|
|
79
|
+
known-first-party = ["integration", "resources", "query_language"]
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from pytestarch.diagram_extension.diagram_rule import DiagramRule
|
|
2
|
+
from pytestarch.eval_structure.evaluable_architecture import EvaluableArchitecture
|
|
3
|
+
from pytestarch.query_language.layered_architecture_rule import (
|
|
4
|
+
LayeredArchitecture,
|
|
5
|
+
LayerRule,
|
|
6
|
+
)
|
|
7
|
+
from pytestarch.query_language.rule import Rule
|
|
8
|
+
|
|
9
|
+
from .pytestarch import (
|
|
10
|
+
get_evaluable_architecture,
|
|
11
|
+
get_evaluable_architecture_for_module_objects,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"DiagramRule",
|
|
16
|
+
"EvaluableArchitecture",
|
|
17
|
+
"get_evaluable_architecture",
|
|
18
|
+
"get_evaluable_architecture_for_module_objects",
|
|
19
|
+
"LayeredArchitecture",
|
|
20
|
+
"LayerRule",
|
|
21
|
+
"Rule",
|
|
22
|
+
]
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from pytestarch import Rule
|
|
4
3
|
from pytestarch.diagram_extension.parsed_dependencies import ParsedDependencies
|
|
5
4
|
from pytestarch.query_language.base_language import RuleApplier
|
|
5
|
+
from pytestarch.query_language.rule import Rule
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class DependencyToRuleConverter:
|
|
@@ -2,12 +2,12 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
|
-
from pytestarch import EvaluableArchitecture
|
|
6
5
|
from pytestarch.diagram_extension.dependency_to_rule_converter import (
|
|
7
6
|
DependencyToRuleConverter,
|
|
8
7
|
)
|
|
9
8
|
from pytestarch.diagram_extension.diagram_parser import PumlParser
|
|
10
9
|
from pytestarch.diagram_extension.parsed_dependencies import ParsedDependencies
|
|
10
|
+
from pytestarch.eval_structure.evaluable_graph import EvaluableArchitecture
|
|
11
11
|
from pytestarch.query_language.base_language import (
|
|
12
12
|
BaseModuleSpecifier,
|
|
13
13
|
FileRule,
|
{pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure/breadth_first_searches.py
RENAMED
|
@@ -41,7 +41,7 @@ def get_dependency_between_modules(
|
|
|
41
41
|
return dependencies # type: ignore
|
|
42
42
|
|
|
43
43
|
|
|
44
|
-
def any_dependency_to_module_other_than(
|
|
44
|
+
def any_dependency_to_module_other_than(
|
|
45
45
|
graph: AbstractGraph, dependent: ModuleFilter, dependent_upons: set[ModuleFilter]
|
|
46
46
|
) -> list[Dependency]:
|
|
47
47
|
# nodes to exclude are nodes that once reached will not have their submodules analysed next
|
|
@@ -75,7 +75,10 @@ def any_dependency_to_module_other_than( # noqa: C901
|
|
|
75
75
|
# the true submodules are excluded
|
|
76
76
|
# reason: if something imports B, then it imports something that is not B.X (and B.X is a dependent_upon module)
|
|
77
77
|
# (but we do not care if it imports B.X.M, as this is part of B.X)
|
|
78
|
-
|
|
78
|
+
try:
|
|
79
|
+
nodes_to_exclude.remove(dependent_upon.identifier)
|
|
80
|
+
except KeyError:
|
|
81
|
+
pass
|
|
79
82
|
|
|
80
83
|
nodes_to_check = list(nodes_that_do_not_fulfill_criterion)
|
|
81
84
|
checked_nodes = set()
|
|
@@ -106,7 +109,7 @@ def any_dependency_to_module_other_than( # noqa: C901
|
|
|
106
109
|
return nodes_fulfilling_criteria # type: ignore
|
|
107
110
|
|
|
108
111
|
|
|
109
|
-
def any_other_dependency_to_module_than(
|
|
112
|
+
def any_other_dependency_to_module_than(
|
|
110
113
|
graph: AbstractGraph, dependents: set[ModuleFilter], dependent_upon: ModuleFilter
|
|
111
114
|
) -> list[Dependency]:
|
|
112
115
|
# submodules of the dependent upon module do not count as an import that is not the dependent upon module
|
|
@@ -145,7 +148,10 @@ def any_other_dependency_to_module_than( # noqa: C901
|
|
|
145
148
|
# if the dependent module is defined via a parent module, this parent module counts as an allowed import
|
|
146
149
|
# reason: we are looking for dependencies other than module A.X. Parent module A is not (only) A.X, so it counts
|
|
147
150
|
# (submodule A.X.M does not count, as it is not anything else but A.X)
|
|
148
|
-
|
|
151
|
+
try:
|
|
152
|
+
nodes_to_exclude.remove(dependent.identifier)
|
|
153
|
+
except KeyError:
|
|
154
|
+
pass
|
|
149
155
|
|
|
150
156
|
checked_nodes = set()
|
|
151
157
|
|
{pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure/module_name_converter.py
RENAMED
|
@@ -5,9 +5,9 @@ from collections import defaultdict
|
|
|
5
5
|
from collections.abc import Sequence
|
|
6
6
|
from typing import cast
|
|
7
7
|
|
|
8
|
-
from pytestarch import EvaluableArchitecture
|
|
9
8
|
from pytestarch.eval_structure.breadth_first_searches import get_all_submodules_of
|
|
10
9
|
from pytestarch.eval_structure.evaluable_architecture import (
|
|
10
|
+
EvaluableArchitecture,
|
|
11
11
|
Module,
|
|
12
12
|
ModuleFilter,
|
|
13
13
|
ModuleNameFilter,
|
|
@@ -64,7 +64,8 @@ class ModuleNameConverter:
|
|
|
64
64
|
never_matched.remove(module_to_match)
|
|
65
65
|
|
|
66
66
|
submodules_of_match = get_all_submodules_of(
|
|
67
|
-
arch._graph,
|
|
67
|
+
arch._graph, # type: ignore
|
|
68
|
+
converted_module_filter,
|
|
68
69
|
)
|
|
69
70
|
submodules_of_match.remove(
|
|
70
71
|
actually_present_module
|
|
@@ -78,10 +78,26 @@ class ImportConverter:
|
|
|
78
78
|
if isinstance(module, ast.Import):
|
|
79
79
|
new_imports = []
|
|
80
80
|
for alias in module.names:
|
|
81
|
-
new_imports.append(
|
|
81
|
+
new_imports.append(
|
|
82
|
+
AbsoluteImport(
|
|
83
|
+
module_name,
|
|
84
|
+
self._adjust_with_root_prefix(
|
|
85
|
+
alias.name, absolute_import_prefix, all_internal_modules
|
|
86
|
+
),
|
|
87
|
+
)
|
|
88
|
+
) # type: ignore
|
|
82
89
|
elif isinstance(module, ast.ImportFrom):
|
|
83
90
|
if module.level == 0:
|
|
84
|
-
new_imports = [
|
|
91
|
+
new_imports = [
|
|
92
|
+
AbsoluteImport(
|
|
93
|
+
module_name,
|
|
94
|
+
self._adjust_with_root_prefix(
|
|
95
|
+
module.module, # type: ignore
|
|
96
|
+
absolute_import_prefix,
|
|
97
|
+
all_internal_modules,
|
|
98
|
+
),
|
|
99
|
+
)
|
|
100
|
+
]
|
|
85
101
|
else:
|
|
86
102
|
new_imports = []
|
|
87
103
|
for alias in module.names:
|
|
@@ -4,7 +4,7 @@ from abc import ABC, abstractmethod
|
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
from typing import Generic, TypeVar, Union
|
|
6
6
|
|
|
7
|
-
from pytestarch import EvaluableArchitecture
|
|
7
|
+
from pytestarch.eval_structure.evaluable_architecture import EvaluableArchitecture
|
|
8
8
|
from pytestarch.utils.decorators import deprecated
|
|
9
9
|
|
|
10
10
|
|
|
@@ -203,7 +203,6 @@ class LayerName(ABC):
|
|
|
203
203
|
|
|
204
204
|
|
|
205
205
|
class BaseLayeredArchitecture(ABC):
|
|
206
|
-
|
|
207
206
|
@abstractmethod
|
|
208
207
|
def with_layer(self) -> LayerName:
|
|
209
208
|
"""This is simply a convenience method to achieve proper typing. It can be omitted."""
|
{pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/query_language/layered_architecture_rule.py
RENAMED
|
@@ -3,8 +3,8 @@ from __future__ import annotations
|
|
|
3
3
|
from collections.abc import Sequence
|
|
4
4
|
from functools import partial
|
|
5
5
|
|
|
6
|
-
from pytestarch import EvaluableArchitecture, Rule
|
|
7
6
|
from pytestarch.eval_structure.evaluable_architecture import (
|
|
7
|
+
EvaluableArchitecture,
|
|
8
8
|
LayerMapping,
|
|
9
9
|
ModuleFilter,
|
|
10
10
|
ModuleNameFilter,
|
|
@@ -24,6 +24,7 @@ from pytestarch.query_language.base_language import (
|
|
|
24
24
|
RuleApplier,
|
|
25
25
|
)
|
|
26
26
|
from pytestarch.query_language.exceptions import ImproperlyConfigured
|
|
27
|
+
from pytestarch.query_language.rule import Rule
|
|
27
28
|
from pytestarch.rule_assessment.rule_check.rule_matcher import (
|
|
28
29
|
LayerRuleMatcher,
|
|
29
30
|
RuleMatcher,
|
|
@@ -170,7 +171,12 @@ class LayerRule(
|
|
|
170
171
|
"Specify a LayeredArchitecture before defining layer behavior."
|
|
171
172
|
)
|
|
172
173
|
|
|
173
|
-
self._rule = Rule(
|
|
174
|
+
self._rule = Rule(
|
|
175
|
+
rule_matcher_class=partial(
|
|
176
|
+
self._rule_matcher_class,
|
|
177
|
+
layer_mapping=self._architecture.layer_mapping, # type: ignore
|
|
178
|
+
)
|
|
179
|
+
).modules_that()
|
|
174
180
|
|
|
175
181
|
return self
|
|
176
182
|
|
|
@@ -4,8 +4,8 @@ from collections.abc import Sequence
|
|
|
4
4
|
from dataclasses import dataclass, replace
|
|
5
5
|
from typing import Callable
|
|
6
6
|
|
|
7
|
-
from pytestarch import EvaluableArchitecture
|
|
8
7
|
from pytestarch.eval_structure.evaluable_architecture import (
|
|
8
|
+
EvaluableArchitecture,
|
|
9
9
|
ModuleFilter,
|
|
10
10
|
ModuleNameFilter,
|
|
11
11
|
ModuleNameRegexFilter,
|
|
@@ -77,20 +77,20 @@ class Rule(
|
|
|
77
77
|
return self
|
|
78
78
|
|
|
79
79
|
def are_sub_modules_of( # type: ignore
|
|
80
|
-
self, modules: str |
|
|
80
|
+
self, modules: str | Sequence[str]
|
|
81
81
|
) -> BehaviorSpecification:
|
|
82
82
|
self._set_modules(
|
|
83
83
|
modules, lambda name: ParentModuleNameFilter(parent_module=name)
|
|
84
84
|
)
|
|
85
85
|
return self
|
|
86
86
|
|
|
87
|
-
def are_named(self, names: str |
|
|
87
|
+
def are_named(self, names: str | Sequence[str]) -> BehaviorSpecification: # type: ignore
|
|
88
88
|
self._set_modules(names, lambda name: ModuleNameFilter(name=name))
|
|
89
89
|
return self
|
|
90
90
|
|
|
91
91
|
@deprecated
|
|
92
92
|
def have_name_containing(
|
|
93
|
-
self, partial_names: str |
|
|
93
|
+
self, partial_names: str | Sequence[str]
|
|
94
94
|
) -> BehaviorSpecification:
|
|
95
95
|
self._set_modules(
|
|
96
96
|
partial_names,
|
|
@@ -109,7 +109,7 @@ class Rule(
|
|
|
109
109
|
|
|
110
110
|
def _set_modules(
|
|
111
111
|
self,
|
|
112
|
-
module_names: str |
|
|
112
|
+
module_names: str | Sequence[str],
|
|
113
113
|
create_module_fn: Callable[[str], ModuleFilter],
|
|
114
114
|
) -> None:
|
|
115
115
|
if self._modules_to_check_to_be_specified_next is None:
|
|
@@ -124,7 +124,9 @@ class Rule(
|
|
|
124
124
|
else:
|
|
125
125
|
self._configuration.modules_to_check_against = modules
|
|
126
126
|
|
|
127
|
-
def _add_modules(
|
|
127
|
+
def _add_modules(
|
|
128
|
+
self, modules: Sequence[tuple[str, bool]]
|
|
129
|
+
) -> BehaviorSpecification:
|
|
128
130
|
module_names = []
|
|
129
131
|
module_creation_fn = []
|
|
130
132
|
|
|
@@ -143,8 +145,8 @@ class Rule(
|
|
|
143
145
|
|
|
144
146
|
def _append_modules(
|
|
145
147
|
self,
|
|
146
|
-
module_names:
|
|
147
|
-
create_module_fns:
|
|
148
|
+
module_names: Sequence[str],
|
|
149
|
+
create_module_fns: Sequence[Callable[[str], ModuleFilter]],
|
|
148
150
|
) -> None:
|
|
149
151
|
modules = [fn(n) for n, fn in zip(module_names, create_module_fns)]
|
|
150
152
|
if self._modules_to_check_to_be_specified_next:
|
{pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/rule_assessment/rule_check/rule_matcher.py
RENAMED
|
@@ -100,16 +100,10 @@ class RuleMatcher(ABC):
|
|
|
100
100
|
self._behavior_requirement.not_explicitly_requested_dependency_required
|
|
101
101
|
or self._behavior_requirement.not_explicitly_requested_dependency_not_allowed
|
|
102
102
|
):
|
|
103
|
-
if
|
|
104
|
-
|
|
105
|
-
):
|
|
106
|
-
not_explicitly_requested_dependency_check_method = (
|
|
107
|
-
evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons
|
|
108
|
-
)
|
|
103
|
+
if not self._updated_module_requirement.rule_specified_with_importer_as_rule_object:
|
|
104
|
+
not_explicitly_requested_dependency_check_method = evaluable.any_dependencies_from_dependents_to_modules_other_than_dependent_upons
|
|
109
105
|
else:
|
|
110
|
-
not_explicitly_requested_dependency_check_method =
|
|
111
|
-
evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents
|
|
112
|
-
)
|
|
106
|
+
not_explicitly_requested_dependency_check_method = evaluable.any_other_dependencies_on_dependent_upons_than_from_dependents
|
|
113
107
|
|
|
114
108
|
return not_explicitly_requested_dependency_check_method(
|
|
115
109
|
self._updated_module_requirement.importers,
|
pytestarch-3.1.0/pyproject.toml
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
[tool.poetry]
|
|
2
|
-
name = "PyTestArch"
|
|
3
|
-
version = "3.1.0"
|
|
4
|
-
description = "Test framework for software architecture based on imports between modules"
|
|
5
|
-
authors = ["zyskarch <zyskarch@gmail.com>"]
|
|
6
|
-
maintainers = ["zyskarch <zyskarch@gmail.com>"]
|
|
7
|
-
readme = "README.md"
|
|
8
|
-
license = "Apache-2.0"
|
|
9
|
-
documentation = "https://zyskarch.github.io/pytestarch/"
|
|
10
|
-
repository = "https://github.com/zyskarch/pytestarch"
|
|
11
|
-
|
|
12
|
-
keywords = ["architecture", "test"]
|
|
13
|
-
classifiers = [
|
|
14
|
-
"Programming Language :: Python :: 3.12",
|
|
15
|
-
"Programming Language :: Python :: 3.11",
|
|
16
|
-
"Programming Language :: Python :: 3.10",
|
|
17
|
-
"Programming Language :: Python :: 3.9",
|
|
18
|
-
"License :: OSI Approved :: Apache Software License",
|
|
19
|
-
"Operating System :: OS Independent",
|
|
20
|
-
"Intended Audience :: Developers",
|
|
21
|
-
"Topic :: Software Development :: Testing",
|
|
22
|
-
"Topic :: Software Development :: Testing :: Unit",
|
|
23
|
-
]
|
|
24
|
-
|
|
25
|
-
[tool.poetry.urls]
|
|
26
|
-
"Bug Tracker" = "https://github.com/zyskarch/pytestarch/issues"
|
|
27
|
-
|
|
28
|
-
[tool.poetry.dependencies]
|
|
29
|
-
python = "^3.9"
|
|
30
|
-
networkx = "^3.2"
|
|
31
|
-
matplotlib = { version = "^3.9", optional = true }
|
|
32
|
-
|
|
33
|
-
[tool.poetry.extras]
|
|
34
|
-
visualization = ["matplotlib"]
|
|
35
|
-
|
|
36
|
-
[tool.poetry.dev-dependencies]
|
|
37
|
-
mkdocs = "1.6.0"
|
|
38
|
-
mkdocstrings-python = "1.10.3"
|
|
39
|
-
mkdocs-material = "9.5.25"
|
|
40
|
-
mkdocs-autorefs = "1.0.1"
|
|
41
|
-
mkdocs-material-extensions = "1.3.1"
|
|
42
|
-
mkdocstrings = "0.25.1"
|
|
43
|
-
griffe = "0.45.2"
|
|
44
|
-
nox = "2024.4.15"
|
|
45
|
-
pre-commit = "3.7.1"
|
|
46
|
-
pytest = "^8.2.1"
|
|
47
|
-
coverage = "^7.5.2"
|
|
48
|
-
mike = "2.1.1"
|
|
49
|
-
|
|
50
|
-
[build-system]
|
|
51
|
-
requires = ["poetry-core>=1.0.0"]
|
|
52
|
-
build-backend = "poetry.core.masonry.api"
|
|
53
|
-
|
|
54
|
-
[tool.pytest.ini_options]
|
|
55
|
-
sourcepath = "src"
|
|
56
|
-
|
|
57
|
-
[tool.isort]
|
|
58
|
-
profile = "black"
|
|
59
|
-
add_imports = ["from __future__ import annotations"]
|
|
60
|
-
|
|
61
|
-
[tool.bandit]
|
|
62
|
-
[tool.bandit.assert_used]
|
|
63
|
-
skips = ["*/test_*.py"]
|
pytestarch-3.1.0/setup.py
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
from setuptools import setup
|
|
3
|
-
|
|
4
|
-
package_dir = \
|
|
5
|
-
{'': 'src'}
|
|
6
|
-
|
|
7
|
-
packages = \
|
|
8
|
-
['pytestarch',
|
|
9
|
-
'pytestarch.diagram_extension',
|
|
10
|
-
'pytestarch.eval_structure',
|
|
11
|
-
'pytestarch.eval_structure_generation',
|
|
12
|
-
'pytestarch.eval_structure_generation.file_import',
|
|
13
|
-
'pytestarch.eval_structure_generation.graph_generation',
|
|
14
|
-
'pytestarch.query_language',
|
|
15
|
-
'pytestarch.rule_assessment',
|
|
16
|
-
'pytestarch.rule_assessment.error_message',
|
|
17
|
-
'pytestarch.rule_assessment.rule_check',
|
|
18
|
-
'pytestarch.utils']
|
|
19
|
-
|
|
20
|
-
package_data = \
|
|
21
|
-
{'': ['*']}
|
|
22
|
-
|
|
23
|
-
install_requires = \
|
|
24
|
-
['networkx>=3.2,<4.0']
|
|
25
|
-
|
|
26
|
-
extras_require = \
|
|
27
|
-
{'visualization': ['matplotlib>=3.9,<4.0']}
|
|
28
|
-
|
|
29
|
-
setup_kwargs = {
|
|
30
|
-
'name': 'pytestarch',
|
|
31
|
-
'version': '3.1.0',
|
|
32
|
-
'description': 'Test framework for software architecture based on imports between modules',
|
|
33
|
-
'long_description': '# Welcome to PyTestArch\n\nPyTestArch is an open source library that allows users to define architectural rules and test their code against them. It is \ngenerally inspired by [ArchUnit](https://www.archunit.org/).\n\n## Installation Guide\nPyTestArch is available via [PyPI](https://pypi.org/project/pytestarch/) and can be installed e.g. via pip: `pip install pytestarch`. To also install the\noptional dependency matplotlib, which is required to draw the created dependency graphs, install `pytestarch[visualization]`\n\n## Usage Guide\nThree steps are required to test an architectural rule:\n\n1) Create an evaluable representation of the source code you want to test\n\n```\nfrom pytestarch import get_evaluable_architecture\n\nevaluable = get_evaluable_architecture("/home/dummy/project", "/home/dummy/project/src")\n```\nThis will scan all python files under /home/dummy/project/src for imports and build an internal representation that can\nlater be queried. The first parameter /home/dummy/project helps PyTestArch to differentiate between internal and external \ndependencies. This evaluable can be used for multiple architectural rule checks; if you are using [pytest](https://docs.pytest.org/en/7.1.x/),\nyou could use a fixture for this evaluable object.\n\n2) Define an architectural rule\n```\nfrom pytestarch import Rule\n\nrule = (\n Rule() \n .modules_that() \n .are_named("project.src.moduleB") \n .should_not() \n .be_imported_by_modules_that() \n .are_sub_modules_of("project.src.moduleA") \n)\n```\n\nThis rule represents the architectural requirements that a module named "project.src.moduleB" should not be imported by any module\nthat is a submodule of "project.src.moduleA", excluding "project.src.moduleA" itself.\n\n3) Evaluate your code against this rule\n\n```\nrule.assert_applies(evaluable)\n```\nThat\'s it!\n',
|
|
34
|
-
'author': 'zyskarch',
|
|
35
|
-
'author_email': 'zyskarch@gmail.com',
|
|
36
|
-
'maintainer': 'zyskarch',
|
|
37
|
-
'maintainer_email': 'zyskarch@gmail.com',
|
|
38
|
-
'url': 'https://github.com/zyskarch/pytestarch',
|
|
39
|
-
'package_dir': package_dir,
|
|
40
|
-
'packages': packages,
|
|
41
|
-
'package_data': package_data,
|
|
42
|
-
'install_requires': install_requires,
|
|
43
|
-
'extras_require': extras_require,
|
|
44
|
-
'python_requires': '>=3.9,<4.0',
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
setup(**setup_kwargs)
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
from pytestarch.eval_structure.evaluable_architecture import ( # noqa: F401
|
|
2
|
-
EvaluableArchitecture,
|
|
3
|
-
)
|
|
4
|
-
from pytestarch.query_language.rule import Rule # noqa: F401
|
|
5
|
-
from .pytestarch import get_evaluable_architecture # noqa: F401 E401
|
|
6
|
-
from .pytestarch import ( # noqa: F401 E401; noqa: F401 E401
|
|
7
|
-
get_evaluable_architecture_for_module_objects,
|
|
8
|
-
)
|
|
9
|
-
from pytestarch.query_language.layered_architecture_rule import ( # noqa: F401
|
|
10
|
-
LayeredArchitecture,
|
|
11
|
-
LayerRule,
|
|
12
|
-
)
|
|
13
|
-
from pytestarch.diagram_extension.diagram_rule import DiagramRule # noqa: F401
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/diagram_extension/parsed_dependencies.py
RENAMED
|
File without changes
|
|
File without changes
|
{pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure/evaluable_architecture.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure_generation/file_import/config.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/eval_structure_generation/file_import/parser.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/rule_assessment/error_message/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/rule_assessment/rule_check/rule_violations.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytestarch-3.1.0 → pytestarch-4.0.0}/src/pytestarch/utils/partial_match_to_regex_converter.py
RENAMED
|
File without changes
|