codmap 0.0.14__tar.gz → 0.0.15__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.14 → codmap-0.0.15}/PKG-INFO +1 -1
- {codmap-0.0.14 → codmap-0.0.15}/codemap/serve/check.py +6 -0
- {codmap-0.0.14 → codmap-0.0.15}/codmap.egg-info/PKG-INFO +1 -1
- {codmap-0.0.14 → codmap-0.0.15}/pyproject.toml +1 -1
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c49_type_only_cycles.py +27 -0
- {codmap-0.0.14 → codmap-0.0.15}/LICENSE +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/README.md +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/__init__.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/apidiff.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/arch.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/cli.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/diagnostics.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/extract/__init__.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/extract/attrflow.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/extract/behavior.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/extract/dataflow.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/extract/dispatch.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/extract/griffe_extractor.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/extract/gsource.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/extract/roots.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/extract/union.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/freshness.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/incremental.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/integrations/__init__.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/integrations/base.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/integrations/cocoindex.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/integrations/gate.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/integrations/gitnexus.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/integrations/registry.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/integrations/transport.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/model.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/provenance.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/query.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/scope.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/serve/__init__.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/serve/_scip_pb2.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/serve/api_surface.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/serve/apidiff.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/serve/architecture.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/serve/audit.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/serve/ctags.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/serve/impact.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/serve/limits.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/serve/livingdocs.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/serve/mcp_server.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/serve/mermaid.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/serve/pack.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/serve/rag.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/serve/review.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/serve/scip.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/serve/semantic.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/serve/server.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/serve/session.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/serve/subsystems.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/serve/vault.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/store.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/tomlio.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codemap/watch.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codmap.egg-info/SOURCES.txt +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codmap.egg-info/dependency_links.txt +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codmap.egg-info/entry_points.txt +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codmap.egg-info/requires.txt +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/codmap.egg-info/top_level.txt +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/setup.cfg +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_epistemic.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_gitnexus_router.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_impact_depth.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_integrations.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_issue3_serve_freshness.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_livingdocs.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_m0_api_surface.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_m11_argcontract.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_m12_dataflow.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_m15_review.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_m16_architecture.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_m17_mcp.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_m18_freshness.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_m1_5_semantics.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_m1_query.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_m2_views.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_m32_watch.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_m3_serve.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_m4_behavior.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_m5_deep.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_m6_repo_scope.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_m7_dispatch.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_m9_family.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c13_callgraph_accuracy.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c13_grep_vs_graph.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c16_semantic.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c20_attribute_edges.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c21_flat_layout.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c22_source_visible_refs.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c23_hard_python.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c24_test_mapping.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c25_provenance.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c26_deep_union.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c27_config_honesty.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c28_limit_envelope.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c29_lazy_imports.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c2_ctags.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c30_local_import_calls.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c30f1_reexport_calls.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c30f2_check_scope.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c31_path_origin.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c32_report_json.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c33_query_signature.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c34_signature_kinds.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c35_contract_location.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c36_target_resolution.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c37_rule_mutation.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c38_tool_drift.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c3_arch_contract.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c3_dogfood.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c41_scope_membership.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c42_deep_tier_stability.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c43_incremental_splice.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c44_absent_answers.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c45_repeat_union.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c46_shadowed_definitions.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c47_incremental_resample.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c48_type_checking_imports.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c4_complexity.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c5_apidiff.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c6_pack.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c7_edge_vocab.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c8_deadcode.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_r1c9_incremental.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_scip_export.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_scope.py +0 -0
- {codmap-0.0.14 → codmap-0.0.15}/tests/test_subsystems.py +0 -0
|
@@ -104,6 +104,10 @@ def render_check(query, contract: ArchitectureContract, violations: list[Violati
|
|
|
104
104
|
"and this exits 0. Use `--require-contract` to make a missing contract a "
|
|
105
105
|
"failure, or `--root DIR` if the file lives elsewhere._\n")
|
|
106
106
|
if not violations:
|
|
107
|
+
# R1-C49-f1 (consumer, issue #18): every enforced rule must name itself here. A
|
|
108
|
+
# rule that ran and stayed silent is the R1-C30-f2 defect from the other side —
|
|
109
|
+
# there the reader concluded more than was checked, here less. `tests/
|
|
110
|
+
# test_r1c49_type_only_cycles.py` fails if a new rule is added and not listed.
|
|
107
111
|
rules = []
|
|
108
112
|
if contract.layers:
|
|
109
113
|
rules.append(f"layered ({len(contract.layers)})")
|
|
@@ -115,6 +119,8 @@ def render_check(query, contract: ArchitectureContract, violations: list[Violati
|
|
|
115
119
|
rules.append("no_cycles")
|
|
116
120
|
if contract.no_lazy_cycles:
|
|
117
121
|
rules.append("no_lazy_cycles")
|
|
122
|
+
if contract.no_type_only_cycles:
|
|
123
|
+
rules.append("no_type_only_cycles")
|
|
118
124
|
if contract.exhaustive:
|
|
119
125
|
rules.append("exhaustive")
|
|
120
126
|
return (f"# Architecture check — `{target}`\n\n"
|
|
@@ -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.15"
|
|
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
|
|
@@ -204,3 +204,30 @@ def test_the_reports_carry_both_kinds_and_say_zero(both, tmp_path):
|
|
|
204
204
|
quiet = Query(extract(str(_pkg(tmp_path, {"a": "from .b import x\n", "b": "x = 1\n"}))))
|
|
205
205
|
assert build_architecture(quiet)["type_only_cycles"] == []
|
|
206
206
|
assert "and 0 through an import under `if TYPE_CHECKING:`" in render_dependencies(quiet)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
# -- f1: a rule that ran must name itself ---------------------------------------------------
|
|
210
|
+
|
|
211
|
+
def test_every_enforced_rule_names_itself_in_the_passing_line(tmp_path):
|
|
212
|
+
"""Reported by the consumer the day they took 0.0.14: `no_type_only_cycles` was
|
|
213
|
+
enforced and absent from "Rules enforced", and a contract holding only that rule
|
|
214
|
+
printed "Rules enforced: ." — the R1-C30-f2 defect from the other side. The loop is
|
|
215
|
+
over the contract's own fields, so a rule added later without a line here fails."""
|
|
216
|
+
import dataclasses
|
|
217
|
+
quiet = Query(extract(str(_pkg(tmp_path, {"a": "from .b import x\n", "b": "x = 1\n"}))))
|
|
218
|
+
skip = {"error", "path"}
|
|
219
|
+
names = [f.name for f in dataclasses.fields(arch.ArchitectureContract) if f.name not in skip]
|
|
220
|
+
assert "no_type_only_cycles" in names
|
|
221
|
+
for name in names:
|
|
222
|
+
value = {"layers": ("core",), "independent": (("core", "data"),),
|
|
223
|
+
"forbidden": (("core", "data"),)}.get(name, True)
|
|
224
|
+
contract = arch.ArchitectureContract(**{name: value})
|
|
225
|
+
assert not contract.is_empty(), f"{name} alone must be a contract"
|
|
226
|
+
md = render_check(quiet, contract, arch.check_contract(quiet, contract))
|
|
227
|
+
assert "Contract satisfied" in md, f"{name} alone should pass on a two-module tree"
|
|
228
|
+
listed = md.split("Rules enforced:")[1].split(".\n")[0]
|
|
229
|
+
assert listed.strip(), f"{name} ran and the line named nothing"
|
|
230
|
+
stem = {"layers": "layered", "independent": "independent",
|
|
231
|
+
"forbidden": "forbidden"}.get(name, name)
|
|
232
|
+
assert stem in listed, f"{name} was enforced but is missing from {listed!r}"
|
|
233
|
+
|
|
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
|