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.
- sciapi-0.0.1/.gitignore +4 -0
- sciapi-0.0.1/PKG-INFO +14 -0
- sciapi-0.0.1/pyproject.toml +35 -0
- sciapi-0.0.1/sciapi/__init__.py +86 -0
- sciapi-0.0.1/sciapi/__main__.py +5 -0
- sciapi-0.0.1/sciapi/_compiler_locations.py +51 -0
- sciapi-0.0.1/sciapi/_declarations/__init__.py +1 -0
- sciapi-0.0.1/sciapi/_declarations/_reference_rows.py +95 -0
- sciapi-0.0.1/sciapi/_declarations/native/__init__.py +3 -0
- sciapi-0.0.1/sciapi/_declarations/native/_formats.py +23 -0
- sciapi-0.0.1/sciapi/_declarations/native/_public_bindings.py +123 -0
- sciapi-0.0.1/sciapi/_declarations/native/_public_signatures.py +43 -0
- sciapi-0.0.1/sciapi/_declarations/native/_reference_rows.py +234 -0
- sciapi-0.0.1/sciapi/_declarations/native/_rustdoc.py +779 -0
- sciapi-0.0.1/sciapi/_declarations/python/__init__.py +1 -0
- sciapi-0.0.1/sciapi/_declarations/python/_bases.py +167 -0
- sciapi-0.0.1/sciapi/_declarations/python/_bindings.py +359 -0
- sciapi-0.0.1/sciapi/_declarations/python/_classes.py +247 -0
- sciapi-0.0.1/sciapi/_declarations/python/_dataclasses.py +741 -0
- sciapi-0.0.1/sciapi/_declarations/python/_display.py +533 -0
- sciapi-0.0.1/sciapi/_declarations/python/_docstrings.py +501 -0
- sciapi-0.0.1/sciapi/_declarations/python/_expressions.py +282 -0
- sciapi-0.0.1/sciapi/_declarations/python/_facts.py +387 -0
- sciapi-0.0.1/sciapi/_declarations/python/_inheritance.py +91 -0
- sciapi-0.0.1/sciapi/_declarations/python/_models.py +959 -0
- sciapi-0.0.1/sciapi/_declarations/python/_public_bindings.py +352 -0
- sciapi-0.0.1/sciapi/_declarations/python/_runtime_facts.py +82 -0
- sciapi-0.0.1/sciapi/_declarations/python/_signatures.py +361 -0
- sciapi-0.0.1/sciapi/_declarations/python/_source_consistency.py +145 -0
- sciapi-0.0.1/sciapi/_declarations/python/_type_aliases.py +327 -0
- sciapi-0.0.1/sciapi/_declarations/python/_types.py +27 -0
- sciapi-0.0.1/sciapi/_declarations/python/_values.py +125 -0
- sciapi-0.0.1/sciapi/_diagnostics.py +135 -0
- sciapi-0.0.1/sciapi/_document_validation.py +171 -0
- sciapi-0.0.1/sciapi/_file_integrity.py +97 -0
- sciapi-0.0.1/sciapi/_immutable_config.py +166 -0
- sciapi-0.0.1/sciapi/_json_encoding.py +15 -0
- sciapi-0.0.1/sciapi/_memoization.py +58 -0
- sciapi-0.0.1/sciapi/_namespaces.py +40 -0
- sciapi-0.0.1/sciapi/_python_sources.py +70 -0
- sciapi-0.0.1/sciapi/_runtime_execution.py +177 -0
- sciapi-0.0.1/sciapi/_version.py +3 -0
- sciapi-0.0.1/sciapi/cli.py +631 -0
- sciapi-0.0.1/sciapi/comparison/__init__.py +1 -0
- sciapi-0.0.1/sciapi/comparison/_check.py +490 -0
- sciapi-0.0.1/sciapi/comparison/_conformance.py +127 -0
- sciapi-0.0.1/sciapi/comparison/_installed_bindings.py +773 -0
- sciapi-0.0.1/sciapi/comparison/_receipt_documents.py +169 -0
- sciapi-0.0.1/sciapi/comparison/cross_language/__init__.py +41 -0
- sciapi-0.0.1/sciapi/comparison/cross_language/_annotation_documents.py +869 -0
- sciapi-0.0.1/sciapi/comparison/cross_language/_behavioral_facts.py +105 -0
- sciapi-0.0.1/sciapi/comparison/cross_language/_evidence_documents.py +952 -0
- sciapi-0.0.1/sciapi/comparison/cross_language/_evidence_values.py +11 -0
- sciapi-0.0.1/sciapi/comparison/cross_language/_report_aggregation.py +180 -0
- sciapi-0.0.1/sciapi/comparison/cross_language/_report_documents.py +832 -0
- sciapi-0.0.1/sciapi/comparison/cross_language/_values.py +212 -0
- sciapi-0.0.1/sciapi/comparison/cross_language/compare.py +73 -0
- sciapi-0.0.1/sciapi/comparison/cross_language/config.py +230 -0
- sciapi-0.0.1/sciapi/comparison/cross_language/error_projections.py +378 -0
- sciapi-0.0.1/sciapi/comparison/cross_language/evidence.py +296 -0
- sciapi-0.0.1/sciapi/comparison/cross_language/evidence_validation.py +609 -0
- sciapi-0.0.1/sciapi/comparison/cross_language/logical_types.py +373 -0
- sciapi-0.0.1/sciapi/comparison/cross_language/native.py +3730 -0
- sciapi-0.0.1/sciapi/comparison/cross_language/nominal.py +550 -0
- sciapi-0.0.1/sciapi/comparison/cross_language/policies.py +681 -0
- sciapi-0.0.1/sciapi/comparison/cross_language/python.py +3261 -0
- sciapi-0.0.1/sciapi/comparison/cross_language/report.py +226 -0
- sciapi-0.0.1/sciapi/comparison/cross_language/representations.py +326 -0
- sciapi-0.0.1/sciapi/comparison/cross_language/requirements.py +293 -0
- sciapi-0.0.1/sciapi/comparison/cross_language/results.py +114 -0
- sciapi-0.0.1/sciapi/comparison/cross_language/semantics.py +186 -0
- sciapi-0.0.1/sciapi/comparison/exports.py +111 -0
- sciapi-0.0.1/sciapi/comparison/history/__init__.py +28 -0
- sciapi-0.0.1/sciapi/comparison/history/_capture_compatibility.py +531 -0
- sciapi-0.0.1/sciapi/comparison/history/_compare.py +1451 -0
- sciapi-0.0.1/sciapi/comparison/history/_fact_values.py +26 -0
- sciapi-0.0.1/sciapi/comparison/history/_policy_document.py +100 -0
- sciapi-0.0.1/sciapi/comparison/history/_snapshot_facts.py +785 -0
- sciapi-0.0.1/sciapi/comparison/history/_versions.py +193 -0
- sciapi-0.0.1/sciapi/comparison/history/policies.py +293 -0
- sciapi-0.0.1/sciapi/comparison/history/results.py +337 -0
- sciapi-0.0.1/sciapi/comparison/installed_python.py +45 -0
- sciapi-0.0.1/sciapi/comparison/python.py +288 -0
- sciapi-0.0.1/sciapi/comparison/receipts.py +237 -0
- sciapi-0.0.1/sciapi/comparison/results.py +62 -0
- sciapi-0.0.1/sciapi/config/__init__.py +119 -0
- sciapi-0.0.1/sciapi/config/_diagnostics.py +66 -0
- sciapi-0.0.1/sciapi/config/_generation.py +323 -0
- sciapi-0.0.1/sciapi/config/_operations.py +233 -0
- sciapi-0.0.1/sciapi/config/_plans.py +279 -0
- sciapi-0.0.1/sciapi/config/_project.py +821 -0
- sciapi-0.0.1/sciapi/config/_reference.py +390 -0
- sciapi-0.0.1/sciapi/config/_source_policies.py +457 -0
- sciapi-0.0.1/sciapi/config/_sources.py +572 -0
- sciapi-0.0.1/sciapi/config/_values.py +294 -0
- sciapi-0.0.1/sciapi/extraction/__init__.py +3 -0
- sciapi-0.0.1/sciapi/extraction/_clang_supplement.py +451 -0
- sciapi-0.0.1/sciapi/extraction/_extract.py +300 -0
- sciapi-0.0.1/sciapi/extraction/clang.py +725 -0
- sciapi-0.0.1/sciapi/extraction/observations.py +46 -0
- sciapi-0.0.1/sciapi/extraction/python/__init__.py +46 -0
- sciapi-0.0.1/sciapi/extraction/python/_encoding.py +982 -0
- sciapi-0.0.1/sciapi/extraction/python/_runtime_protocol.py +1186 -0
- sciapi-0.0.1/sciapi/extraction/python/_runtime_worker.py +1440 -0
- sciapi-0.0.1/sciapi/extraction/python/_source.py +1282 -0
- sciapi-0.0.1/sciapi/extraction/python/_visit.py +354 -0
- sciapi-0.0.1/sciapi/extraction/python/runtime.py +545 -0
- sciapi-0.0.1/sciapi/extraction/rustdoc.py +677 -0
- sciapi-0.0.1/sciapi/python_generation/__init__.py +9 -0
- sciapi-0.0.1/sciapi/python_generation/_generate.py +95 -0
- sciapi-0.0.1/sciapi/python_generation/_imports.py +261 -0
- sciapi-0.0.1/sciapi/python_generation/_manifest.py +135 -0
- sciapi-0.0.1/sciapi/python_generation/_members.py +73 -0
- sciapi-0.0.1/sciapi/python_generation/_plan.py +855 -0
- sciapi-0.0.1/sciapi/python_generation/_reference_inputs.py +46 -0
- sciapi-0.0.1/sciapi/python_generation/_reused_sources.py +112 -0
- sciapi-0.0.1/sciapi/python_generation/_source_syntax.py +308 -0
- sciapi-0.0.1/sciapi/python_generation/_target.py +64 -0
- sciapi-0.0.1/sciapi/python_generation/native_stubs.py +398 -0
- sciapi-0.0.1/sciapi/python_generation/package.py +799 -0
- sciapi-0.0.1/sciapi/python_generation/results.py +202 -0
- sciapi-0.0.1/sciapi/python_generation/runtime_modules.py +1104 -0
- sciapi-0.0.1/sciapi/python_generation/stubs.py +749 -0
- sciapi-0.0.1/sciapi/references/__init__.py +9 -0
- sciapi-0.0.1/sciapi/references/_documentation_ownership.py +295 -0
- sciapi-0.0.1/sciapi/references/_documents.py +470 -0
- sciapi-0.0.1/sciapi/references/_files.py +310 -0
- sciapi-0.0.1/sciapi/references/_native_prose.py +728 -0
- sciapi-0.0.1/sciapi/references/_pages.py +1542 -0
- sciapi-0.0.1/sciapi/references/_python_declarations.py +874 -0
- sciapi-0.0.1/sciapi/references/_reference.py +64 -0
- sciapi-0.0.1/sciapi/references/_render.py +617 -0
- sciapi-0.0.1/sciapi/references/_validation.py +94 -0
- sciapi-0.0.1/sciapi/references/reader.py +44 -0
- sciapi-0.0.1/sciapi/references/results.py +46 -0
- sciapi-0.0.1/sciapi/resources/schemas/griffe-LICENSE.txt +15 -0
- sciapi-0.0.1/sciapi/resources/schemas/python-public.schema.json +1143 -0
- sciapi-0.0.1/sciapi/resources/static/sciapi.css +29 -0
- sciapi-0.0.1/sciapi/resources/templates/reference/page.md.jinja +33 -0
- sciapi-0.0.1/sciapi/snapshots/__init__.py +6 -0
- sciapi-0.0.1/sciapi/snapshots/_freshness.py +145 -0
- sciapi-0.0.1/sciapi/snapshots/_manifest.py +233 -0
- sciapi-0.0.1/sciapi/snapshots/_pointers.py +93 -0
- sciapi-0.0.1/sciapi/snapshots/_readers.py +65 -0
- sciapi-0.0.1/sciapi/snapshots/_writer.py +177 -0
- sciapi-0.0.1/sciapi/snapshots/bundles.py +319 -0
- sciapi-0.0.1/sciapi/sphinxext/__init__.py +92 -0
- sciapi-0.0.1/sciapi/sphinxext/_annotations.py +274 -0
- sciapi-0.0.1/sciapi/sphinxext/_directives.py +623 -0
- sciapi-0.0.1/sciapi/sphinxext/_lifecycle.py +233 -0
- sciapi-0.0.1/sciapi/sphinxext/_options.py +103 -0
- sciapi-0.0.1/sciapi/sphinxext/_staging.py +80 -0
- sciapi-0.0.1/sciapi/workflows/__init__.py +7 -0
- sciapi-0.0.1/sciapi/workflows/_cache.py +49 -0
- sciapi-0.0.1/sciapi/workflows/_execution.py +146 -0
- sciapi-0.0.1/sciapi/workflows/_request.py +130 -0
- sciapi-0.0.1/sciapi/workflows/results.py +156 -0
- sciapi-0.0.1/sciapi/workflows/session.py +779 -0
- sciapi-0.0.0/PKG-INFO +0 -4
- sciapi-0.0.0/pyproject.toml +0 -22
- sciapi-0.0.0/setup.cfg +0 -4
- sciapi-0.0.0/src/SciAPI.egg-info/PKG-INFO +0 -4
- sciapi-0.0.0/src/SciAPI.egg-info/SOURCES.txt +0 -7
- sciapi-0.0.0/src/SciAPI.egg-info/dependency_links.txt +0 -1
- sciapi-0.0.0/src/SciAPI.egg-info/not-zip-safe +0 -1
- sciapi-0.0.0/src/SciAPI.egg-info/top_level.txt +0 -1
- /sciapi-0.0.0/src/sciapi/__init__.py → /sciapi-0.0.1/sciapi/py.typed +0 -0
sciapi-0.0.1/.gitignore
ADDED
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,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,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
|
+
)
|