modwire-cli 1.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.
Files changed (33) hide show
  1. modwire_cli-1.0.0/.github/ISSUE_TEMPLATE/bug_report.yml +46 -0
  2. modwire_cli-1.0.0/.github/ISSUE_TEMPLATE/config.yml +1 -0
  3. modwire_cli-1.0.0/.github/ISSUE_TEMPLATE/feature_request.yml +47 -0
  4. modwire_cli-1.0.0/.github/ISSUE_TEMPLATE/task.yml +48 -0
  5. modwire_cli-1.0.0/.github/workflows/ci.yml +28 -0
  6. modwire_cli-1.0.0/.github/workflows/human-approval.yml +133 -0
  7. modwire_cli-1.0.0/.github/workflows/issue-metadata.yml +21 -0
  8. modwire_cli-1.0.0/.github/workflows/release.yml +68 -0
  9. modwire_cli-1.0.0/.gitignore +12 -0
  10. modwire_cli-1.0.0/CHANGELOG.md +11 -0
  11. modwire_cli-1.0.0/LICENSE +21 -0
  12. modwire_cli-1.0.0/MANIFEST.in +5 -0
  13. modwire_cli-1.0.0/Makefile +21 -0
  14. modwire_cli-1.0.0/PKG-INFO +78 -0
  15. modwire_cli-1.0.0/README.md +42 -0
  16. modwire_cli-1.0.0/pyproject.toml +75 -0
  17. modwire_cli-1.0.0/scripts/verify_release.py +57 -0
  18. modwire_cli-1.0.0/setup.cfg +4 -0
  19. modwire_cli-1.0.0/src/modwire_cli/__init__.py +6 -0
  20. modwire_cli-1.0.0/src/modwire_cli/_version.py +24 -0
  21. modwire_cli-1.0.0/src/modwire_cli/main.py +65 -0
  22. modwire_cli-1.0.0/src/modwire_cli/py.typed +1 -0
  23. modwire_cli-1.0.0/src/modwire_cli.egg-info/PKG-INFO +78 -0
  24. modwire_cli-1.0.0/src/modwire_cli.egg-info/SOURCES.txt +31 -0
  25. modwire_cli-1.0.0/src/modwire_cli.egg-info/dependency_links.txt +1 -0
  26. modwire_cli-1.0.0/src/modwire_cli.egg-info/entry_points.txt +2 -0
  27. modwire_cli-1.0.0/src/modwire_cli.egg-info/requires.txt +9 -0
  28. modwire_cli-1.0.0/src/modwire_cli.egg-info/scm_file_list.json +26 -0
  29. modwire_cli-1.0.0/src/modwire_cli.egg-info/scm_version.json +8 -0
  30. modwire_cli-1.0.0/src/modwire_cli.egg-info/top_level.txt +1 -0
  31. modwire_cli-1.0.0/tests/test_cli.py +65 -0
  32. modwire_cli-1.0.0/tests/test_release.py +9 -0
  33. modwire_cli-1.0.0/uv.lock +867 -0
@@ -0,0 +1,46 @@
1
+ name: Bug report
2
+ description: Report incorrect or unexpected existing behavior.
3
+ title: "Bug: "
4
+ type: Bug
5
+ projects:
6
+ - modwire/1
7
+ body:
8
+ - type: markdown
9
+ attributes:
10
+ value: |
11
+ Select every pinned issue field before submission. Use native dependencies and sub-issues for relationships.
12
+ - type: textarea
13
+ id: summary
14
+ attributes:
15
+ label: What happened?
16
+ description: Describe the observed behavior and its impact.
17
+ validations:
18
+ required: true
19
+ - type: textarea
20
+ id: reproduce
21
+ attributes:
22
+ label: Reproduction
23
+ description: Provide the smallest reproducible example, command, or fixture.
24
+ validations:
25
+ required: true
26
+ - type: textarea
27
+ id: expected
28
+ attributes:
29
+ label: Expected behavior
30
+ description: State the behavior that would resolve the bug.
31
+ validations:
32
+ required: true
33
+ - type: input
34
+ id: version
35
+ attributes:
36
+ label: Package version
37
+ placeholder: 1.2.3 or commit SHA
38
+ validations:
39
+ required: false
40
+ - type: input
41
+ id: relationships
42
+ attributes:
43
+ label: Related issues
44
+ description: Link candidate blockers, blocked work, parents, or sub-issues for native relationship assignment.
45
+ validations:
46
+ required: false
@@ -0,0 +1 @@
1
+ blank_issues_enabled: false
@@ -0,0 +1,47 @@
1
+ name: Feature request
2
+ description: Propose a new user-facing capability or behavior.
3
+ title: "Feature: "
4
+ type: Feature
5
+ projects:
6
+ - modwire/1
7
+ body:
8
+ - type: markdown
9
+ attributes:
10
+ value: |
11
+ Select every pinned issue field before submission. Use native dependencies and sub-issues for relationships.
12
+ - type: textarea
13
+ id: problem
14
+ attributes:
15
+ label: Problem
16
+ description: Describe the user or integration problem this should solve.
17
+ validations:
18
+ required: true
19
+ - type: textarea
20
+ id: outcome
21
+ attributes:
22
+ label: Proposed outcome
23
+ description: Describe observable behavior without prescribing unnecessary implementation detail.
24
+ validations:
25
+ required: true
26
+ - type: textarea
27
+ id: acceptance
28
+ attributes:
29
+ label: Acceptance criteria
30
+ placeholder: |
31
+ - [ ] Observable behavior is implemented.
32
+ - [ ] Relevant tests and documentation are updated.
33
+ validations:
34
+ required: true
35
+ - type: textarea
36
+ id: alternatives
37
+ attributes:
38
+ label: Alternatives considered
39
+ validations:
40
+ required: false
41
+ - type: input
42
+ id: relationships
43
+ attributes:
44
+ label: Related issues
45
+ description: Link candidate blockers, blocked work, parents, or sub-issues for native relationship assignment.
46
+ validations:
47
+ required: false
@@ -0,0 +1,48 @@
1
+ name: Task
2
+ description: Propose concrete implementation, maintenance, documentation, or release work.
3
+ title: "Task: "
4
+ type: Task
5
+ projects:
6
+ - modwire/1
7
+ body:
8
+ - type: markdown
9
+ attributes:
10
+ value: |
11
+ Select every pinned issue field before submission. Use native dependencies and sub-issues for relationships.
12
+ - type: textarea
13
+ id: outcome
14
+ attributes:
15
+ label: Outcome
16
+ description: State the observable result, not only the activity.
17
+ validations:
18
+ required: true
19
+ - type: textarea
20
+ id: scope
21
+ attributes:
22
+ label: Scope
23
+ description: Describe the implementation boundary and important exclusions.
24
+ validations:
25
+ required: true
26
+ - type: textarea
27
+ id: acceptance
28
+ attributes:
29
+ label: Acceptance criteria
30
+ placeholder: |
31
+ - [ ] Observable behavior is implemented.
32
+ - [ ] Relevant tests and documentation are updated.
33
+ validations:
34
+ required: true
35
+ - type: textarea
36
+ id: rollout
37
+ attributes:
38
+ label: Rollout and rollback
39
+ description: Explain compatibility, migration, rollout, or rollback considerations; write "Not applicable" when none exist.
40
+ validations:
41
+ required: true
42
+ - type: input
43
+ id: relationships
44
+ attributes:
45
+ label: Related issues
46
+ description: Link candidate blockers, blocked work, parents, or sub-issues for native relationship assignment.
47
+ validations:
48
+ required: false
@@ -0,0 +1,28 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ verify:
14
+ runs-on: ubuntu-latest
15
+ strategy:
16
+ matrix:
17
+ python-version: ["3.12", "3.13", "3.14"]
18
+
19
+ steps:
20
+ - uses: actions/checkout@v6
21
+ with:
22
+ fetch-depth: 0
23
+ - uses: astral-sh/setup-uv@v7
24
+ with:
25
+ enable-cache: true
26
+ python-version: ${{ matrix.python-version }}
27
+ - run: uv sync --all-groups --frozen
28
+ - run: make verify
@@ -0,0 +1,133 @@
1
+ name: Human approval
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled]
6
+
7
+ permissions:
8
+ contents: read
9
+ pull-requests: read
10
+
11
+ concurrency:
12
+ group: human-approval-${{ github.event.pull_request.number }}
13
+ cancel-in-progress: true
14
+
15
+ jobs:
16
+ policy:
17
+ name: Evaluate approval policy
18
+ if: github.event.pull_request.draft == false
19
+ runs-on: ubuntu-latest
20
+ outputs:
21
+ required: ${{ steps.classify.outputs.required }}
22
+ reason: ${{ steps.classify.outputs.reason }}
23
+ steps:
24
+ - name: Classify pull request risk
25
+ id: classify
26
+ uses: actions/github-script@v7
27
+ with:
28
+ script: |
29
+ const files = await github.paginate(
30
+ github.rest.pulls.listFiles,
31
+ {
32
+ owner: context.repo.owner,
33
+ repo: context.repo.repo,
34
+ pull_number: context.issue.number,
35
+ per_page: 100,
36
+ },
37
+ );
38
+
39
+ const sensitivePaths = [
40
+ /^\.github\/workflows\//,
41
+ /^\.github\/modwire-ecosystem\.ya?ml$/,
42
+ /^\.github\/scripts\//,
43
+ /^docs\/governance\//,
44
+ /(^|\/)CODEOWNERS$/,
45
+ /(^|\/)SECURITY\.md$/,
46
+ /(^|\/)pyproject\.toml$/,
47
+ /(^|\/)(uv\.lock|poetry\.lock|Pipfile\.lock)$/,
48
+ ];
49
+ const sensitiveLabels = new Set([
50
+ "breaking",
51
+ "contract",
52
+ "release-gate",
53
+ "requires-human-approval",
54
+ ]);
55
+
56
+ const matchedFiles = files
57
+ .map(({ filename }) => filename)
58
+ .filter((filename) =>
59
+ sensitivePaths.some((pattern) => pattern.test(filename)),
60
+ );
61
+ const matchedLabels = (context.payload.pull_request.labels ?? [])
62
+ .map(({ name }) => name.toLowerCase())
63
+ .filter((name) => sensitiveLabels.has(name));
64
+
65
+ const reasons = [];
66
+ if (matchedFiles.length > 0) {
67
+ reasons.push(
68
+ `sensitive files: ${matchedFiles.slice(0, 5).join(", ")}`,
69
+ );
70
+ }
71
+ if (matchedLabels.length > 0) {
72
+ reasons.push(`sensitive labels: ${matchedLabels.join(", ")}`);
73
+ }
74
+
75
+ const required = reasons.length > 0;
76
+ core.setOutput("required", String(required));
77
+ core.setOutput(
78
+ "reason",
79
+ required ? reasons.join("; ") : "routine change",
80
+ );
81
+ core.notice(
82
+ required
83
+ ? `Human approval required: ${reasons.join("; ")}`
84
+ : "Human approval not required: routine change.",
85
+ { title: "Human approval policy" },
86
+ );
87
+
88
+ approval_gate:
89
+ name: Await human approval
90
+ needs: policy
91
+ if: needs.policy.outputs.required == 'true'
92
+ runs-on: ubuntu-latest
93
+ environment:
94
+ name: human-approval
95
+ deployment: false
96
+ steps:
97
+ - name: Record human confirmation
98
+ run: echo "::notice title=Human approval received::A human approved this pull request for merge."
99
+
100
+ human-approval:
101
+ name: Human approval
102
+ needs: [policy, approval_gate]
103
+ if: >-
104
+ always() &&
105
+ github.event.pull_request.draft == false &&
106
+ needs.policy.result == 'success' &&
107
+ (
108
+ needs.approval_gate.result == 'success' ||
109
+ needs.approval_gate.result == 'skipped'
110
+ )
111
+ runs-on: ubuntu-latest
112
+ steps:
113
+ - name: Report approval decision
114
+ env:
115
+ APPROVAL_REQUIRED: ${{ needs.policy.outputs.required }}
116
+ APPROVAL_REASON: ${{ needs.policy.outputs.reason }}
117
+ run: |
118
+ if [[ "$APPROVAL_REQUIRED" == "true" ]]; then
119
+ title="Human approval received"
120
+ detail="A required human reviewer approved this pull request."
121
+ else
122
+ title="Human approval not required"
123
+ detail="This pull request passed automatically as a routine change."
124
+ fi
125
+
126
+ echo "::notice title=$title::$APPROVAL_REASON"
127
+ {
128
+ echo "## $title"
129
+ echo
130
+ echo "$detail"
131
+ echo
132
+ echo "**Policy decision:** $APPROVAL_REASON"
133
+ } >> "$GITHUB_STEP_SUMMARY"
@@ -0,0 +1,21 @@
1
+ name: Issue metadata
2
+
3
+ on:
4
+ issues:
5
+ types:
6
+ - opened
7
+ - edited
8
+ - typed
9
+ - untyped
10
+ - field_added
11
+ - field_removed
12
+ - labeled
13
+ - unlabeled
14
+
15
+ permissions:
16
+ contents: read
17
+ issues: write
18
+
19
+ jobs:
20
+ validate:
21
+ uses: modwire/modwire/.github/workflows/issue-metadata.yml@main
@@ -0,0 +1,68 @@
1
+ name: Release
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+ workflow_dispatch:
7
+ inputs:
8
+ tag:
9
+ description: Existing SemVer tag to publish, for example v1.2.3
10
+ required: true
11
+ type: string
12
+
13
+ permissions:
14
+ contents: read
15
+
16
+ env:
17
+ RELEASE_TAG: ${{ github.event.release.tag_name || inputs.tag }}
18
+
19
+ jobs:
20
+ build:
21
+ runs-on: ubuntu-latest
22
+ steps:
23
+ - uses: actions/checkout@v6
24
+ with:
25
+ ref: ${{ env.RELEASE_TAG }}
26
+ fetch-depth: 0
27
+ - uses: astral-sh/setup-uv@v7
28
+ with:
29
+ enable-cache: true
30
+ python-version: "3.12"
31
+ - run: uv sync --all-groups --frozen
32
+ - run: make release-check TAG="$RELEASE_TAG"
33
+ - run: make install-check
34
+ - uses: actions/upload-artifact@v7
35
+ with:
36
+ name: distributions
37
+ path: dist/
38
+ if-no-files-found: error
39
+
40
+ publish-pypi:
41
+ needs: build
42
+ runs-on: ubuntu-latest
43
+ environment:
44
+ name: pypi
45
+ url: https://pypi.org/project/modwire-cli/
46
+ permissions:
47
+ id-token: write
48
+ steps:
49
+ - uses: actions/download-artifact@v8
50
+ with:
51
+ name: distributions
52
+ path: dist/
53
+ - uses: pypa/gh-action-pypi-publish@release/v1
54
+
55
+ github-release:
56
+ if: ${{ github.event_name == 'release' }}
57
+ needs: build
58
+ runs-on: ubuntu-latest
59
+ permissions:
60
+ contents: write
61
+ steps:
62
+ - uses: actions/download-artifact@v8
63
+ with:
64
+ name: distributions
65
+ path: dist/
66
+ - run: gh release upload "$RELEASE_TAG" dist/* --clobber --repo "$GITHUB_REPOSITORY"
67
+ env:
68
+ GH_TOKEN: ${{ github.token }}
@@ -0,0 +1,12 @@
1
+ .venv/
2
+ .dev/
3
+ .pytest_cache/
4
+ .ruff_cache/
5
+ .coverage
6
+ htmlcov/
7
+ build/
8
+ dist/
9
+ *.egg-info/
10
+ src/modwire_cli/_version.py
11
+ __pycache__/
12
+ *.py[cod]
@@ -0,0 +1,11 @@
1
+ # Changelog
2
+
3
+ ## [1.0.0] - 2026-07-11
4
+
5
+ - Added the thin standalone `modwire` report command.
6
+ - Added Modwire 5 report catalog and extracted-source health reports.
7
+ - Kept policy evaluation and report contracts inside Modwire Core.
8
+ - Added typed package metadata, artifact validation, CI, and trusted PyPI
9
+ publishing scaffolding.
10
+
11
+ [1.0.0]: https://github.com/modwire/modwire-cli/releases/tag/v1.0.0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Tomasz Szpak
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,5 @@
1
+ include CHANGELOG.md
2
+ include LICENSE
3
+ include README.md
4
+ include src/modwire_cli/py.typed
5
+ recursive-exclude * __pycache__ *.py[cod]
@@ -0,0 +1,21 @@
1
+ .PHONY: lint test verify build release-check install-check
2
+
3
+ lint:
4
+ uv run ruff check .
5
+
6
+ test:
7
+ uv run pytest
8
+
9
+ verify: lint test build
10
+
11
+ build:
12
+ rm -rf dist
13
+ uv build --out-dir dist
14
+ uv run twine check dist/*
15
+
16
+ release-check: build
17
+ @test -n "$(TAG)" || (echo "usage: make release-check TAG=vX.Y.Z" && exit 2)
18
+ uv run python scripts/verify_release.py "$(TAG)" dist
19
+
20
+ install-check:
21
+ uv run --isolated --no-project --with ./dist/*.whl modwire --help
@@ -0,0 +1,78 @@
1
+ Metadata-Version: 2.4
2
+ Name: modwire-cli
3
+ Version: 1.0.0
4
+ Summary: Command-line runtime for the Modwire ecosystem.
5
+ Author: Tomasz Szpak
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/modwire/modwire-cli
8
+ Project-URL: Repository, https://github.com/modwire/modwire-cli
9
+ Project-URL: Issues, https://github.com/modwire/modwire-cli/issues
10
+ Project-URL: Changelog, https://github.com/modwire/modwire-cli/blob/main/CHANGELOG.md
11
+ Keywords: architecture,cli,code-analysis,modwire,static-analysis
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Typing :: Typed
23
+ Classifier: Topic :: Software Development :: Quality Assurance
24
+ Requires-Python: >=3.12
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: click>=8.1
28
+ Requires-Dist: modwire<6,>=5
29
+ Requires-Dist: modwire-extraction<3,>=2
30
+ Provides-Extra: dev
31
+ Requires-Dist: build>=1.2; extra == "dev"
32
+ Requires-Dist: pytest>=8; extra == "dev"
33
+ Requires-Dist: ruff>=0.8; extra == "dev"
34
+ Requires-Dist: twine>=5; extra == "dev"
35
+ Dynamic: license-file
36
+
37
+ # modwire-cli
38
+
39
+ The thin command-line reporter for the Modwire ecosystem. It extracts a source
40
+ map, calls Modwire, and prints Modwire's reports.
41
+
42
+ ## Installation
43
+
44
+ ```bash
45
+ python -m pip install modwire-cli
46
+ ```
47
+
48
+ Python 3.12 or newer is required.
49
+
50
+ ## Usage
51
+
52
+ ```bash
53
+ modwire architecture reports
54
+ modwire --config-dir .modwire architecture health src python
55
+ ```
56
+
57
+ For development:
58
+
59
+ ```bash
60
+ uv sync --all-groups
61
+ uv run pytest
62
+ uv build
63
+ ```
64
+
65
+ Run the same checks used by CI with `make verify`.
66
+
67
+ ## Release
68
+
69
+ Releases use strict `vX.Y.Z` tags. Before creating the first release, configure
70
+ the `pypi` environment and a Trusted Publisher for the `modwire/modwire-cli`
71
+ GitHub repository on PyPI. Then publish a GitHub release:
72
+
73
+ ```bash
74
+ gh release create v1.0.0 --target main --generate-notes --title v1.0.0
75
+ ```
76
+
77
+ The release workflow verifies the tag and distribution metadata, publishes to
78
+ PyPI without a long-lived token, and attaches the distributions to the release.
@@ -0,0 +1,42 @@
1
+ # modwire-cli
2
+
3
+ The thin command-line reporter for the Modwire ecosystem. It extracts a source
4
+ map, calls Modwire, and prints Modwire's reports.
5
+
6
+ ## Installation
7
+
8
+ ```bash
9
+ python -m pip install modwire-cli
10
+ ```
11
+
12
+ Python 3.12 or newer is required.
13
+
14
+ ## Usage
15
+
16
+ ```bash
17
+ modwire architecture reports
18
+ modwire --config-dir .modwire architecture health src python
19
+ ```
20
+
21
+ For development:
22
+
23
+ ```bash
24
+ uv sync --all-groups
25
+ uv run pytest
26
+ uv build
27
+ ```
28
+
29
+ Run the same checks used by CI with `make verify`.
30
+
31
+ ## Release
32
+
33
+ Releases use strict `vX.Y.Z` tags. Before creating the first release, configure
34
+ the `pypi` environment and a Trusted Publisher for the `modwire/modwire-cli`
35
+ GitHub repository on PyPI. Then publish a GitHub release:
36
+
37
+ ```bash
38
+ gh release create v1.0.0 --target main --generate-notes --title v1.0.0
39
+ ```
40
+
41
+ The release workflow verifies the tag and distribution metadata, publishes to
42
+ PyPI without a long-lived token, and attaches the distributions to the release.
@@ -0,0 +1,75 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77", "setuptools-scm[toml]>=8", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "modwire-cli"
7
+ description = "Command-line runtime for the Modwire ecosystem."
8
+ readme = "README.md"
9
+ requires-python = ">=3.12"
10
+ license = "MIT"
11
+ dynamic = ["version"]
12
+ authors = [{ name = "Tomasz Szpak" }]
13
+ keywords = ["architecture", "cli", "code-analysis", "modwire", "static-analysis"]
14
+ classifiers = [
15
+ "Development Status :: 5 - Production/Stable",
16
+ "Environment :: Console",
17
+ "Intended Audience :: Developers",
18
+ "Operating System :: OS Independent",
19
+ "Programming Language :: Python",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3 :: Only",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Programming Language :: Python :: 3.13",
24
+ "Programming Language :: Python :: 3.14",
25
+ "Typing :: Typed",
26
+ "Topic :: Software Development :: Quality Assurance",
27
+ ]
28
+ dependencies = [
29
+ "click>=8.1",
30
+ "modwire>=5,<6",
31
+ "modwire-extraction>=2,<3",
32
+ ]
33
+
34
+ [project.optional-dependencies]
35
+ dev = ["build>=1.2", "pytest>=8", "ruff>=0.8", "twine>=5"]
36
+
37
+ [dependency-groups]
38
+ dev = ["build>=1.2", "pytest>=8", "ruff>=0.8", "twine>=5"]
39
+
40
+ [project.scripts]
41
+ modwire = "modwire_cli:cli"
42
+
43
+ [project.urls]
44
+ Homepage = "https://github.com/modwire/modwire-cli"
45
+ Repository = "https://github.com/modwire/modwire-cli"
46
+ Issues = "https://github.com/modwire/modwire-cli/issues"
47
+ Changelog = "https://github.com/modwire/modwire-cli/blob/main/CHANGELOG.md"
48
+
49
+ [tool.setuptools]
50
+ package-dir = { "" = "src" }
51
+ include-package-data = true
52
+
53
+ [tool.setuptools.package-data]
54
+ modwire_cli = ["py.typed"]
55
+
56
+ [tool.setuptools.exclude-package-data]
57
+ "*" = ["**/__pycache__/*", "**/*.py[cod]"]
58
+
59
+ [tool.setuptools.packages.find]
60
+ where = ["src"]
61
+
62
+ [tool.setuptools_scm]
63
+ fallback_version = "0.0.0.dev0"
64
+ local_scheme = "no-local-version"
65
+ version_file = "src/modwire_cli/_version.py"
66
+
67
+ [tool.pytest.ini_options]
68
+ testpaths = ["tests"]
69
+ addopts = ["-ra", "--strict-config", "--strict-markers"]
70
+ filterwarnings = ["error"]
71
+
72
+ [tool.ruff]
73
+ line-length = 120
74
+ target-version = "py312"
75
+ extend-exclude = ["src/modwire_cli/_version.py"]