modwire 1.1.0__tar.gz → 2.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.
- modwire-2.0.0/.github/ISSUE_TEMPLATE/bug_report.yml +106 -0
- modwire-2.0.0/.github/ISSUE_TEMPLATE/config.yml +1 -0
- modwire-2.0.0/.github/ISSUE_TEMPLATE/feature_request.yml +70 -0
- modwire-2.0.0/.github/PULL_REQUEST_TEMPLATE.md +14 -0
- modwire-2.0.0/CONTRIBUTING.md +42 -0
- modwire-2.0.0/PKG-INFO +252 -0
- modwire-2.0.0/README.md +219 -0
- modwire-2.0.0/docs/wiki/Development-checks.md +23 -0
- modwire-2.0.0/docs/wiki/Home.md +31 -0
- modwire-2.0.0/docs/wiki/Reporting-bugs.md +26 -0
- modwire-2.0.0/docs/wiki/Requesting-features.md +26 -0
- {modwire-1.1.0 → modwire-2.0.0}/pyproject.toml +3 -3
- modwire-2.0.0/src/modwire/__init__.py +86 -0
- {modwire-1.1.0 → modwire-2.0.0}/src/modwire/_version.py +3 -3
- modwire-2.0.0/src/modwire/architecture/__init__.py +59 -0
- {modwire-1.1.0 → modwire-2.0.0}/src/modwire/architecture/analyzers.py +19 -0
- modwire-2.0.0/src/modwire/architecture/config.py +126 -0
- modwire-2.0.0/src/modwire/architecture/insights.py +246 -0
- modwire-2.0.0/src/modwire/architecture/matching.py +153 -0
- {modwire-1.1.0 → modwire-2.0.0}/src/modwire/architecture/policy.py +20 -14
- modwire-2.0.0/src/modwire/architecture/render.py +99 -0
- modwire-2.0.0/src/modwire/architecture/violations.py +47 -0
- modwire-2.0.0/src/modwire/extraction/__init__.py +33 -0
- modwire-2.0.0/src/modwire/extraction/cache.py +92 -0
- modwire-2.0.0/src/modwire/extraction/manifest.py +97 -0
- modwire-2.0.0/src/modwire/extraction/models.py +151 -0
- modwire-2.0.0/src/modwire/extraction/roots.py +100 -0
- modwire-2.0.0/src/modwire/extraction/serialization.py +106 -0
- modwire-2.0.0/src/modwire/extraction/service.py +100 -0
- {modwire-1.1.0 → modwire-2.0.0}/src/modwire/extractors/base.py +15 -2
- {modwire-1.1.0 → modwire-2.0.0}/src/modwire/extractors/loader.py +6 -1
- {modwire-1.1.0 → modwire-2.0.0}/src/modwire/extractors/php.py +5 -1
- modwire-2.0.0/src/modwire/graph.py +116 -0
- modwire-2.0.0/src/modwire/metadata.py +128 -0
- modwire-2.0.0/src/modwire/shape/__init__.py +16 -0
- modwire-2.0.0/src/modwire/shape/config.py +93 -0
- modwire-2.0.0/src/modwire/shape/evaluator.py +32 -0
- modwire-2.0.0/src/modwire/shape/rules.py +389 -0
- modwire-2.0.0/src/modwire/shape/violations.py +23 -0
- modwire-2.0.0/src/modwire/testing/__init__.py +24 -0
- modwire-2.0.0/src/modwire/testing/factories.py +168 -0
- modwire-2.0.0/src/modwire.egg-info/PKG-INFO +252 -0
- {modwire-1.1.0 → modwire-2.0.0}/src/modwire.egg-info/SOURCES.txt +26 -1
- {modwire-1.1.0 → modwire-2.0.0}/tests/test_api.py +440 -1
- modwire-2.0.0/tests/test_architecture_api.py +360 -0
- modwire-1.1.0/PKG-INFO +0 -112
- modwire-1.1.0/README.md +0 -79
- modwire-1.1.0/src/modwire/__init__.py +0 -18
- modwire-1.1.0/src/modwire/architecture/__init__.py +0 -10
- modwire-1.1.0/src/modwire/architecture/matching.py +0 -58
- modwire-1.1.0/src/modwire/architecture/render.py +0 -98
- modwire-1.1.0/src/modwire/architecture/violations.py +0 -24
- modwire-1.1.0/src/modwire/extraction.py +0 -73
- modwire-1.1.0/src/modwire/graph.py +0 -56
- modwire-1.1.0/src/modwire.egg-info/PKG-INFO +0 -112
- modwire-1.1.0/tests/test_architecture_api.py +0 -43
- {modwire-1.1.0 → modwire-2.0.0}/.github/workflows/ci.yml +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/.github/workflows/release.yml +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/.gitignore +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/LICENSE +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/setup.cfg +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/show_test_source_files.py +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/src/modwire/definitions.py +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/src/modwire/exports.py +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/src/modwire/extractors/__init__.py +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/src/modwire/extractors/python.py +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/src/modwire/extractors/scripts/php_extractor.php +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/src/modwire/extractors/scripts/python_extractor.py +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/src/modwire/extractors/scripts/typescript_extractor.js +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/src/modwire/extractors/typescript.py +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/src/modwire.egg-info/dependency_links.txt +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/src/modwire.egg-info/requires.txt +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/src/modwire.egg-info/top_level.txt +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/tests/apps/php/ignored/generated.php +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/tests/apps/php/src/application/use_cases/activate.php +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/tests/apps/php/src/domain/model/user.php +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/tests/apps/php/src/domain/services/policy.php +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/tests/apps/php/src/interfaces/http/controller.php +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/tests/apps/python/ignored/generated.py +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/tests/apps/python/src/application/use_cases/activate.py +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/tests/apps/python/src/domain/model/user.py +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/tests/apps/python/src/domain/services/policy.py +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/tests/apps/python/src/interfaces/http/controller.py +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/tests/apps/typescript/ignored/generated.ts +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/tests/apps/typescript/src/application/use_cases/activate.ts +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/tests/apps/typescript/src/domain/model/profile.tsx +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/tests/apps/typescript/src/domain/model/user.ts +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/tests/apps/typescript/src/domain/services/audit.js +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/tests/apps/typescript/src/domain/services/policy.ts +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/tests/apps/typescript/src/interfaces/http/controller.ts +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/tests/apps/typescript/src/interfaces/http/view.jsx +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/tests/test_standalone.py +0 -0
- {modwire-1.1.0 → modwire-2.0.0}/uv.lock +0 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Report incorrect extraction, graph output, architecture analysis, packaging, or runtime behavior.
|
|
3
|
+
title: "Bug: "
|
|
4
|
+
labels:
|
|
5
|
+
- bug
|
|
6
|
+
body:
|
|
7
|
+
- type: markdown
|
|
8
|
+
attributes:
|
|
9
|
+
value: |
|
|
10
|
+
Thanks for reporting a bug. Clear reproduction details make it much easier to fix issues in extractors and graph analysis.
|
|
11
|
+
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: summary
|
|
14
|
+
attributes:
|
|
15
|
+
label: What happened?
|
|
16
|
+
description: Describe the bug and the behavior you expected instead.
|
|
17
|
+
placeholder: Modwire returned...
|
|
18
|
+
validations:
|
|
19
|
+
required: true
|
|
20
|
+
|
|
21
|
+
- type: dropdown
|
|
22
|
+
id: area
|
|
23
|
+
attributes:
|
|
24
|
+
label: Affected area
|
|
25
|
+
options:
|
|
26
|
+
- Python extractor
|
|
27
|
+
- TypeScript/JavaScript extractor
|
|
28
|
+
- PHP extractor
|
|
29
|
+
- Dependency graph
|
|
30
|
+
- Architecture policy API
|
|
31
|
+
- Packaging or installation
|
|
32
|
+
- Documentation
|
|
33
|
+
- Other
|
|
34
|
+
validations:
|
|
35
|
+
required: true
|
|
36
|
+
|
|
37
|
+
- type: textarea
|
|
38
|
+
id: reproduce
|
|
39
|
+
attributes:
|
|
40
|
+
label: How can we reproduce it?
|
|
41
|
+
description: Include the smallest source tree, snippet, command, or test case that shows the problem.
|
|
42
|
+
placeholder: |
|
|
43
|
+
1. Create this file...
|
|
44
|
+
2. Run this code...
|
|
45
|
+
3. Observe...
|
|
46
|
+
validations:
|
|
47
|
+
required: true
|
|
48
|
+
|
|
49
|
+
- type: textarea
|
|
50
|
+
id: actual
|
|
51
|
+
attributes:
|
|
52
|
+
label: Actual output
|
|
53
|
+
description: Paste the returned objects, graph edges, violation output, traceback, or command output.
|
|
54
|
+
render: text
|
|
55
|
+
validations:
|
|
56
|
+
required: false
|
|
57
|
+
|
|
58
|
+
- type: textarea
|
|
59
|
+
id: expected
|
|
60
|
+
attributes:
|
|
61
|
+
label: Expected output
|
|
62
|
+
description: Describe the graph, source IDs, symbols, imports, or violations you expected.
|
|
63
|
+
validations:
|
|
64
|
+
required: false
|
|
65
|
+
|
|
66
|
+
- type: input
|
|
67
|
+
id: modwire-version
|
|
68
|
+
attributes:
|
|
69
|
+
label: Modwire version
|
|
70
|
+
description: Run `python -m pip show modwire` or identify the commit SHA if installed from source.
|
|
71
|
+
placeholder: 0.0.0 or commit SHA
|
|
72
|
+
validations:
|
|
73
|
+
required: false
|
|
74
|
+
|
|
75
|
+
- type: input
|
|
76
|
+
id: python-version
|
|
77
|
+
attributes:
|
|
78
|
+
label: Python version
|
|
79
|
+
placeholder: "3.11, 3.12, or 3.13"
|
|
80
|
+
validations:
|
|
81
|
+
required: true
|
|
82
|
+
|
|
83
|
+
- type: input
|
|
84
|
+
id: runtime-versions
|
|
85
|
+
attributes:
|
|
86
|
+
label: Node.js or PHP version, if relevant
|
|
87
|
+
description: TypeScript/JavaScript extraction requires Node.js. PHP extraction requires PHP.
|
|
88
|
+
placeholder: "Node.js 20.x, PHP 8.3, or not applicable"
|
|
89
|
+
validations:
|
|
90
|
+
required: false
|
|
91
|
+
|
|
92
|
+
- type: input
|
|
93
|
+
id: os
|
|
94
|
+
attributes:
|
|
95
|
+
label: Operating system
|
|
96
|
+
placeholder: "macOS 15, Ubuntu 24.04, Windows 11, etc."
|
|
97
|
+
validations:
|
|
98
|
+
required: false
|
|
99
|
+
|
|
100
|
+
- type: textarea
|
|
101
|
+
id: context
|
|
102
|
+
attributes:
|
|
103
|
+
label: Additional context
|
|
104
|
+
description: Add anything else that may help explain the problem.
|
|
105
|
+
validations:
|
|
106
|
+
required: false
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
blank_issues_enabled: false
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Suggest a new capability, supported language, extractor improvement, graph API, or architecture rule.
|
|
3
|
+
title: "Feature: "
|
|
4
|
+
labels:
|
|
5
|
+
- enhancement
|
|
6
|
+
body:
|
|
7
|
+
- type: markdown
|
|
8
|
+
attributes:
|
|
9
|
+
value: |
|
|
10
|
+
Use this form for new capabilities or behavior changes. For incorrect current behavior, please open a bug report instead.
|
|
11
|
+
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: problem
|
|
14
|
+
attributes:
|
|
15
|
+
label: What problem should this solve?
|
|
16
|
+
description: Describe the workflow, codebase shape, or analysis gap that motivates the request.
|
|
17
|
+
placeholder: I want to use Modwire to...
|
|
18
|
+
validations:
|
|
19
|
+
required: true
|
|
20
|
+
|
|
21
|
+
- type: dropdown
|
|
22
|
+
id: area
|
|
23
|
+
attributes:
|
|
24
|
+
label: Feature area
|
|
25
|
+
options:
|
|
26
|
+
- New language support
|
|
27
|
+
- Python extractor
|
|
28
|
+
- TypeScript/JavaScript extractor
|
|
29
|
+
- PHP extractor
|
|
30
|
+
- Dependency graph
|
|
31
|
+
- Architecture policy API
|
|
32
|
+
- Exports or integrations
|
|
33
|
+
- Documentation
|
|
34
|
+
- Other
|
|
35
|
+
validations:
|
|
36
|
+
required: true
|
|
37
|
+
|
|
38
|
+
- type: textarea
|
|
39
|
+
id: proposal
|
|
40
|
+
attributes:
|
|
41
|
+
label: Proposed behavior
|
|
42
|
+
description: Explain the API, CLI, output shape, analyzer, or documentation you would like to see.
|
|
43
|
+
placeholder: Modwire should...
|
|
44
|
+
validations:
|
|
45
|
+
required: true
|
|
46
|
+
|
|
47
|
+
- type: textarea
|
|
48
|
+
id: example
|
|
49
|
+
attributes:
|
|
50
|
+
label: Example usage or input
|
|
51
|
+
description: Include a short source snippet, desired graph shape, policy example, or Python API sketch if useful.
|
|
52
|
+
render: python
|
|
53
|
+
validations:
|
|
54
|
+
required: false
|
|
55
|
+
|
|
56
|
+
- type: textarea
|
|
57
|
+
id: alternatives
|
|
58
|
+
attributes:
|
|
59
|
+
label: Alternatives considered
|
|
60
|
+
description: Mention any workaround or different API shape you have considered.
|
|
61
|
+
validations:
|
|
62
|
+
required: false
|
|
63
|
+
|
|
64
|
+
- type: checkboxes
|
|
65
|
+
id: contribution
|
|
66
|
+
attributes:
|
|
67
|
+
label: Contribution
|
|
68
|
+
options:
|
|
69
|
+
- label: I would be interested in working on this.
|
|
70
|
+
required: false
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Contributing to Modwire
|
|
2
|
+
|
|
3
|
+
Modwire is a Python package for extracting source-code dependencies and
|
|
4
|
+
evaluating architecture rules across Python, TypeScript/JavaScript, and PHP
|
|
5
|
+
projects.
|
|
6
|
+
|
|
7
|
+
## Requesting Features
|
|
8
|
+
|
|
9
|
+
Use the `Feature request` issue form for new capabilities, such as:
|
|
10
|
+
|
|
11
|
+
- support for another language or framework convention
|
|
12
|
+
- richer symbol, import, or graph metadata
|
|
13
|
+
- new architecture analyzers or policy matching behavior
|
|
14
|
+
- export formats or integrations with other tools
|
|
15
|
+
- documentation examples for common workflows
|
|
16
|
+
|
|
17
|
+
Feature requests are easiest to evaluate when they include the problem being
|
|
18
|
+
solved, a small example input, and the desired API or output shape.
|
|
19
|
+
|
|
20
|
+
## Reporting Bugs
|
|
21
|
+
|
|
22
|
+
Use the `Bug report` issue form for incorrect current behavior, such as:
|
|
23
|
+
|
|
24
|
+
- missing or incorrect imports, symbols, source IDs, or graph edges
|
|
25
|
+
- incorrect architecture-policy violations
|
|
26
|
+
- extractor crashes or runtime failures
|
|
27
|
+
- packaging, installation, or compatibility problems
|
|
28
|
+
- documentation that contradicts the implemented behavior
|
|
29
|
+
|
|
30
|
+
Bug reports should include a minimal reproduction, the expected output, the
|
|
31
|
+
actual output, and relevant versions for Python, Modwire, Node.js, or PHP.
|
|
32
|
+
|
|
33
|
+
## Pull Requests
|
|
34
|
+
|
|
35
|
+
Before opening a pull request, run the local checks documented in
|
|
36
|
+
[Development checks](docs/wiki/Development-checks.md).
|
|
37
|
+
|
|
38
|
+
Extractor changes should include focused tests under `tests/` and, when
|
|
39
|
+
relevant, a small fixture under `tests/apps/`.
|
|
40
|
+
|
|
41
|
+
Keep pull requests scoped to one behavior change. If an issue exists, link it in
|
|
42
|
+
the pull request description.
|
modwire-2.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: modwire
|
|
3
|
+
Version: 2.0.0
|
|
4
|
+
Summary: Extract source-code dependencies and build dependency graphs.
|
|
5
|
+
Author: Tomasz Szpak
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/9orky/modwire
|
|
8
|
+
Project-URL: Repository, https://github.com/9orky/modwire
|
|
9
|
+
Project-URL: Issues, https://github.com/9orky/modwire/issues
|
|
10
|
+
Keywords: architecture,code-analysis,dependency-graph,static-analysis
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Software Development
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
23
|
+
Requires-Python: >=3.11
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: pydantic>=2.8
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: build>=1.2; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
30
|
+
Requires-Dist: ruff>=0.8; extra == "dev"
|
|
31
|
+
Requires-Dist: twine>=5.1; extra == "dev"
|
|
32
|
+
Dynamic: license-file
|
|
33
|
+
|
|
34
|
+
# modwire
|
|
35
|
+
|
|
36
|
+
`modwire` extracts source-code structure and import dependencies from Python,
|
|
37
|
+
TypeScript/JavaScript, and PHP projects. It returns typed Python objects that
|
|
38
|
+
you can use to build dependency graphs, inspect symbols, and evaluate
|
|
39
|
+
architecture rules.
|
|
40
|
+
|
|
41
|
+
## Installation
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
python -m pip install modwire
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The Python extractor works with Python alone. TypeScript/JavaScript extraction
|
|
48
|
+
requires Node.js at runtime, and PHP extraction requires PHP at runtime.
|
|
49
|
+
|
|
50
|
+
## Quick Start
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from pathlib import Path
|
|
54
|
+
|
|
55
|
+
from modwire import discover_sources, extract_code
|
|
56
|
+
|
|
57
|
+
manifest = discover_sources(
|
|
58
|
+
"python",
|
|
59
|
+
Path("src"),
|
|
60
|
+
exclusions=("**/__pycache__/**",),
|
|
61
|
+
)
|
|
62
|
+
result = extract_code("python", Path("src"), exclusions=manifest.exclusions)
|
|
63
|
+
|
|
64
|
+
print(result.extraction_result.summary.files_checked)
|
|
65
|
+
print(result.graph.node_ids())
|
|
66
|
+
print([(edge.from_id, edge.to_id) for edge in result.graph.edges])
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Graph nodes use canonical extensionless source IDs, so equivalent Python,
|
|
70
|
+
TypeScript, and PHP projects can be compared through the same graph shape.
|
|
71
|
+
|
|
72
|
+
## Supported Languages
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
from modwire import supported_languages
|
|
77
|
+
|
|
78
|
+
print(supported_languages())
|
|
79
|
+
# ("python", "typescript", "php")
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Language-specific source IDs can be normalized without running a full
|
|
83
|
+
extraction:
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
from modwire import normalize_source_id
|
|
87
|
+
|
|
88
|
+
print(normalize_source_id("typescript", "src/view.tsx"))
|
|
89
|
+
# "src/view"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Extraction Options
|
|
93
|
+
|
|
94
|
+
Use `SourceRoots` when source IDs should be relative to a workspace root or to a
|
|
95
|
+
logical package prefix:
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
from pathlib import Path
|
|
99
|
+
|
|
100
|
+
from modwire import SourceRoots, extract_code
|
|
101
|
+
|
|
102
|
+
code_map = extract_code(
|
|
103
|
+
"python",
|
|
104
|
+
Path("packages/billing/src"),
|
|
105
|
+
source_roots=SourceRoots(
|
|
106
|
+
workspace_root=Path("."),
|
|
107
|
+
source_id_mode="relative_to_workspace_root",
|
|
108
|
+
),
|
|
109
|
+
)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Use `ExtractionCache` to reuse extraction output when files and extractor
|
|
113
|
+
implementations have not changed:
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
from pathlib import Path
|
|
117
|
+
|
|
118
|
+
from modwire import ExtractionCache, extract_code
|
|
119
|
+
|
|
120
|
+
code_map = extract_code(
|
|
121
|
+
"python",
|
|
122
|
+
Path("src"),
|
|
123
|
+
cache=ExtractionCache(Path(".modwire-cache")),
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
print(code_map.cache_status)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Architecture Policy API
|
|
130
|
+
|
|
131
|
+
`modwire.architecture` exposes policy evaluation helpers for checking import
|
|
132
|
+
boundaries and common dependency-flow rules.
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
from modwire import extract_code
|
|
136
|
+
from modwire.architecture import (
|
|
137
|
+
ArchitectureBoundaryRule,
|
|
138
|
+
ArchitectureConfig,
|
|
139
|
+
ArchitectureFlowRules,
|
|
140
|
+
ArchitecturePolicyEvaluator,
|
|
141
|
+
ArchitectureRules,
|
|
142
|
+
ArchitectureTagRule,
|
|
143
|
+
render_violations,
|
|
144
|
+
supported_analyzers,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
print(supported_analyzers())
|
|
148
|
+
# ("backward-flow", "no-reentry", "no-cycles")
|
|
149
|
+
|
|
150
|
+
code_map = extract_code("python", "src")
|
|
151
|
+
config = ArchitectureConfig(
|
|
152
|
+
language="python",
|
|
153
|
+
architecture_root="src",
|
|
154
|
+
rules=ArchitectureRules(
|
|
155
|
+
tags=(
|
|
156
|
+
ArchitectureTagRule(name="module", match="features/*"),
|
|
157
|
+
ArchitectureTagRule(name="ui", match="features/*/ui"),
|
|
158
|
+
ArchitectureTagRule(name="domain", match="features/*/domain"),
|
|
159
|
+
),
|
|
160
|
+
boundaries=(
|
|
161
|
+
ArchitectureBoundaryRule(
|
|
162
|
+
source="features/*/ui",
|
|
163
|
+
disallow=("features/*/domain",),
|
|
164
|
+
allow_same_match=True,
|
|
165
|
+
),
|
|
166
|
+
),
|
|
167
|
+
flow=ArchitectureFlowRules(
|
|
168
|
+
layers=("domain", "ui"),
|
|
169
|
+
module_tag="module",
|
|
170
|
+
analyzers=("no-cycles",),
|
|
171
|
+
),
|
|
172
|
+
),
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
violations = ArchitecturePolicyEvaluator().evaluate(code_map.graph, config)
|
|
176
|
+
print(render_violations(tuple(violations)))
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Architecture insight helpers summarize ownership and graph pressure:
|
|
180
|
+
|
|
181
|
+
```python
|
|
182
|
+
from modwire.architecture import coherence_summary, find_hotspots, map_code
|
|
183
|
+
|
|
184
|
+
architecture_map = map_code(code_map, config)
|
|
185
|
+
hotspots = find_hotspots(code_map, limit=5)
|
|
186
|
+
coherence = coherence_summary(code_map)
|
|
187
|
+
|
|
188
|
+
print(architecture_map.cross_module_dependencies)
|
|
189
|
+
print(hotspots)
|
|
190
|
+
print(coherence.external_dependencies)
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Shape Policy API
|
|
194
|
+
|
|
195
|
+
Shape policies evaluate file, symbol, callable, property, and import metadata:
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
from modwire import ShapePolicyEvaluator, evaluate_shape
|
|
199
|
+
|
|
200
|
+
violations = evaluate_shape(
|
|
201
|
+
code_map,
|
|
202
|
+
{
|
|
203
|
+
"max_functions_per_file": 5,
|
|
204
|
+
"max_methods_per_class": 10,
|
|
205
|
+
"allow_import_aliases": False,
|
|
206
|
+
"require_joined_imports": True,
|
|
207
|
+
},
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
same_result = ShapePolicyEvaluator().evaluate(code_map, {})
|
|
211
|
+
print([violation.to_dict() for violation in violations])
|
|
212
|
+
print(same_result)
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Serialization And Exports
|
|
216
|
+
|
|
217
|
+
`CodeMap` results can be serialized for later analysis, and export metadata can
|
|
218
|
+
be used to find currently unused public symbols:
|
|
219
|
+
|
|
220
|
+
```python
|
|
221
|
+
from modwire import (
|
|
222
|
+
deserialize_code_map,
|
|
223
|
+
find_unused_exports,
|
|
224
|
+
serialize_code_map,
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
payload = serialize_code_map(code_map)
|
|
228
|
+
loaded = deserialize_code_map(payload)
|
|
229
|
+
|
|
230
|
+
unused = find_unused_exports(loaded.extraction_result)
|
|
231
|
+
print([(export.source_id, export.name) for export in unused])
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Development
|
|
235
|
+
|
|
236
|
+
See [Development checks](docs/wiki/Development-checks.md) for the local command
|
|
237
|
+
set used before pull requests and releases.
|
|
238
|
+
|
|
239
|
+
## Contributing
|
|
240
|
+
|
|
241
|
+
Feature requests and bug reports are tracked through GitHub Issues:
|
|
242
|
+
|
|
243
|
+
- Open a feature request for new language support, graph metadata, architecture
|
|
244
|
+
rules, export formats, or documentation examples.
|
|
245
|
+
- Open a bug report for incorrect extraction results, graph edges, architecture
|
|
246
|
+
violations, packaging problems, or runtime failures.
|
|
247
|
+
|
|
248
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the information to include and the
|
|
249
|
+
checks to run before opening a pull request.
|
|
250
|
+
|
|
251
|
+
Starter wiki pages are tracked under [docs/wiki](docs/wiki) so the GitHub Wiki
|
|
252
|
+
can be initialized with the same guidance.
|
modwire-2.0.0/README.md
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# modwire
|
|
2
|
+
|
|
3
|
+
`modwire` extracts source-code structure and import dependencies from Python,
|
|
4
|
+
TypeScript/JavaScript, and PHP projects. It returns typed Python objects that
|
|
5
|
+
you can use to build dependency graphs, inspect symbols, and evaluate
|
|
6
|
+
architecture rules.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
python -m pip install modwire
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
The Python extractor works with Python alone. TypeScript/JavaScript extraction
|
|
15
|
+
requires Node.js at runtime, and PHP extraction requires PHP at runtime.
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
|
|
22
|
+
from modwire import discover_sources, extract_code
|
|
23
|
+
|
|
24
|
+
manifest = discover_sources(
|
|
25
|
+
"python",
|
|
26
|
+
Path("src"),
|
|
27
|
+
exclusions=("**/__pycache__/**",),
|
|
28
|
+
)
|
|
29
|
+
result = extract_code("python", Path("src"), exclusions=manifest.exclusions)
|
|
30
|
+
|
|
31
|
+
print(result.extraction_result.summary.files_checked)
|
|
32
|
+
print(result.graph.node_ids())
|
|
33
|
+
print([(edge.from_id, edge.to_id) for edge in result.graph.edges])
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Graph nodes use canonical extensionless source IDs, so equivalent Python,
|
|
37
|
+
TypeScript, and PHP projects can be compared through the same graph shape.
|
|
38
|
+
|
|
39
|
+
## Supported Languages
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from modwire import supported_languages
|
|
44
|
+
|
|
45
|
+
print(supported_languages())
|
|
46
|
+
# ("python", "typescript", "php")
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Language-specific source IDs can be normalized without running a full
|
|
50
|
+
extraction:
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from modwire import normalize_source_id
|
|
54
|
+
|
|
55
|
+
print(normalize_source_id("typescript", "src/view.tsx"))
|
|
56
|
+
# "src/view"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Extraction Options
|
|
60
|
+
|
|
61
|
+
Use `SourceRoots` when source IDs should be relative to a workspace root or to a
|
|
62
|
+
logical package prefix:
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from pathlib import Path
|
|
66
|
+
|
|
67
|
+
from modwire import SourceRoots, extract_code
|
|
68
|
+
|
|
69
|
+
code_map = extract_code(
|
|
70
|
+
"python",
|
|
71
|
+
Path("packages/billing/src"),
|
|
72
|
+
source_roots=SourceRoots(
|
|
73
|
+
workspace_root=Path("."),
|
|
74
|
+
source_id_mode="relative_to_workspace_root",
|
|
75
|
+
),
|
|
76
|
+
)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Use `ExtractionCache` to reuse extraction output when files and extractor
|
|
80
|
+
implementations have not changed:
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from pathlib import Path
|
|
84
|
+
|
|
85
|
+
from modwire import ExtractionCache, extract_code
|
|
86
|
+
|
|
87
|
+
code_map = extract_code(
|
|
88
|
+
"python",
|
|
89
|
+
Path("src"),
|
|
90
|
+
cache=ExtractionCache(Path(".modwire-cache")),
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
print(code_map.cache_status)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Architecture Policy API
|
|
97
|
+
|
|
98
|
+
`modwire.architecture` exposes policy evaluation helpers for checking import
|
|
99
|
+
boundaries and common dependency-flow rules.
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
from modwire import extract_code
|
|
103
|
+
from modwire.architecture import (
|
|
104
|
+
ArchitectureBoundaryRule,
|
|
105
|
+
ArchitectureConfig,
|
|
106
|
+
ArchitectureFlowRules,
|
|
107
|
+
ArchitecturePolicyEvaluator,
|
|
108
|
+
ArchitectureRules,
|
|
109
|
+
ArchitectureTagRule,
|
|
110
|
+
render_violations,
|
|
111
|
+
supported_analyzers,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
print(supported_analyzers())
|
|
115
|
+
# ("backward-flow", "no-reentry", "no-cycles")
|
|
116
|
+
|
|
117
|
+
code_map = extract_code("python", "src")
|
|
118
|
+
config = ArchitectureConfig(
|
|
119
|
+
language="python",
|
|
120
|
+
architecture_root="src",
|
|
121
|
+
rules=ArchitectureRules(
|
|
122
|
+
tags=(
|
|
123
|
+
ArchitectureTagRule(name="module", match="features/*"),
|
|
124
|
+
ArchitectureTagRule(name="ui", match="features/*/ui"),
|
|
125
|
+
ArchitectureTagRule(name="domain", match="features/*/domain"),
|
|
126
|
+
),
|
|
127
|
+
boundaries=(
|
|
128
|
+
ArchitectureBoundaryRule(
|
|
129
|
+
source="features/*/ui",
|
|
130
|
+
disallow=("features/*/domain",),
|
|
131
|
+
allow_same_match=True,
|
|
132
|
+
),
|
|
133
|
+
),
|
|
134
|
+
flow=ArchitectureFlowRules(
|
|
135
|
+
layers=("domain", "ui"),
|
|
136
|
+
module_tag="module",
|
|
137
|
+
analyzers=("no-cycles",),
|
|
138
|
+
),
|
|
139
|
+
),
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
violations = ArchitecturePolicyEvaluator().evaluate(code_map.graph, config)
|
|
143
|
+
print(render_violations(tuple(violations)))
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Architecture insight helpers summarize ownership and graph pressure:
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
from modwire.architecture import coherence_summary, find_hotspots, map_code
|
|
150
|
+
|
|
151
|
+
architecture_map = map_code(code_map, config)
|
|
152
|
+
hotspots = find_hotspots(code_map, limit=5)
|
|
153
|
+
coherence = coherence_summary(code_map)
|
|
154
|
+
|
|
155
|
+
print(architecture_map.cross_module_dependencies)
|
|
156
|
+
print(hotspots)
|
|
157
|
+
print(coherence.external_dependencies)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Shape Policy API
|
|
161
|
+
|
|
162
|
+
Shape policies evaluate file, symbol, callable, property, and import metadata:
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
from modwire import ShapePolicyEvaluator, evaluate_shape
|
|
166
|
+
|
|
167
|
+
violations = evaluate_shape(
|
|
168
|
+
code_map,
|
|
169
|
+
{
|
|
170
|
+
"max_functions_per_file": 5,
|
|
171
|
+
"max_methods_per_class": 10,
|
|
172
|
+
"allow_import_aliases": False,
|
|
173
|
+
"require_joined_imports": True,
|
|
174
|
+
},
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
same_result = ShapePolicyEvaluator().evaluate(code_map, {})
|
|
178
|
+
print([violation.to_dict() for violation in violations])
|
|
179
|
+
print(same_result)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Serialization And Exports
|
|
183
|
+
|
|
184
|
+
`CodeMap` results can be serialized for later analysis, and export metadata can
|
|
185
|
+
be used to find currently unused public symbols:
|
|
186
|
+
|
|
187
|
+
```python
|
|
188
|
+
from modwire import (
|
|
189
|
+
deserialize_code_map,
|
|
190
|
+
find_unused_exports,
|
|
191
|
+
serialize_code_map,
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
payload = serialize_code_map(code_map)
|
|
195
|
+
loaded = deserialize_code_map(payload)
|
|
196
|
+
|
|
197
|
+
unused = find_unused_exports(loaded.extraction_result)
|
|
198
|
+
print([(export.source_id, export.name) for export in unused])
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Development
|
|
202
|
+
|
|
203
|
+
See [Development checks](docs/wiki/Development-checks.md) for the local command
|
|
204
|
+
set used before pull requests and releases.
|
|
205
|
+
|
|
206
|
+
## Contributing
|
|
207
|
+
|
|
208
|
+
Feature requests and bug reports are tracked through GitHub Issues:
|
|
209
|
+
|
|
210
|
+
- Open a feature request for new language support, graph metadata, architecture
|
|
211
|
+
rules, export formats, or documentation examples.
|
|
212
|
+
- Open a bug report for incorrect extraction results, graph edges, architecture
|
|
213
|
+
violations, packaging problems, or runtime failures.
|
|
214
|
+
|
|
215
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the information to include and the
|
|
216
|
+
checks to run before opening a pull request.
|
|
217
|
+
|
|
218
|
+
Starter wiki pages are tracked under [docs/wiki](docs/wiki) so the GitHub Wiki
|
|
219
|
+
can be initialized with the same guidance.
|