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.
Files changed (71) hide show
  1. clean_docs/__init__.py +26 -0
  2. clean_docs/__main__.py +3 -0
  3. clean_docs/accessibility.py +182 -0
  4. clean_docs/adapters/__init__.py +1 -0
  5. clean_docs/adapters/event_capture.py +56 -0
  6. clean_docs/adapters/mdx_dependencies.json +714 -0
  7. clean_docs/adapters/mdx_parser.mjs +29992 -0
  8. clean_docs/applicability.py +330 -0
  9. clean_docs/audit.py +1120 -0
  10. clean_docs/bootstrap.py +507 -0
  11. clean_docs/capabilities.py +200 -0
  12. clean_docs/changed.py +452 -0
  13. clean_docs/claims.py +840 -0
  14. clean_docs/cli.py +1612 -0
  15. clean_docs/context.py +307 -0
  16. clean_docs/corpus.py +377 -0
  17. clean_docs/demo.py +369 -0
  18. clean_docs/doctor.py +184 -0
  19. clean_docs/emit/__init__.py +4 -0
  20. clean_docs/emit/llms_txt.py +102 -0
  21. clean_docs/emit/stepwise.py +168 -0
  22. clean_docs/engine.py +324 -0
  23. clean_docs/errors.py +20 -0
  24. clean_docs/evaluation.py +867 -0
  25. clean_docs/execution.py +138 -0
  26. clean_docs/explain.py +123 -0
  27. clean_docs/extractors/__init__.py +19 -0
  28. clean_docs/extractors/command.py +51 -0
  29. clean_docs/extractors/inventory.py +176 -0
  30. clean_docs/extractors/json_pointer.py +84 -0
  31. clean_docs/extractors/python_literal.py +104 -0
  32. clean_docs/extractors/static.py +111 -0
  33. clean_docs/feedback.py +1390 -0
  34. clean_docs/impact.py +1624 -0
  35. clean_docs/improvements.py +1178 -0
  36. clean_docs/inventory.py +474 -0
  37. clean_docs/isolation.py +157 -0
  38. clean_docs/manifest.py +898 -0
  39. clean_docs/mdx.py +272 -0
  40. clean_docs/migration.py +121 -0
  41. clean_docs/models.py +194 -0
  42. clean_docs/outcomes.py +296 -0
  43. clean_docs/performance.py +123 -0
  44. clean_docs/phrasing.py +448 -0
  45. clean_docs/plugins.py +249 -0
  46. clean_docs/policy.py +536 -0
  47. clean_docs/projections.py +255 -0
  48. clean_docs/regions.py +75 -0
  49. clean_docs/release.py +232 -0
  50. clean_docs/renderers.py +57 -0
  51. clean_docs/residue.py +311 -0
  52. clean_docs/review_contracts.py +862 -0
  53. clean_docs/review_ledger.py +297 -0
  54. clean_docs/review_limits.py +9 -0
  55. clean_docs/sensitivity.py +602 -0
  56. clean_docs/snapshot.py +212 -0
  57. clean_docs/standard.py +281 -0
  58. clean_docs/standards/default.json +309 -0
  59. clean_docs/standards/exemplars.md +87 -0
  60. clean_docs/standards/v0-migrations.json +26 -0
  61. clean_docs/symbols.py +47 -0
  62. clean_docs/templates.py +96 -0
  63. clean_docs/verdict.py +1397 -0
  64. clean_docs/visuals.py +346 -0
  65. clean_docs/write_gate.py +170 -0
  66. sourcebound-1.2.1.dist-info/LICENSE +21 -0
  67. sourcebound-1.2.1.dist-info/METADATA +109 -0
  68. sourcebound-1.2.1.dist-info/RECORD +71 -0
  69. sourcebound-1.2.1.dist-info/WHEEL +5 -0
  70. sourcebound-1.2.1.dist-info/entry_points.txt +2 -0
  71. 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
+ )