SciAPI 0.0.0__tar.gz → 0.0.1__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 (167) hide show
  1. sciapi-0.0.1/.gitignore +4 -0
  2. sciapi-0.0.1/PKG-INFO +14 -0
  3. sciapi-0.0.1/pyproject.toml +35 -0
  4. sciapi-0.0.1/sciapi/__init__.py +86 -0
  5. sciapi-0.0.1/sciapi/__main__.py +5 -0
  6. sciapi-0.0.1/sciapi/_compiler_locations.py +51 -0
  7. sciapi-0.0.1/sciapi/_declarations/__init__.py +1 -0
  8. sciapi-0.0.1/sciapi/_declarations/_reference_rows.py +95 -0
  9. sciapi-0.0.1/sciapi/_declarations/native/__init__.py +3 -0
  10. sciapi-0.0.1/sciapi/_declarations/native/_formats.py +23 -0
  11. sciapi-0.0.1/sciapi/_declarations/native/_public_bindings.py +123 -0
  12. sciapi-0.0.1/sciapi/_declarations/native/_public_signatures.py +43 -0
  13. sciapi-0.0.1/sciapi/_declarations/native/_reference_rows.py +234 -0
  14. sciapi-0.0.1/sciapi/_declarations/native/_rustdoc.py +779 -0
  15. sciapi-0.0.1/sciapi/_declarations/python/__init__.py +1 -0
  16. sciapi-0.0.1/sciapi/_declarations/python/_bases.py +167 -0
  17. sciapi-0.0.1/sciapi/_declarations/python/_bindings.py +359 -0
  18. sciapi-0.0.1/sciapi/_declarations/python/_classes.py +247 -0
  19. sciapi-0.0.1/sciapi/_declarations/python/_dataclasses.py +741 -0
  20. sciapi-0.0.1/sciapi/_declarations/python/_display.py +533 -0
  21. sciapi-0.0.1/sciapi/_declarations/python/_docstrings.py +501 -0
  22. sciapi-0.0.1/sciapi/_declarations/python/_expressions.py +282 -0
  23. sciapi-0.0.1/sciapi/_declarations/python/_facts.py +387 -0
  24. sciapi-0.0.1/sciapi/_declarations/python/_inheritance.py +91 -0
  25. sciapi-0.0.1/sciapi/_declarations/python/_models.py +959 -0
  26. sciapi-0.0.1/sciapi/_declarations/python/_public_bindings.py +352 -0
  27. sciapi-0.0.1/sciapi/_declarations/python/_runtime_facts.py +82 -0
  28. sciapi-0.0.1/sciapi/_declarations/python/_signatures.py +361 -0
  29. sciapi-0.0.1/sciapi/_declarations/python/_source_consistency.py +145 -0
  30. sciapi-0.0.1/sciapi/_declarations/python/_type_aliases.py +327 -0
  31. sciapi-0.0.1/sciapi/_declarations/python/_types.py +27 -0
  32. sciapi-0.0.1/sciapi/_declarations/python/_values.py +125 -0
  33. sciapi-0.0.1/sciapi/_diagnostics.py +135 -0
  34. sciapi-0.0.1/sciapi/_document_validation.py +171 -0
  35. sciapi-0.0.1/sciapi/_file_integrity.py +97 -0
  36. sciapi-0.0.1/sciapi/_immutable_config.py +166 -0
  37. sciapi-0.0.1/sciapi/_json_encoding.py +15 -0
  38. sciapi-0.0.1/sciapi/_memoization.py +58 -0
  39. sciapi-0.0.1/sciapi/_namespaces.py +40 -0
  40. sciapi-0.0.1/sciapi/_python_sources.py +70 -0
  41. sciapi-0.0.1/sciapi/_runtime_execution.py +177 -0
  42. sciapi-0.0.1/sciapi/_version.py +3 -0
  43. sciapi-0.0.1/sciapi/cli.py +631 -0
  44. sciapi-0.0.1/sciapi/comparison/__init__.py +1 -0
  45. sciapi-0.0.1/sciapi/comparison/_check.py +490 -0
  46. sciapi-0.0.1/sciapi/comparison/_conformance.py +127 -0
  47. sciapi-0.0.1/sciapi/comparison/_installed_bindings.py +773 -0
  48. sciapi-0.0.1/sciapi/comparison/_receipt_documents.py +169 -0
  49. sciapi-0.0.1/sciapi/comparison/cross_language/__init__.py +41 -0
  50. sciapi-0.0.1/sciapi/comparison/cross_language/_annotation_documents.py +869 -0
  51. sciapi-0.0.1/sciapi/comparison/cross_language/_behavioral_facts.py +105 -0
  52. sciapi-0.0.1/sciapi/comparison/cross_language/_evidence_documents.py +952 -0
  53. sciapi-0.0.1/sciapi/comparison/cross_language/_evidence_values.py +11 -0
  54. sciapi-0.0.1/sciapi/comparison/cross_language/_report_aggregation.py +180 -0
  55. sciapi-0.0.1/sciapi/comparison/cross_language/_report_documents.py +832 -0
  56. sciapi-0.0.1/sciapi/comparison/cross_language/_values.py +212 -0
  57. sciapi-0.0.1/sciapi/comparison/cross_language/compare.py +73 -0
  58. sciapi-0.0.1/sciapi/comparison/cross_language/config.py +230 -0
  59. sciapi-0.0.1/sciapi/comparison/cross_language/error_projections.py +378 -0
  60. sciapi-0.0.1/sciapi/comparison/cross_language/evidence.py +296 -0
  61. sciapi-0.0.1/sciapi/comparison/cross_language/evidence_validation.py +609 -0
  62. sciapi-0.0.1/sciapi/comparison/cross_language/logical_types.py +373 -0
  63. sciapi-0.0.1/sciapi/comparison/cross_language/native.py +3730 -0
  64. sciapi-0.0.1/sciapi/comparison/cross_language/nominal.py +550 -0
  65. sciapi-0.0.1/sciapi/comparison/cross_language/policies.py +681 -0
  66. sciapi-0.0.1/sciapi/comparison/cross_language/python.py +3261 -0
  67. sciapi-0.0.1/sciapi/comparison/cross_language/report.py +226 -0
  68. sciapi-0.0.1/sciapi/comparison/cross_language/representations.py +326 -0
  69. sciapi-0.0.1/sciapi/comparison/cross_language/requirements.py +293 -0
  70. sciapi-0.0.1/sciapi/comparison/cross_language/results.py +114 -0
  71. sciapi-0.0.1/sciapi/comparison/cross_language/semantics.py +186 -0
  72. sciapi-0.0.1/sciapi/comparison/exports.py +111 -0
  73. sciapi-0.0.1/sciapi/comparison/history/__init__.py +28 -0
  74. sciapi-0.0.1/sciapi/comparison/history/_capture_compatibility.py +531 -0
  75. sciapi-0.0.1/sciapi/comparison/history/_compare.py +1451 -0
  76. sciapi-0.0.1/sciapi/comparison/history/_fact_values.py +26 -0
  77. sciapi-0.0.1/sciapi/comparison/history/_policy_document.py +100 -0
  78. sciapi-0.0.1/sciapi/comparison/history/_snapshot_facts.py +785 -0
  79. sciapi-0.0.1/sciapi/comparison/history/_versions.py +193 -0
  80. sciapi-0.0.1/sciapi/comparison/history/policies.py +293 -0
  81. sciapi-0.0.1/sciapi/comparison/history/results.py +337 -0
  82. sciapi-0.0.1/sciapi/comparison/installed_python.py +45 -0
  83. sciapi-0.0.1/sciapi/comparison/python.py +288 -0
  84. sciapi-0.0.1/sciapi/comparison/receipts.py +237 -0
  85. sciapi-0.0.1/sciapi/comparison/results.py +62 -0
  86. sciapi-0.0.1/sciapi/config/__init__.py +119 -0
  87. sciapi-0.0.1/sciapi/config/_diagnostics.py +66 -0
  88. sciapi-0.0.1/sciapi/config/_generation.py +323 -0
  89. sciapi-0.0.1/sciapi/config/_operations.py +233 -0
  90. sciapi-0.0.1/sciapi/config/_plans.py +279 -0
  91. sciapi-0.0.1/sciapi/config/_project.py +821 -0
  92. sciapi-0.0.1/sciapi/config/_reference.py +390 -0
  93. sciapi-0.0.1/sciapi/config/_source_policies.py +457 -0
  94. sciapi-0.0.1/sciapi/config/_sources.py +572 -0
  95. sciapi-0.0.1/sciapi/config/_values.py +294 -0
  96. sciapi-0.0.1/sciapi/extraction/__init__.py +3 -0
  97. sciapi-0.0.1/sciapi/extraction/_clang_supplement.py +451 -0
  98. sciapi-0.0.1/sciapi/extraction/_extract.py +300 -0
  99. sciapi-0.0.1/sciapi/extraction/clang.py +725 -0
  100. sciapi-0.0.1/sciapi/extraction/observations.py +46 -0
  101. sciapi-0.0.1/sciapi/extraction/python/__init__.py +46 -0
  102. sciapi-0.0.1/sciapi/extraction/python/_encoding.py +982 -0
  103. sciapi-0.0.1/sciapi/extraction/python/_runtime_protocol.py +1186 -0
  104. sciapi-0.0.1/sciapi/extraction/python/_runtime_worker.py +1440 -0
  105. sciapi-0.0.1/sciapi/extraction/python/_source.py +1282 -0
  106. sciapi-0.0.1/sciapi/extraction/python/_visit.py +354 -0
  107. sciapi-0.0.1/sciapi/extraction/python/runtime.py +545 -0
  108. sciapi-0.0.1/sciapi/extraction/rustdoc.py +677 -0
  109. sciapi-0.0.1/sciapi/python_generation/__init__.py +9 -0
  110. sciapi-0.0.1/sciapi/python_generation/_generate.py +95 -0
  111. sciapi-0.0.1/sciapi/python_generation/_imports.py +261 -0
  112. sciapi-0.0.1/sciapi/python_generation/_manifest.py +135 -0
  113. sciapi-0.0.1/sciapi/python_generation/_members.py +73 -0
  114. sciapi-0.0.1/sciapi/python_generation/_plan.py +855 -0
  115. sciapi-0.0.1/sciapi/python_generation/_reference_inputs.py +46 -0
  116. sciapi-0.0.1/sciapi/python_generation/_reused_sources.py +112 -0
  117. sciapi-0.0.1/sciapi/python_generation/_source_syntax.py +308 -0
  118. sciapi-0.0.1/sciapi/python_generation/_target.py +64 -0
  119. sciapi-0.0.1/sciapi/python_generation/native_stubs.py +398 -0
  120. sciapi-0.0.1/sciapi/python_generation/package.py +799 -0
  121. sciapi-0.0.1/sciapi/python_generation/results.py +202 -0
  122. sciapi-0.0.1/sciapi/python_generation/runtime_modules.py +1104 -0
  123. sciapi-0.0.1/sciapi/python_generation/stubs.py +749 -0
  124. sciapi-0.0.1/sciapi/references/__init__.py +9 -0
  125. sciapi-0.0.1/sciapi/references/_documentation_ownership.py +295 -0
  126. sciapi-0.0.1/sciapi/references/_documents.py +470 -0
  127. sciapi-0.0.1/sciapi/references/_files.py +310 -0
  128. sciapi-0.0.1/sciapi/references/_native_prose.py +728 -0
  129. sciapi-0.0.1/sciapi/references/_pages.py +1542 -0
  130. sciapi-0.0.1/sciapi/references/_python_declarations.py +874 -0
  131. sciapi-0.0.1/sciapi/references/_reference.py +64 -0
  132. sciapi-0.0.1/sciapi/references/_render.py +617 -0
  133. sciapi-0.0.1/sciapi/references/_validation.py +94 -0
  134. sciapi-0.0.1/sciapi/references/reader.py +44 -0
  135. sciapi-0.0.1/sciapi/references/results.py +46 -0
  136. sciapi-0.0.1/sciapi/resources/schemas/griffe-LICENSE.txt +15 -0
  137. sciapi-0.0.1/sciapi/resources/schemas/python-public.schema.json +1143 -0
  138. sciapi-0.0.1/sciapi/resources/static/sciapi.css +29 -0
  139. sciapi-0.0.1/sciapi/resources/templates/reference/page.md.jinja +33 -0
  140. sciapi-0.0.1/sciapi/snapshots/__init__.py +6 -0
  141. sciapi-0.0.1/sciapi/snapshots/_freshness.py +145 -0
  142. sciapi-0.0.1/sciapi/snapshots/_manifest.py +233 -0
  143. sciapi-0.0.1/sciapi/snapshots/_pointers.py +93 -0
  144. sciapi-0.0.1/sciapi/snapshots/_readers.py +65 -0
  145. sciapi-0.0.1/sciapi/snapshots/_writer.py +177 -0
  146. sciapi-0.0.1/sciapi/snapshots/bundles.py +319 -0
  147. sciapi-0.0.1/sciapi/sphinxext/__init__.py +92 -0
  148. sciapi-0.0.1/sciapi/sphinxext/_annotations.py +274 -0
  149. sciapi-0.0.1/sciapi/sphinxext/_directives.py +623 -0
  150. sciapi-0.0.1/sciapi/sphinxext/_lifecycle.py +233 -0
  151. sciapi-0.0.1/sciapi/sphinxext/_options.py +103 -0
  152. sciapi-0.0.1/sciapi/sphinxext/_staging.py +80 -0
  153. sciapi-0.0.1/sciapi/workflows/__init__.py +7 -0
  154. sciapi-0.0.1/sciapi/workflows/_cache.py +49 -0
  155. sciapi-0.0.1/sciapi/workflows/_execution.py +146 -0
  156. sciapi-0.0.1/sciapi/workflows/_request.py +130 -0
  157. sciapi-0.0.1/sciapi/workflows/results.py +156 -0
  158. sciapi-0.0.1/sciapi/workflows/session.py +779 -0
  159. sciapi-0.0.0/PKG-INFO +0 -4
  160. sciapi-0.0.0/pyproject.toml +0 -22
  161. sciapi-0.0.0/setup.cfg +0 -4
  162. sciapi-0.0.0/src/SciAPI.egg-info/PKG-INFO +0 -4
  163. sciapi-0.0.0/src/SciAPI.egg-info/SOURCES.txt +0 -7
  164. sciapi-0.0.0/src/SciAPI.egg-info/dependency_links.txt +0 -1
  165. sciapi-0.0.0/src/SciAPI.egg-info/not-zip-safe +0 -1
  166. sciapi-0.0.0/src/SciAPI.egg-info/top_level.txt +0 -1
  167. /sciapi-0.0.0/src/sciapi/__init__.py → /sciapi-0.0.1/sciapi/py.typed +0 -0
@@ -0,0 +1,4 @@
1
+ # The ignore rules of the package folder. hatchling puts the nearest
2
+ # .gitignore into the sdist, so this one stands in for the repository's.
3
+ __pycache__/
4
+ *.py[cod]
sciapi-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,14 @@
1
+ Metadata-Version: 2.5
2
+ Name: sciapi
3
+ Version: 0.0.1
4
+ Summary: Extract, check, generate, and document Python and native library interfaces.
5
+ Requires-Python: >=3.12
6
+ Requires-Dist: griffe==2.4.1
7
+ Requires-Dist: jinja2>=3.1
8
+ Requires-Dist: jsonschema>=4.26
9
+ Requires-Dist: markdown-it-py>=4
10
+ Requires-Dist: pydantic>=2.14
11
+ Requires-Dist: typing-extensions>=4.16
12
+ Provides-Extra: sphinx
13
+ Requires-Dist: myst-parser>=5; extra == 'sphinx'
14
+ Requires-Dist: sphinx>=8.2; extra == 'sphinx'
@@ -0,0 +1,35 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.27"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "sciapi"
7
+ dynamic = ["version"]
8
+ description = "Extract, check, generate, and document Python and native library interfaces."
9
+ requires-python = ">=3.12"
10
+ dependencies = [
11
+ # Exact, since the shipped schema python-public.schema.json is derived from
12
+ # the serialization of this version.
13
+ "griffe==2.4.1",
14
+ "jinja2>=3.1",
15
+ "jsonschema>=4.26",
16
+ "markdown-it-py>=4",
17
+ "pydantic>=2.14",
18
+ "typing-extensions>=4.16",
19
+ ]
20
+
21
+ [project.optional-dependencies]
22
+ # The Sphinx extension `sciapi.sphinxext`, which renders references in MyST.
23
+ sphinx = ["myst-parser>=5", "sphinx>=8.2"]
24
+
25
+ [project.scripts]
26
+ sciapi = "sciapi.cli:main"
27
+
28
+ [tool.hatch.version]
29
+ path = "sciapi/_version.py"
30
+
31
+ [tool.hatch.build.targets.wheel]
32
+ packages = ["sciapi"]
33
+
34
+ [tool.hatch.build.targets.sdist]
35
+ include = ["/sciapi"]
@@ -0,0 +1,86 @@
1
+ """Extract, verify, generate and document independently observed interfaces."""
2
+
3
+ from sciapi._diagnostics import Finding
4
+ from sciapi._version import __version__ as __version__
5
+ from sciapi.comparison._check import check
6
+ from sciapi.comparison._conformance import conformance
7
+ from sciapi.comparison.cross_language.compare import compare_contracts
8
+ from sciapi.comparison.cross_language.config import ContractConfig
9
+ from sciapi.comparison.cross_language.evidence import CoverageEvidence
10
+ from sciapi.comparison.cross_language.evidence_validation import (
11
+ validate_behavioral_coverage,
12
+ )
13
+ from sciapi.comparison.cross_language.report import ContractReport
14
+ from sciapi.comparison.cross_language.requirements import (
15
+ RequirementSet,
16
+ behavioral_requirements,
17
+ )
18
+ from sciapi.comparison.cross_language.results import (
19
+ ConformanceResult,
20
+ CoverageResult,
21
+ )
22
+ from sciapi.comparison.history import (
23
+ Change,
24
+ ChangePolicy,
25
+ ChangeReport,
26
+ VersionDecision,
27
+ VersionPolicy,
28
+ compare_snapshots,
29
+ evaluate_version,
30
+ )
31
+ from sciapi.comparison.receipts import read_check
32
+ from sciapi.comparison.results import CheckResult
33
+ from sciapi.config._project import Project
34
+ from sciapi.extraction._extract import extract
35
+ from sciapi.python_generation._generate import generate
36
+ from sciapi.python_generation.results import (
37
+ GeneratedFile,
38
+ GenerationDecision,
39
+ GenerationPlanSummary,
40
+ GenerationResult,
41
+ )
42
+ from sciapi.references._reference import reference
43
+ from sciapi.references.results import ReferenceResult
44
+ from sciapi.snapshots._readers import read_bundle
45
+ from sciapi.snapshots.bundles import Artifact, Bundle
46
+ from sciapi.workflows.results import WorkflowResult
47
+ from sciapi.workflows.session import PipelineSession, run
48
+
49
+ __all__ = [
50
+ "Artifact",
51
+ "Bundle",
52
+ "Change",
53
+ "ChangePolicy",
54
+ "ChangeReport",
55
+ "CheckResult",
56
+ "ConformanceResult",
57
+ "ContractConfig",
58
+ "ContractReport",
59
+ "CoverageEvidence",
60
+ "CoverageResult",
61
+ "Finding",
62
+ "GeneratedFile",
63
+ "GenerationDecision",
64
+ "GenerationPlanSummary",
65
+ "GenerationResult",
66
+ "PipelineSession",
67
+ "Project",
68
+ "ReferenceResult",
69
+ "RequirementSet",
70
+ "VersionDecision",
71
+ "VersionPolicy",
72
+ "WorkflowResult",
73
+ "behavioral_requirements",
74
+ "check",
75
+ "compare_contracts",
76
+ "compare_snapshots",
77
+ "conformance",
78
+ "evaluate_version",
79
+ "extract",
80
+ "generate",
81
+ "read_bundle",
82
+ "read_check",
83
+ "reference",
84
+ "run",
85
+ "validate_behavioral_coverage",
86
+ ]
@@ -0,0 +1,5 @@
1
+ """Execute the public command-line interface."""
2
+
3
+ from sciapi.cli import main
4
+
5
+ raise SystemExit(main())
@@ -0,0 +1,51 @@
1
+ """Normalize compiler-location identities without consulting live sources."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import ntpath
6
+ import posixpath
7
+ from pathlib import PurePath, PurePosixPath, PureWindowsPath
8
+ from urllib.parse import unquote, urlparse
9
+
10
+ __all__: list[str] = []
11
+
12
+
13
+ def source_path(value: str) -> str:
14
+ """Decode a file URI, preserving remote hosts and Windows drive roots."""
15
+ parsed = urlparse(value)
16
+ if parsed.scheme != "file":
17
+ return value
18
+ path = unquote(parsed.path)
19
+ if parsed.netloc and parsed.netloc.casefold() != "localhost":
20
+ return "//" + parsed.netloc + path
21
+ if path.startswith("/") and PureWindowsPath(path[1:]).drive:
22
+ return path[1:]
23
+ return path
24
+
25
+
26
+ def logical_path(value: str) -> PurePath:
27
+ """Select the compiler path's own flavor and normalize it lexically."""
28
+ path = source_path(value)
29
+ if "\\" in path or PureWindowsPath(path).drive:
30
+ return PureWindowsPath(ntpath.normpath(path))
31
+ return PurePosixPath(posixpath.normpath(path))
32
+
33
+
34
+ def location_identity(value: str, root: PurePath | None = None) -> str:
35
+ """Normalize an identity with its compiler path's case rules."""
36
+ path = logical_path(value)
37
+ if root is not None and not path.is_absolute():
38
+ path = logical_path((root / path.as_posix()).as_posix())
39
+ identity = path.as_posix()
40
+ if isinstance(path, PureWindowsPath):
41
+ return identity.casefold()
42
+ return identity
43
+
44
+
45
+ def resolve_compiler_root(value: str | PurePath, base: PurePath) -> str:
46
+ """Preserve foreign absolute roots and resolve relative roots lexically."""
47
+ path = logical_path(str(value))
48
+ if path.is_absolute():
49
+ return str(value)
50
+ parent = logical_path(str(base))
51
+ return logical_path((parent / path.as_posix()).as_posix()).as_posix()
@@ -0,0 +1 @@
1
+ """Private helpers for captured interface declarations."""
@@ -0,0 +1,95 @@
1
+ """Stable rows and path targets shared by saved declaration consumers."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import re
7
+ from typing import Any
8
+
9
+ Row = dict[str, Any]
10
+
11
+ _CONTAINERS = {
12
+ "module",
13
+ "class",
14
+ "exception",
15
+ "struct",
16
+ "enum",
17
+ "trait",
18
+ "union",
19
+ "c.struct",
20
+ "c.enum",
21
+ "c.union",
22
+ }
23
+
24
+
25
+ def _kind(row: Row) -> str:
26
+ return str(row.get("kind", "")).replace(" ", "_")
27
+
28
+
29
+ _READABLE_PATH = re.compile(r"[A-Za-z_]\w*(?:(?:\.|::)[A-Za-z_]\w*)+", re.ASCII)
30
+
31
+
32
+ def public_anchor(path: str) -> str:
33
+ """Return the stable target shared by raw and expanded public bindings.
34
+
35
+ A path of two or more identifiers joined by dots or ``::`` is its own
36
+ anchor, as in Sphinx's Python domain. Its separator keeps it distinct from
37
+ heading and other generated identifiers, which never contain one. Any other
38
+ path, including a single name, becomes a lowercase slug with a digest
39
+ suffix; its hyphens keep it distinct from every readable anchor.
40
+ """
41
+ if _READABLE_PATH.fullmatch(path):
42
+ return path
43
+ slug = re.sub(r"[^a-zA-Z0-9]+", "-", path).strip("-").lower()[:80]
44
+ return f"api-{slug}-{hashlib.sha256(path.encode()).hexdigest()[:10]}"
45
+
46
+
47
+ def _parent(path: str, separator: str, paths: dict[str, Row]) -> str:
48
+ while separator in path:
49
+ path = path.rsplit(separator, 1)[0]
50
+ if path in paths and _kind(paths[path]) in _CONTAINERS:
51
+ return path
52
+ return ""
53
+
54
+
55
+ def _metadata(value: dict[str, Any]) -> dict[str, Any]:
56
+ meta = value.get("x-api-tools", {})
57
+ return meta if isinstance(meta, dict) else {}
58
+
59
+
60
+ def _base_row(path: str, kind: str, *, level: int = 2) -> dict[str, Any]:
61
+ return {
62
+ "path": path,
63
+ "kind": kind,
64
+ "anchor": public_anchor(path),
65
+ "level": min(level, 6),
66
+ "alias": False,
67
+ "canonical_path": path,
68
+ "canonical_anchor": public_anchor(path),
69
+ "signature": "",
70
+ "annotation": "",
71
+ "value": "",
72
+ "required": None,
73
+ "readonly": False,
74
+ "sections": [],
75
+ "doc": "",
76
+ "abi": "",
77
+ "object_kind": kind,
78
+ "references": [],
79
+ "module": "",
80
+ "class_name": "",
81
+ "owner": "",
82
+ "bases": [],
83
+ "labels": [],
84
+ "declaration_kind": "",
85
+ "named_tuple_fields": [],
86
+ "type_parameters": [],
87
+ "parameter_specs": [],
88
+ "model_fields": [],
89
+ "limits": [],
90
+ "full_value": "",
91
+ "declaration_name": "",
92
+ "parameters": [],
93
+ "returns": "",
94
+ "constructor_in_class": False,
95
+ }
@@ -0,0 +1,3 @@
1
+ """Pure views of captured native declaration records."""
2
+
3
+ __all__: list[str] = []
@@ -0,0 +1,23 @@
1
+ """Identify the declaration language of a captured document format."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+
8
+ def declaration_language(format_name: str, document: dict[str, Any]) -> str:
9
+ if (
10
+ "griffe" in format_name
11
+ or format_name == "python"
12
+ or document.get("kind") == "module"
13
+ ):
14
+ return "python"
15
+ if "rustdoc" in format_name:
16
+ return "rust"
17
+ if any(
18
+ value in format_name
19
+ for value in ("clang", "symbolgraph", "symbol-graph")
20
+ ):
21
+ return "c"
22
+ msg = f"Unsupported reference format: {format_name}"
23
+ raise ValueError(msg)
@@ -0,0 +1,123 @@
1
+ """Expand only compiler-proven native forwarding container bindings."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections import deque
6
+ from copy import deepcopy
7
+ from dataclasses import dataclass, field
8
+
9
+ from sciapi._declarations._reference_rows import (
10
+ _CONTAINERS,
11
+ Row,
12
+ _kind,
13
+ _parent,
14
+ public_anchor,
15
+ )
16
+
17
+
18
+ @dataclass
19
+ class _NativeBindings:
20
+ """Compiler rows plus the proven forwarding spellings expanded from them."""
21
+
22
+ originals: dict[str, Row]
23
+ expanded: dict[str, Row] = field(init=False)
24
+
25
+ def __post_init__(self) -> None:
26
+ self.expanded = dict(self.originals)
27
+
28
+ def definition(self, path: str) -> str:
29
+ seen: set[str] = set()
30
+ while path in self.originals and self.originals[path].get("alias"):
31
+ if path in seen:
32
+ msg = f"Cyclic reference alias: {path}"
33
+ raise ValueError(msg)
34
+ seen.add(path)
35
+ path = str(self.originals[path].get("canonical_path", ""))
36
+ return path
37
+
38
+ def identity(self, path: str) -> str:
39
+ return (
40
+ self.definition(path)
41
+ if path in self.originals
42
+ else str(self.expanded[path]["canonical_path"])
43
+ )
44
+
45
+ def recursive(self, path: str, target: str) -> bool:
46
+ while "::" in path:
47
+ path = path.rsplit("::", 1)[0]
48
+ if path in self.expanded and self.identity(path) == target:
49
+ return True
50
+ return False
51
+
52
+ def forward(self, path: str, child: str, item: Row) -> str | None:
53
+ target = self.identity(path)
54
+ spelling = path + child[len(target) :]
55
+ child_identity = self.definition(child)
56
+ if spelling in self.expanded:
57
+ if self.identity(spelling) != child_identity:
58
+ msg = f"Conflicting compiler-proven public binding: {spelling}"
59
+ raise ValueError(msg)
60
+ return None
61
+ copy = deepcopy(item)
62
+ copy.update(
63
+ path=spelling,
64
+ anchor=public_anchor(spelling),
65
+ alias=True,
66
+ canonical_path=child_identity,
67
+ expanded=True,
68
+ )
69
+ self.expanded[spelling] = copy
70
+ return spelling
71
+
72
+ def expand(self) -> None:
73
+ # Newly proven spellings can themselves forward container aliases.
74
+ pending = deque(sorted(self.originals))
75
+ while pending:
76
+ path = pending.popleft()
77
+ row = self.expanded[path]
78
+ target = self.identity(path)
79
+ source = self.originals.get(target)
80
+ if (
81
+ not row.get("alias")
82
+ or source is None
83
+ or _kind(source) not in _CONTAINERS
84
+ or self.recursive(path, target)
85
+ ):
86
+ continue
87
+ for child, item in self.originals.items():
88
+ if child.startswith(target + "::"):
89
+ spelling = self.forward(path, child, item)
90
+ if spelling is not None:
91
+ pending.append(spelling)
92
+
93
+ def rows(self) -> list[Row]:
94
+ result = []
95
+ for path, row in sorted(self.expanded.items()):
96
+ identity = self.identity(path)
97
+ item = deepcopy(self.originals.get(identity, row))
98
+ item.update(
99
+ path=path,
100
+ anchor=str(row["anchor"]),
101
+ definition_path=identity,
102
+ inventory_alias=bool(row.get("alias", False)),
103
+ inventory_kind=str(row.get("kind", "")),
104
+ expanded=bool(row.get("expanded", False)),
105
+ documentation_parent=_parent(path, "::", self.expanded),
106
+ documentation_inherited=False,
107
+ external=identity not in self.originals,
108
+ )
109
+ result.append(item)
110
+ effective = {str(row["path"]): row for row in result}
111
+ for row in result:
112
+ row["documentation_parent"] = _parent(
113
+ str(row["path"]), "::", effective
114
+ )
115
+ return result
116
+
117
+
118
+ def expand_native_bindings(rows: list[Row], language: str) -> list[Row]:
119
+ """Retain compiler identities and expand only proven container aliases."""
120
+ bindings = _NativeBindings({str(row["path"]): row for row in rows})
121
+ if language == "rust":
122
+ bindings.expand()
123
+ return bindings.rows()
@@ -0,0 +1,43 @@
1
+ """Project compiler-prepared declaration names to public native spellings."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+
7
+
8
+ def public_signature(
9
+ signature: str, declaration_name: str, public: str, kind: str
10
+ ) -> str:
11
+ """Change only the compiler-prepared declaration's known name token."""
12
+ old = declaration_name
13
+ new = public.rsplit("::", 1)[-1]
14
+ if old == new:
15
+ return signature
16
+ token = {
17
+ "function": "fn",
18
+ "method": "fn",
19
+ "module": "mod",
20
+ "struct": "struct",
21
+ "enum": "enum",
22
+ "trait": "trait",
23
+ "union": "union",
24
+ "type_alias": "type",
25
+ "trait_alias": "trait",
26
+ "assoc_type": "type",
27
+ "constant": "const",
28
+ "assoc_const": "const",
29
+ "static": "static",
30
+ "macro": r"macro(?:_rules!)?",
31
+ }.get(kind)
32
+ if token is None:
33
+ return signature
34
+ return re.sub(
35
+ r"(\b"
36
+ + token
37
+ + r"\s+)(?:r#)?"
38
+ + re.escape(old.removeprefix("r#"))
39
+ + r"(?=\W|$)",
40
+ lambda match: match[1] + new,
41
+ signature,
42
+ count=1,
43
+ )