sourcebound 1.2.1__py3-none-any.whl
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.
- clean_docs/__init__.py +26 -0
- clean_docs/__main__.py +3 -0
- clean_docs/accessibility.py +182 -0
- clean_docs/adapters/__init__.py +1 -0
- clean_docs/adapters/event_capture.py +56 -0
- clean_docs/adapters/mdx_dependencies.json +714 -0
- clean_docs/adapters/mdx_parser.mjs +29992 -0
- clean_docs/applicability.py +330 -0
- clean_docs/audit.py +1120 -0
- clean_docs/bootstrap.py +507 -0
- clean_docs/capabilities.py +200 -0
- clean_docs/changed.py +452 -0
- clean_docs/claims.py +840 -0
- clean_docs/cli.py +1612 -0
- clean_docs/context.py +307 -0
- clean_docs/corpus.py +377 -0
- clean_docs/demo.py +369 -0
- clean_docs/doctor.py +184 -0
- clean_docs/emit/__init__.py +4 -0
- clean_docs/emit/llms_txt.py +102 -0
- clean_docs/emit/stepwise.py +168 -0
- clean_docs/engine.py +324 -0
- clean_docs/errors.py +20 -0
- clean_docs/evaluation.py +867 -0
- clean_docs/execution.py +138 -0
- clean_docs/explain.py +123 -0
- clean_docs/extractors/__init__.py +19 -0
- clean_docs/extractors/command.py +51 -0
- clean_docs/extractors/inventory.py +176 -0
- clean_docs/extractors/json_pointer.py +84 -0
- clean_docs/extractors/python_literal.py +104 -0
- clean_docs/extractors/static.py +111 -0
- clean_docs/feedback.py +1390 -0
- clean_docs/impact.py +1624 -0
- clean_docs/improvements.py +1178 -0
- clean_docs/inventory.py +474 -0
- clean_docs/isolation.py +157 -0
- clean_docs/manifest.py +898 -0
- clean_docs/mdx.py +272 -0
- clean_docs/migration.py +121 -0
- clean_docs/models.py +194 -0
- clean_docs/outcomes.py +296 -0
- clean_docs/performance.py +123 -0
- clean_docs/phrasing.py +448 -0
- clean_docs/plugins.py +249 -0
- clean_docs/policy.py +536 -0
- clean_docs/projections.py +255 -0
- clean_docs/regions.py +75 -0
- clean_docs/release.py +232 -0
- clean_docs/renderers.py +57 -0
- clean_docs/residue.py +311 -0
- clean_docs/review_contracts.py +862 -0
- clean_docs/review_ledger.py +297 -0
- clean_docs/review_limits.py +9 -0
- clean_docs/sensitivity.py +602 -0
- clean_docs/snapshot.py +212 -0
- clean_docs/standard.py +281 -0
- clean_docs/standards/default.json +309 -0
- clean_docs/standards/exemplars.md +87 -0
- clean_docs/standards/v0-migrations.json +26 -0
- clean_docs/symbols.py +47 -0
- clean_docs/templates.py +96 -0
- clean_docs/verdict.py +1397 -0
- clean_docs/visuals.py +346 -0
- clean_docs/write_gate.py +170 -0
- sourcebound-1.2.1.dist-info/LICENSE +21 -0
- sourcebound-1.2.1.dist-info/METADATA +109 -0
- sourcebound-1.2.1.dist-info/RECORD +71 -0
- sourcebound-1.2.1.dist-info/WHEEL +5 -0
- sourcebound-1.2.1.dist-info/entry_points.txt +2 -0
- sourcebound-1.2.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import hashlib
|
|
4
|
+
import json
|
|
5
|
+
import sys
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
import yaml
|
|
9
|
+
|
|
10
|
+
if sys.version_info >= (3, 11):
|
|
11
|
+
import tomllib
|
|
12
|
+
else:
|
|
13
|
+
import tomli as tomllib
|
|
14
|
+
|
|
15
|
+
from clean_docs.errors import ExtractionError
|
|
16
|
+
from clean_docs.models import EvidenceValue, Provenance, RegionBinding
|
|
17
|
+
from clean_docs.snapshot import RepositorySnapshot
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _digest(value: Any) -> str:
|
|
21
|
+
normalized = json.dumps(value, sort_keys=True, separators=(",", ":"), ensure_ascii=False)
|
|
22
|
+
return hashlib.sha256(normalized.encode()).hexdigest()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _decode(token: str) -> str:
|
|
26
|
+
return token.replace("~1", "/").replace("~0", "~")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _resolve(value: Any, pointer: str | None) -> Any:
|
|
30
|
+
if pointer is None:
|
|
31
|
+
return value
|
|
32
|
+
current = value
|
|
33
|
+
for raw_token in pointer.removeprefix("/").split("/"):
|
|
34
|
+
token = _decode(raw_token)
|
|
35
|
+
if isinstance(current, dict) and token in current:
|
|
36
|
+
current = current[token]
|
|
37
|
+
elif isinstance(current, list) and token.isdigit() and int(token) < len(current):
|
|
38
|
+
current = current[int(token)]
|
|
39
|
+
else:
|
|
40
|
+
raise ExtractionError(f"structured-data pointer does not resolve: {pointer}")
|
|
41
|
+
return current
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def extract_file(snapshot: RepositorySnapshot, binding: RegionBinding) -> EvidenceValue:
|
|
45
|
+
text = snapshot.read_text(binding.source.path)
|
|
46
|
+
return EvidenceValue(
|
|
47
|
+
kind="text",
|
|
48
|
+
value=text,
|
|
49
|
+
provenance=Provenance(
|
|
50
|
+
snapshot.label,
|
|
51
|
+
binding.source.path.as_posix(),
|
|
52
|
+
binding.source.path.as_posix(),
|
|
53
|
+
"file@1",
|
|
54
|
+
hashlib.sha256(text.encode()).hexdigest(),
|
|
55
|
+
),
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def extract_paths(snapshot: RepositorySnapshot, binding: RegionBinding) -> EvidenceValue:
|
|
60
|
+
if binding.source.glob is None:
|
|
61
|
+
raise ExtractionError("path extractor requires a glob")
|
|
62
|
+
paths = [path.as_posix() for path in snapshot.matching_files(binding.source.glob)]
|
|
63
|
+
if not paths:
|
|
64
|
+
raise ExtractionError(
|
|
65
|
+
f"binding {binding.id} path glob matched zero files: "
|
|
66
|
+
f"{binding.source.glob}"
|
|
67
|
+
)
|
|
68
|
+
return EvidenceValue(
|
|
69
|
+
kind="list",
|
|
70
|
+
value=paths,
|
|
71
|
+
provenance=Provenance(
|
|
72
|
+
snapshot.label,
|
|
73
|
+
"<paths>",
|
|
74
|
+
binding.source.glob,
|
|
75
|
+
"path@1",
|
|
76
|
+
_digest(paths),
|
|
77
|
+
),
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def extract_structured(snapshot: RepositorySnapshot, binding: RegionBinding) -> EvidenceValue:
|
|
82
|
+
text = snapshot.read_text(binding.source.path)
|
|
83
|
+
suffix = binding.source.path.suffix.lower()
|
|
84
|
+
try:
|
|
85
|
+
if suffix == ".json":
|
|
86
|
+
value = json.loads(text)
|
|
87
|
+
elif suffix in {".yaml", ".yml"}:
|
|
88
|
+
value = yaml.safe_load(text)
|
|
89
|
+
elif suffix == ".toml":
|
|
90
|
+
value = tomllib.loads(text)
|
|
91
|
+
else:
|
|
92
|
+
raise ExtractionError(f"unsupported structured-data format: {suffix or '<none>'}")
|
|
93
|
+
except (json.JSONDecodeError, yaml.YAMLError, tomllib.TOMLDecodeError) as exc:
|
|
94
|
+
raise ExtractionError(f"cannot parse {binding.source.path}: {exc}") from exc
|
|
95
|
+
selected = _resolve(value, binding.source.pointer)
|
|
96
|
+
kind = "table" if isinstance(selected, list) and all(
|
|
97
|
+
isinstance(item, dict) for item in selected
|
|
98
|
+
) else "list" if isinstance(selected, list) else "scalar" if not isinstance(
|
|
99
|
+
selected, dict
|
|
100
|
+
) else "mapping"
|
|
101
|
+
return EvidenceValue(
|
|
102
|
+
kind=kind,
|
|
103
|
+
value=selected,
|
|
104
|
+
provenance=Provenance(
|
|
105
|
+
snapshot.label,
|
|
106
|
+
binding.source.path.as_posix(),
|
|
107
|
+
binding.source.pointer or "/",
|
|
108
|
+
"structured-data@1",
|
|
109
|
+
_digest(selected),
|
|
110
|
+
),
|
|
111
|
+
)
|