codmap 0.0.25__tar.gz → 0.0.26__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.
- {codmap-0.0.25/codmap.egg-info → codmap-0.0.26}/PKG-INFO +2 -2
- {codmap-0.0.25 → codmap-0.0.26}/README.md +1 -1
- {codmap-0.0.25 → codmap-0.0.26}/codemap/arch.py +22 -0
- {codmap-0.0.25 → codmap-0.0.26/codmap.egg-info}/PKG-INFO +2 -2
- {codmap-0.0.25 → codmap-0.0.26}/codmap.egg-info/SOURCES.txt +1 -0
- {codmap-0.0.25 → codmap-0.0.26}/pyproject.toml +1 -1
- codmap-0.0.26/tests/test_r1c76_contract_table_typo.py +68 -0
- {codmap-0.0.25 → codmap-0.0.26}/LICENSE +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/__init__.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/apidiff.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/cli.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/diagnostics.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/extract/__init__.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/extract/attrflow.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/extract/behavior.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/extract/dataflow.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/extract/dispatch.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/extract/griffe_extractor.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/extract/gsource.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/extract/probe.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/extract/roots.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/extract/union.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/freshness.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/incremental.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/integrations/__init__.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/integrations/base.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/integrations/cocoindex.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/integrations/gate.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/integrations/gitnexus.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/integrations/registry.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/integrations/transport.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/model.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/provenance.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/query.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/scope.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/serve/__init__.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/serve/_scip_pb2.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/serve/api_surface.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/serve/apidiff.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/serve/architecture.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/serve/audit.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/serve/check.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/serve/ctags.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/serve/currency.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/serve/impact.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/serve/limits.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/serve/livingdocs.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/serve/mcp_server.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/serve/mermaid.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/serve/pack.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/serve/rag.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/serve/review.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/serve/scip.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/serve/semantic.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/serve/server.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/serve/session.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/serve/subsystems.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/serve/vault.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/store.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/tomlio.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codemap/watch.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codmap.egg-info/dependency_links.txt +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codmap.egg-info/entry_points.txt +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codmap.egg-info/requires.txt +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/codmap.egg-info/top_level.txt +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/setup.cfg +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_epistemic.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_gitnexus_router.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_impact_depth.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_integrations.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_issue3_serve_freshness.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_livingdocs.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_m0_api_surface.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_m11_argcontract.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_m12_dataflow.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_m15_review.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_m16_architecture.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_m17_mcp.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_m18_freshness.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_m1_5_semantics.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_m1_query.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_m2_views.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_m32_watch.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_m3_serve.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_m4_behavior.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_m5_deep.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_m6_repo_scope.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_m7_dispatch.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_m9_family.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_pack_honesty.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c13_callgraph_accuracy.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c13_grep_vs_graph.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c16_semantic.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c20_attribute_edges.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c21_flat_layout.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c22_source_visible_refs.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c23_hard_python.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c24_test_mapping.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c25_provenance.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c26_deep_union.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c27_config_honesty.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c28_limit_envelope.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c29_lazy_imports.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c2_ctags.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c30_local_import_calls.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c30f1_reexport_calls.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c30f2_check_scope.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c31_path_origin.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c32_report_json.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c33_query_signature.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c34_signature_kinds.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c35_contract_location.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c36_target_resolution.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c37_rule_mutation.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c38_tool_drift.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c39_edge_resolution.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c3_arch_contract.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c3_dogfood.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c40_flow_reach.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c41_scope_membership.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c42_deep_tier_stability.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c43_incremental_splice.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c44_absent_answers.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c45_repeat_union.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c46_shadowed_definitions.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c47_incremental_resample.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c48_type_checking_imports.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c49_type_only_cycles.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c4_complexity.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c50_flow_entry_points.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c53_narrowing_declared.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c54_deterministic_rendering.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c55_override_grade.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c56_stub_files.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c57_facade_package.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c58_cycle_tangles.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c59_completeness_drop.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c5_apidiff.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c60_nested_definitions.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c62_phantom_rules.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c63_answer_format.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c64_dependency_probe.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c66_pack_direction.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c68_dotted_imports.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c69_contract_validation.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c6_pack.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c70_check_graph_currency.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c71_attribute_chain_calls.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c72_flat_inference_in_packages.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c73_cli_version.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c74_call_site_conservation.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c75_reexported_class_calls.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c7_edge_vocab.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c8_deadcode.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_r1c9_incremental.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_scip_export.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_scope.py +0 -0
- {codmap-0.0.25 → codmap-0.0.26}/tests/test_subsystems.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codmap
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.26
|
|
4
4
|
Summary: Static analyzer that turns a package's source into a queryable code graph.
|
|
5
5
|
Author-email: kogriv <kogriv@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -44,7 +44,7 @@ and a **SCIP index** for interop with Sourcegraph / Glean and other precise-code
|
|
|
44
44
|
|
|
45
45
|
[](https://github.com/kogriv/codemap/actions/workflows/ci.yml)
|
|
46
46
|
|
|
47
|
-
**Status:** 🟢 M0–M20 implemented + research track (R1/R2) — schema 0.13, **
|
|
47
|
+
**Status:** 🟢 M0–M20 implemented + research track (R1/R2) — schema 0.13, **1136 tests with no failures on
|
|
48
48
|
Python 3.11–3.14** ([in CI](docs/ci.md): the full suite including the dogfood pass, a determinism check, a
|
|
49
49
|
wheel smoke test, and ctags/SCIP interop against the real CLIs), warm serve surface with 31 ops (28 exposed
|
|
50
50
|
as MCP tools), and SCIP export. See **[DESIGN.md](DESIGN.md)** (product design &
|
|
@@ -8,7 +8,7 @@ and a **SCIP index** for interop with Sourcegraph / Glean and other precise-code
|
|
|
8
8
|
|
|
9
9
|
[](https://github.com/kogriv/codemap/actions/workflows/ci.yml)
|
|
10
10
|
|
|
11
|
-
**Status:** 🟢 M0–M20 implemented + research track (R1/R2) — schema 0.13, **
|
|
11
|
+
**Status:** 🟢 M0–M20 implemented + research track (R1/R2) — schema 0.13, **1136 tests with no failures on
|
|
12
12
|
Python 3.11–3.14** ([in CI](docs/ci.md): the full suite including the dogfood pass, a determinism check, a
|
|
13
13
|
wheel smoke test, and ctags/SCIP interop against the real CLIs), warm serve surface with 31 ops (28 exposed
|
|
14
14
|
as MCP tools), and SCIP export. See **[DESIGN.md](DESIGN.md)** (product design &
|
|
@@ -101,9 +101,31 @@ def load_contract(root: str | Path = ".") -> ArchitectureContract:
|
|
|
101
101
|
data, error = read_toml(path)
|
|
102
102
|
if error:
|
|
103
103
|
return ArchitectureContract(error=error, path=str(path))
|
|
104
|
+
near = _near_miss_tables(data)
|
|
105
|
+
if near:
|
|
106
|
+
return ArchitectureContract(error=near, path=str(path))
|
|
104
107
|
return replace(parse_contract(data.get("architecture", {})), path=str(path))
|
|
105
108
|
|
|
106
109
|
|
|
110
|
+
def _near_miss_tables(data: dict) -> str | None:
|
|
111
|
+
"""R1-C76 (design ``contract_table_typo.md``): a table named like ``[architecture]`` but not it.
|
|
112
|
+
|
|
113
|
+
``[architectur]`` used to read as "no contract", exit 0: R1-C69 closed the schema inside the
|
|
114
|
+
table, and the table name stayed the one typo that turned a gate green. Refused even beside a
|
|
115
|
+
real ``[architecture]`` (D2): its rules would never run. Other tables are not checked (D3).
|
|
116
|
+
"""
|
|
117
|
+
import difflib
|
|
118
|
+
|
|
119
|
+
names = [k for k, v in data.items()
|
|
120
|
+
if k != "architecture" and isinstance(v, dict)
|
|
121
|
+
and difflib.SequenceMatcher(None, k.lower(), "architecture").ratio() >= 0.8]
|
|
122
|
+
if not names:
|
|
123
|
+
return None
|
|
124
|
+
listed = ", ".join(f"`[{k}]`" for k in names)
|
|
125
|
+
return (f"{listed} looks like a misspelling of `[architecture]`; codemap reads only "
|
|
126
|
+
"`[architecture]`, so its rules would never run")
|
|
127
|
+
|
|
128
|
+
|
|
107
129
|
#: R1-C69: the closed schema of ``[architecture]``. A key outside it is an error, not a skip.
|
|
108
130
|
_FLAGS = ("no_cycles", "no_lazy_cycles", "no_type_only_cycles", "exhaustive", "no_phantom_rules")
|
|
109
131
|
_KNOWN_KEYS = ("layers", "independent", "forbidden") + _FLAGS
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codmap
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.26
|
|
4
4
|
Summary: Static analyzer that turns a package's source into a queryable code graph.
|
|
5
5
|
Author-email: kogriv <kogriv@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -44,7 +44,7 @@ and a **SCIP index** for interop with Sourcegraph / Glean and other precise-code
|
|
|
44
44
|
|
|
45
45
|
[](https://github.com/kogriv/codemap/actions/workflows/ci.yml)
|
|
46
46
|
|
|
47
|
-
**Status:** 🟢 M0–M20 implemented + research track (R1/R2) — schema 0.13, **
|
|
47
|
+
**Status:** 🟢 M0–M20 implemented + research track (R1/R2) — schema 0.13, **1136 tests with no failures on
|
|
48
48
|
Python 3.11–3.14** ([in CI](docs/ci.md): the full suite including the dogfood pass, a determinism check, a
|
|
49
49
|
wheel smoke test, and ctags/SCIP interop against the real CLIs), warm serve surface with 31 ops (28 exposed
|
|
50
50
|
as MCP tools), and SCIP export. See **[DESIGN.md](DESIGN.md)** (product design &
|
|
@@ -147,6 +147,7 @@ tests/test_r1c72_flat_inference_in_packages.py
|
|
|
147
147
|
tests/test_r1c73_cli_version.py
|
|
148
148
|
tests/test_r1c74_call_site_conservation.py
|
|
149
149
|
tests/test_r1c75_reexported_class_calls.py
|
|
150
|
+
tests/test_r1c76_contract_table_typo.py
|
|
150
151
|
tests/test_r1c7_edge_vocab.py
|
|
151
152
|
tests/test_r1c8_deadcode.py
|
|
152
153
|
tests/test_r1c9_incremental.py
|
|
@@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta"
|
|
|
9
9
|
# version. README says this plainly, since `pip install codmap` / `import codemap` is a
|
|
10
10
|
# seam a reader will otherwise hit by surprise.
|
|
11
11
|
name = "codmap"
|
|
12
|
-
version = "0.0.
|
|
12
|
+
version = "0.0.26"
|
|
13
13
|
description = "Static analyzer that turns a package's source into a queryable code graph."
|
|
14
14
|
readme = "README.md"
|
|
15
15
|
# M20/D1: measured, not assumed. Each release of the declared range runs the full suite in
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""R1-C76 — a misspelled `[architecture]` table is refused, not read as "no contract".
|
|
2
|
+
|
|
3
|
+
Found by asking codemap the question its import-linter card asked of import-linter (zero contracts pass).
|
|
4
|
+
Design `docs/design/contract_table_typo.md`.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import pytest
|
|
10
|
+
|
|
11
|
+
from codemap import arch
|
|
12
|
+
from codemap.cli import main
|
|
13
|
+
from codemap.extract import extract
|
|
14
|
+
from codemap.query import Query
|
|
15
|
+
from codemap.serve.check import build_check
|
|
16
|
+
|
|
17
|
+
RULE = 'forbidden = [{from="core", to="analysis"}]\n'
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@pytest.fixture(scope="module")
|
|
21
|
+
def pkg(tmp_path_factory):
|
|
22
|
+
root = tmp_path_factory.mktemp("r1c76") / "tpkg"
|
|
23
|
+
for d in (root, root / "core", root / "analysis"):
|
|
24
|
+
d.mkdir(parents=True, exist_ok=True)
|
|
25
|
+
(d / "__init__.py").write_text("")
|
|
26
|
+
(root / "analysis" / "b.py").write_text("X = 1\n")
|
|
27
|
+
(root / "core" / "a.py").write_text("from tpkg.analysis import b\n")
|
|
28
|
+
return root
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _check(tmp_path, pkg, toml, capsys, *extra) -> tuple[int, str]:
|
|
32
|
+
if toml is not None:
|
|
33
|
+
(tmp_path / "codemap.toml").write_text(toml)
|
|
34
|
+
rc = main(["check", "--build", str(pkg), "--root", str(tmp_path), *extra])
|
|
35
|
+
return rc, capsys.readouterr().out
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@pytest.mark.parametrize("toml, name", [
|
|
39
|
+
(f"[architectur]\n{RULE}", "architectur"),
|
|
40
|
+
(f"[Architecture]\n{RULE}", "Architecture"),
|
|
41
|
+
(f"[archtecture]\n{RULE}", "archtecture"),
|
|
42
|
+
(f"[architecture]\nno_cycles = true\n\n[architectur]\n{RULE}", "architectur"),
|
|
43
|
+
], ids=["A1", "A2-case", "A2-letter", "A3-both"])
|
|
44
|
+
def test_a_near_miss_table_is_refused(tmp_path, pkg, capsys, toml, name):
|
|
45
|
+
rc, out = _check(tmp_path, pkg, toml, capsys)
|
|
46
|
+
assert rc == 2, out
|
|
47
|
+
assert f"`[{name}]`" in out and "`[architecture]`" in out
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def test_mcp_check_carries_the_refusal(tmp_path, pkg):
|
|
51
|
+
(tmp_path / "codemap.toml").write_text(f"[architectur]\n{RULE}")
|
|
52
|
+
c = arch.load_contract(tmp_path)
|
|
53
|
+
q = Query(extract(str(pkg)))
|
|
54
|
+
payload = build_check(q, c, arch.check_contract(q, c))
|
|
55
|
+
assert payload["ok"] is False
|
|
56
|
+
assert "`[architectur]`" in payload["contract_error"]
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def test_what_was_valid_or_absent_answers_as_before(tmp_path, pkg, capsys):
|
|
60
|
+
rc, out = _check(tmp_path, pkg, f"[architecture]\n{RULE}", capsys)
|
|
61
|
+
assert rc == 2 and "1 rule(s) broken" in out # a real violation, as before
|
|
62
|
+
rc, out = _check(tmp_path, pkg, '[integrations]\nenabled = []\n', capsys)
|
|
63
|
+
assert rc == 0 and "No `[architecture]` contract found" in out # unrelated table: still absent
|
|
64
|
+
with pytest.raises(SystemExit, match="no \\[architecture\\] contract found"):
|
|
65
|
+
_check(tmp_path, pkg, None, capsys, "--require-contract") # still opt-in for absence (exit 1)
|
|
66
|
+
(tmp_path / "codemap.toml").unlink()
|
|
67
|
+
rc, out = _check(tmp_path, pkg, None, capsys)
|
|
68
|
+
assert rc == 0 and "No `[architecture]` contract found" in out # no file at all
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|