archetype-py 0.1.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 (46) hide show
  1. archetype_py-0.1.0/.github/workflows/archetype.yml +36 -0
  2. archetype_py-0.1.0/.github/workflows/ci.yml +35 -0
  3. archetype_py-0.1.0/.github/workflows/publish.yml +62 -0
  4. archetype_py-0.1.0/.gitignore +38 -0
  5. archetype_py-0.1.0/CHANGELOG.md +15 -0
  6. archetype_py-0.1.0/LICENSE +21 -0
  7. archetype_py-0.1.0/PKG-INFO +195 -0
  8. archetype_py-0.1.0/README.md +172 -0
  9. archetype_py-0.1.0/archetype/__init__.py +3 -0
  10. archetype_py-0.1.0/archetype/analysis/__init__.py +3 -0
  11. archetype_py-0.1.0/archetype/analysis/ast_utils.py +19 -0
  12. archetype_py-0.1.0/archetype/analysis/imports.py +97 -0
  13. archetype_py-0.1.0/archetype/analysis/init.py +1 -0
  14. archetype_py-0.1.0/archetype/analysis/models.py +26 -0
  15. archetype_py-0.1.0/archetype/check.py +70 -0
  16. archetype_py-0.1.0/archetype/dsl/__init__.py +3 -0
  17. archetype_py-0.1.0/archetype/dsl/init.py +1 -0
  18. archetype_py-0.1.0/archetype/dsl/query.py +114 -0
  19. archetype_py-0.1.0/archetype/init.py +8 -0
  20. archetype_py-0.1.0/archetype/plugin/__init__.py +3 -0
  21. archetype_py-0.1.0/archetype/plugin/init.py +1 -0
  22. archetype_py-0.1.0/archetype/plugin/pytest_plugin.py +75 -0
  23. archetype_py-0.1.0/archetype/reporter.py +65 -0
  24. archetype_py-0.1.0/archetype/rule.py +61 -0
  25. archetype_py-0.1.0/archetype/rules/__init__.py +8 -0
  26. archetype_py-0.1.0/archetype/rules/boundaries.py +57 -0
  27. archetype_py-0.1.0/archetype/rules/cycles.py +69 -0
  28. archetype_py-0.1.0/archetype/rules/layers.py +69 -0
  29. archetype_py-0.1.0/archetype/rules/naming.py +116 -0
  30. archetype_py-0.1.0/architecture.py +18 -0
  31. archetype_py-0.1.0/pyproject.toml +49 -0
  32. archetype_py-0.1.0/tests/fixtures/simple_project/simple_project/api.py +13 -0
  33. archetype_py-0.1.0/tests/fixtures/simple_project/simple_project/db.py +1 -0
  34. archetype_py-0.1.0/tests/fixtures/simple_project/simple_project/internal/init.py +1 -0
  35. archetype_py-0.1.0/tests/fixtures/simple_project/simple_project/internal/tokens.py +1 -0
  36. archetype_py-0.1.0/tests/fixtures/simple_project/simple_project/main.py +3 -0
  37. archetype_py-0.1.0/tests/fixtures/simple_project/simple_project/services.py +12 -0
  38. archetype_py-0.1.0/tests/test_cli.py +132 -0
  39. archetype_py-0.1.0/tests/test_dsl.py +60 -0
  40. archetype_py-0.1.0/tests/test_graph.py +35 -0
  41. archetype_py-0.1.0/tests/test_plugin.py +100 -0
  42. archetype_py-0.1.0/tests/test_rule.py +89 -0
  43. archetype_py-0.1.0/tests/test_rules_boundaries.py +58 -0
  44. archetype_py-0.1.0/tests/test_rules_cycles.py +76 -0
  45. archetype_py-0.1.0/tests/test_rules_layers.py +69 -0
  46. archetype_py-0.1.0/tests/test_rules_naming.py +68 -0
@@ -0,0 +1,36 @@
1
+ name: Archetype Check Template
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+
9
+ jobs:
10
+ archetype:
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ # Pull down your repository code so CI can inspect it.
15
+ - name: Checkout repository
16
+ uses: actions/checkout@v4
17
+
18
+ # Install Python 3.11 so the Archetype CLI can run.
19
+ - name: Set up Python
20
+ uses: actions/setup-python@v5
21
+ with:
22
+ python-version: "3.11"
23
+
24
+ # Install Archetype from PyPI into the CI environment.
25
+ - name: Install Archetype
26
+ run: |
27
+ python -m pip install --upgrade pip
28
+ pip install archetype-py
29
+
30
+ # Run architecture rules defined in architecture.py.
31
+ # This step exits non-zero on violations, which fails the workflow.
32
+ - name: Run architecture checks
33
+ run: archetype check .
34
+
35
+ # If your team already runs pytest in CI, you can skip this workflow file.
36
+ # Archetype's pytest plugin runs architecture.py rules automatically during pytest.
@@ -0,0 +1,35 @@
1
+ name: Archetype Library CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ python-version: ["3.11", "3.12"]
16
+
17
+ steps:
18
+ - name: Checkout repository
19
+ uses: actions/checkout@v4
20
+
21
+ - name: Set up Python
22
+ uses: actions/setup-python@v5
23
+ with:
24
+ python-version: ${{ matrix.python-version }}
25
+
26
+ - name: Install package and development dependencies
27
+ run: |
28
+ python -m pip install --upgrade pip
29
+ pip install -e ".[dev]"
30
+
31
+ - name: Run full test suite
32
+ run: pytest
33
+
34
+ - name: Run Archetype against this codebase
35
+ run: archetype check .
@@ -0,0 +1,62 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+
12
+ steps:
13
+ # Checkout repository contents for test execution.
14
+ - name: Checkout repository
15
+ uses: actions/checkout@v4
16
+
17
+ # Install Python runtime used for tests and packaging checks.
18
+ - name: Set up Python
19
+ uses: actions/setup-python@v5
20
+ with:
21
+ python-version: "3.11"
22
+
23
+ # Install the project in editable mode with dev dependencies.
24
+ - name: Install dependencies
25
+ run: |
26
+ python -m pip install --upgrade pip
27
+ pip install -e ".[dev]"
28
+
29
+ # Run the full test suite; publication is blocked on any failure.
30
+ - name: Run tests
31
+ run: pytest
32
+
33
+ publish:
34
+ runs-on: ubuntu-latest
35
+ needs: test
36
+ permissions:
37
+ id-token: write
38
+ contents: read
39
+
40
+ steps:
41
+ # Checkout repository contents so the package can be built.
42
+ - name: Checkout repository
43
+ uses: actions/checkout@v4
44
+
45
+ # Set up Python for building distribution artifacts.
46
+ - name: Set up Python
47
+ uses: actions/setup-python@v5
48
+ with:
49
+ python-version: "3.11"
50
+
51
+ # Install Hatch and build source/wheel distributions.
52
+ - name: Build package
53
+ run: |
54
+ python -m pip install --upgrade pip
55
+ pip install hatch
56
+ hatch build
57
+
58
+ # Publish using PyPI Trusted Publishing (no API token secret required).
59
+ # Before this works, configure Trusted Publishing in your PyPI project:
60
+ # https://pypi.org/manage/account/publishing
61
+ - name: Publish to PyPI
62
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,38 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Distribution / packaging
7
+ build/
8
+ dist/
9
+ *.egg-info/
10
+ .eggs/
11
+
12
+ # Virtual environments
13
+ .venv/
14
+ venv/
15
+ env/
16
+ ENV/
17
+
18
+ # Test / coverage
19
+ .pytest_cache/
20
+ .coverage
21
+ .coverage.*
22
+ htmlcov/
23
+
24
+ # Type checkers / linters
25
+ .mypy_cache/
26
+ .ruff_cache/
27
+ .pyre/
28
+
29
+ # IDE / editor
30
+ .vscode/
31
+ .idea/
32
+
33
+ # OS files
34
+ .DS_Store
35
+
36
+ # Hatch
37
+ .hatch/
38
+ LAUNCH.md
@@ -0,0 +1,15 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 - 2026-05-09
4
+
5
+ ### Added
6
+ - Introduced static import graph analysis that maps module dependencies without executing application code.
7
+ - Added a rule authoring model using `@rule` decorators and a central registry so architectural checks are defined as plain Python.
8
+ - Shipped a readable query DSL with project loading, import constraints, and cycle checks for writing architecture policies.
9
+ - Added a CLI command (`archetype check`) that discovers `architecture.py`, executes rules, and returns CI-friendly exit codes.
10
+ - Added a pytest plugin that auto-collects `architecture.py` rules as native pytest test items with readable failure output.
11
+ - Added a shared reporting layer for consistent violation formatting across CLI and pytest execution paths.
12
+ - Added built-in rule packs for layering constraints, module boundaries, naming conventions, and circular import detection.
13
+ - Added test fixtures and comprehensive pytest coverage for graph construction, DSL behavior, CLI behavior, plugin collection, and built-in rules.
14
+ - Added GitHub Actions workflows for reusable architecture checks in downstream projects and matrix CI for Archetype development.
15
+ - Added packaging and release automation for PyPI publication using GitHub Actions Trusted Publishing.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) [YEAR] [AUTHOR NAME]
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,195 @@
1
+ Metadata-Version: 2.4
2
+ Name: archetype-py
3
+ Version: 0.1.0
4
+ Summary: Archetype statically analyzes Python projects to enforce architectural rules as code.
5
+ Project-URL: Homepage, https://github.com/your-org/your-repo
6
+ Project-URL: Documentation, https://github.com/your-org/your-repo
7
+ Author-email: Mossab Arektout <mossabarektout2000@gmail.com>
8
+ License: MIT
9
+ License-File: LICENSE
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Software Development :: Quality Assurance
15
+ Requires-Python: >=3.11
16
+ Requires-Dist: click
17
+ Requires-Dist: networkx
18
+ Requires-Dist: rich
19
+ Provides-Extra: dev
20
+ Requires-Dist: hatch; extra == 'dev'
21
+ Requires-Dist: pytest; extra == 'dev'
22
+ Description-Content-Type: text/markdown
23
+
24
+ ![PyPI](https://img.shields.io/pypi/v/archetype) ![Python](https://img.shields.io/pypi/pyversions/archetype) ![License](https://img.shields.io/badge/license-MIT-green) ![CI](https://img.shields.io/github/actions/workflow/status/your-org/your-repo/ci.yml?branch=main)
25
+
26
+ ## Architectural rules should not live in people’s heads
27
+ Architectural rules usually exist in engineers’ heads but nowhere in the codebase.
28
+ Archetype turns those rules into executable Python checks that run in `archetype check` and `pytest`.
29
+
30
+ ```python
31
+ # architecture.py
32
+ from archetype import imports, rule
33
+
34
+ @rule("api does not import db")
35
+ def api_not_db() -> None:
36
+ imports("myapp.api").must_not_import("myapp.db")
37
+
38
+ @rule("services only import db")
39
+ def services_only_db() -> None:
40
+ imports("myapp.services").must_only_import_from("myapp.db")
41
+ ```
42
+
43
+ ```text
44
+ $ archetype check .
45
+ ✓ api does not import db
46
+ ✗ services only import db
47
+ - myapp.services.user -> myapp.cache: Module 'myapp.services.user' imports 'myapp.cache', which is outside the allowed set: ('myapp.db',).
48
+ Summary: 1 passed, 1 failed, 2 total rules.
49
+ ```
50
+
51
+ ## Installation
52
+ ```bash
53
+ pip install archetype-py
54
+ ```
55
+
56
+ ## Quickstart
57
+ 1. Install Archetype.
58
+
59
+ ```bash
60
+ pip install archetype-py
61
+ ```
62
+
63
+ 2. Create `architecture.py` in your project root.
64
+
65
+ ```bash
66
+ touch architecture.py
67
+ ```
68
+
69
+ 3. Add your first rule with the imports DSL.
70
+
71
+ ```python
72
+ # architecture.py
73
+ from archetype import imports, rule
74
+
75
+ @rule("api does not import db")
76
+ def api_not_db() -> None:
77
+ imports("myapp.api").must_not_import("myapp.db")
78
+ ```
79
+
80
+ 4. Run the checker.
81
+
82
+ ```bash
83
+ archetype check .
84
+ ```
85
+
86
+ 5. Read the output and fix violations.
87
+
88
+ ```text
89
+ ✓ api does not import db
90
+ Summary: 1 passed, 0 failed, 1 total rules.
91
+ ```
92
+
93
+ If your project already runs `pytest`, running `pytest` is sufficient because Archetype rules are collected and executed by the pytest plugin.
94
+
95
+ ## Why Archetype exists
96
+ Style tools enforce how code looks. Type tools enforce what values can flow through code. Architectural tools enforce which parts of the system are allowed to depend on which other parts.
97
+
98
+ Pylint and similar linters are strong at local code quality checks, and Mypy is strong at static type correctness. Neither is designed to express team-level dependency contracts like “API cannot import DB” or “internal modules are private outside their package boundary.”
99
+
100
+ Archetype keeps rules in `architecture.py` as normal Python functions, not static YAML declarations. That makes rules executable, reviewable, testable, and easy to evolve with the codebase using the same language and tooling your team already uses.
101
+
102
+ ## Built-in rules reference
103
+ ### `layers`
104
+ Enforces that lower layers do not import upper layers.
105
+
106
+ ```python
107
+ from archetype import rule
108
+ from archetype.rules import layers
109
+
110
+ @rule("layers are ordered")
111
+ def layer_order() -> None:
112
+ layers(["myapp.api", "myapp.services", "myapp.db"]).are_ordered()
113
+ ```
114
+
115
+ ### `module` (module boundaries)
116
+ Enforces that a protected internal module is only imported from an allowed parent scope.
117
+
118
+ ```python
119
+ from archetype import rule
120
+ from archetype.rules import module
121
+
122
+ @rule("internal auth is private")
123
+ def auth_boundary() -> None:
124
+ module("myapp.auth.internal").only_imported_within("myapp.auth")
125
+ ```
126
+
127
+ ### `classes_in` and `functions_in` (naming conventions)
128
+ Enforces class naming patterns and required top-level functions in matched modules.
129
+
130
+ ```python
131
+ from archetype import rule
132
+ from archetype.rules import classes_in, functions_in
133
+
134
+ @rule("service classes end with Service")
135
+ def class_names() -> None:
136
+ classes_in("myapp.services").all_match(r".*Service$")
137
+
138
+ @rule("api modules expose handle")
139
+ def api_handle_exists() -> None:
140
+ functions_in("myapp.api").must_include("handle")
141
+ ```
142
+
143
+ ### `no_cycles`
144
+ Enforces that there are no import cycles in the whole project or in a selected module scope.
145
+
146
+ ```python
147
+ from archetype import rule
148
+ from archetype.rules import no_cycles
149
+
150
+ @rule("no cycles in services")
151
+ def services_no_cycles() -> None:
152
+ no_cycles("myapp.services")
153
+ ```
154
+
155
+ ## Writing custom rules
156
+ ```python
157
+ from archetype import imports, rule
158
+
159
+ @rule("custom architecture policy")
160
+ def custom_policy() -> None:
161
+ imports("myapp.api").must_not_import("myapp.db")
162
+ imports("myapp.services").has_no_cycles()
163
+ imports("myapp.services").must_only_import_from("myapp.db", "myapp.shared")
164
+ ```
165
+
166
+ Any Python function decorated with `@rule` that returns without raising is a passing rule. Rules can use the full Python language, so you can encode architecture constraints that do not fit generic linters or static config.
167
+
168
+ ## CI integration
169
+ ```yaml
170
+ name: Archetype Check
171
+
172
+ on:
173
+ push:
174
+ branches: [main]
175
+ pull_request:
176
+
177
+ jobs:
178
+ archetype:
179
+ runs-on: ubuntu-latest
180
+ steps:
181
+ - uses: actions/checkout@v4
182
+ - uses: actions/setup-python@v5
183
+ with:
184
+ python-version: "3.11"
185
+ - run: |
186
+ python -m pip install --upgrade pip
187
+ pip install archetype-py
188
+ - run: archetype check .
189
+ ```
190
+
191
+ If your CI already runs `pytest`, no additional CI configuration is required.
192
+
193
+ ## Contributing
194
+ Source code and issue tracking are in the GitHub repository: `https://github.com/your-org/your-repo`.
195
+ Contributions are welcome; open an issue first to discuss scope before submitting a pull request.
@@ -0,0 +1,172 @@
1
+ ![PyPI](https://img.shields.io/pypi/v/archetype) ![Python](https://img.shields.io/pypi/pyversions/archetype) ![License](https://img.shields.io/badge/license-MIT-green) ![CI](https://img.shields.io/github/actions/workflow/status/your-org/your-repo/ci.yml?branch=main)
2
+
3
+ ## Architectural rules should not live in people’s heads
4
+ Architectural rules usually exist in engineers’ heads but nowhere in the codebase.
5
+ Archetype turns those rules into executable Python checks that run in `archetype check` and `pytest`.
6
+
7
+ ```python
8
+ # architecture.py
9
+ from archetype import imports, rule
10
+
11
+ @rule("api does not import db")
12
+ def api_not_db() -> None:
13
+ imports("myapp.api").must_not_import("myapp.db")
14
+
15
+ @rule("services only import db")
16
+ def services_only_db() -> None:
17
+ imports("myapp.services").must_only_import_from("myapp.db")
18
+ ```
19
+
20
+ ```text
21
+ $ archetype check .
22
+ ✓ api does not import db
23
+ ✗ services only import db
24
+ - myapp.services.user -> myapp.cache: Module 'myapp.services.user' imports 'myapp.cache', which is outside the allowed set: ('myapp.db',).
25
+ Summary: 1 passed, 1 failed, 2 total rules.
26
+ ```
27
+
28
+ ## Installation
29
+ ```bash
30
+ pip install archetype-py
31
+ ```
32
+
33
+ ## Quickstart
34
+ 1. Install Archetype.
35
+
36
+ ```bash
37
+ pip install archetype-py
38
+ ```
39
+
40
+ 2. Create `architecture.py` in your project root.
41
+
42
+ ```bash
43
+ touch architecture.py
44
+ ```
45
+
46
+ 3. Add your first rule with the imports DSL.
47
+
48
+ ```python
49
+ # architecture.py
50
+ from archetype import imports, rule
51
+
52
+ @rule("api does not import db")
53
+ def api_not_db() -> None:
54
+ imports("myapp.api").must_not_import("myapp.db")
55
+ ```
56
+
57
+ 4. Run the checker.
58
+
59
+ ```bash
60
+ archetype check .
61
+ ```
62
+
63
+ 5. Read the output and fix violations.
64
+
65
+ ```text
66
+ ✓ api does not import db
67
+ Summary: 1 passed, 0 failed, 1 total rules.
68
+ ```
69
+
70
+ If your project already runs `pytest`, running `pytest` is sufficient because Archetype rules are collected and executed by the pytest plugin.
71
+
72
+ ## Why Archetype exists
73
+ Style tools enforce how code looks. Type tools enforce what values can flow through code. Architectural tools enforce which parts of the system are allowed to depend on which other parts.
74
+
75
+ Pylint and similar linters are strong at local code quality checks, and Mypy is strong at static type correctness. Neither is designed to express team-level dependency contracts like “API cannot import DB” or “internal modules are private outside their package boundary.”
76
+
77
+ Archetype keeps rules in `architecture.py` as normal Python functions, not static YAML declarations. That makes rules executable, reviewable, testable, and easy to evolve with the codebase using the same language and tooling your team already uses.
78
+
79
+ ## Built-in rules reference
80
+ ### `layers`
81
+ Enforces that lower layers do not import upper layers.
82
+
83
+ ```python
84
+ from archetype import rule
85
+ from archetype.rules import layers
86
+
87
+ @rule("layers are ordered")
88
+ def layer_order() -> None:
89
+ layers(["myapp.api", "myapp.services", "myapp.db"]).are_ordered()
90
+ ```
91
+
92
+ ### `module` (module boundaries)
93
+ Enforces that a protected internal module is only imported from an allowed parent scope.
94
+
95
+ ```python
96
+ from archetype import rule
97
+ from archetype.rules import module
98
+
99
+ @rule("internal auth is private")
100
+ def auth_boundary() -> None:
101
+ module("myapp.auth.internal").only_imported_within("myapp.auth")
102
+ ```
103
+
104
+ ### `classes_in` and `functions_in` (naming conventions)
105
+ Enforces class naming patterns and required top-level functions in matched modules.
106
+
107
+ ```python
108
+ from archetype import rule
109
+ from archetype.rules import classes_in, functions_in
110
+
111
+ @rule("service classes end with Service")
112
+ def class_names() -> None:
113
+ classes_in("myapp.services").all_match(r".*Service$")
114
+
115
+ @rule("api modules expose handle")
116
+ def api_handle_exists() -> None:
117
+ functions_in("myapp.api").must_include("handle")
118
+ ```
119
+
120
+ ### `no_cycles`
121
+ Enforces that there are no import cycles in the whole project or in a selected module scope.
122
+
123
+ ```python
124
+ from archetype import rule
125
+ from archetype.rules import no_cycles
126
+
127
+ @rule("no cycles in services")
128
+ def services_no_cycles() -> None:
129
+ no_cycles("myapp.services")
130
+ ```
131
+
132
+ ## Writing custom rules
133
+ ```python
134
+ from archetype import imports, rule
135
+
136
+ @rule("custom architecture policy")
137
+ def custom_policy() -> None:
138
+ imports("myapp.api").must_not_import("myapp.db")
139
+ imports("myapp.services").has_no_cycles()
140
+ imports("myapp.services").must_only_import_from("myapp.db", "myapp.shared")
141
+ ```
142
+
143
+ Any Python function decorated with `@rule` that returns without raising is a passing rule. Rules can use the full Python language, so you can encode architecture constraints that do not fit generic linters or static config.
144
+
145
+ ## CI integration
146
+ ```yaml
147
+ name: Archetype Check
148
+
149
+ on:
150
+ push:
151
+ branches: [main]
152
+ pull_request:
153
+
154
+ jobs:
155
+ archetype:
156
+ runs-on: ubuntu-latest
157
+ steps:
158
+ - uses: actions/checkout@v4
159
+ - uses: actions/setup-python@v5
160
+ with:
161
+ python-version: "3.11"
162
+ - run: |
163
+ python -m pip install --upgrade pip
164
+ pip install archetype-py
165
+ - run: archetype check .
166
+ ```
167
+
168
+ If your CI already runs `pytest`, no additional CI configuration is required.
169
+
170
+ ## Contributing
171
+ Source code and issue tracking are in the GitHub repository: `https://github.com/your-org/your-repo`.
172
+ Contributions are welcome; open an issue first to discuss scope before submitting a pull request.
@@ -0,0 +1,3 @@
1
+ """Archetype public package exports."""
2
+
3
+ from archetype.init import * # noqa: F401,F403
@@ -0,0 +1,3 @@
1
+ """Archetype analysis subpackage."""
2
+
3
+ from archetype.analysis.init import * # noqa: F401,F403
@@ -0,0 +1,19 @@
1
+ """AST traversal helpers used by Archetype static analysis."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import ast
6
+
7
+
8
+ def get_class_names(tree: ast.AST) -> list[str]:
9
+ """Return all class names defined anywhere in the AST."""
10
+ return [node.name for node in ast.walk(tree) if isinstance(node, ast.ClassDef)]
11
+
12
+
13
+ def get_top_level_function_names(tree: ast.AST) -> list[str]:
14
+ """Return names of module-level functions only (excluding class methods)."""
15
+ return [
16
+ node.name
17
+ for node in getattr(tree, "body", [])
18
+ if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))
19
+ ]