docs/scripts/check_api_coverage.py
Rama main · réplica de lectura del repositorio original.
"""Check that every public Python module is included in API Reference."""
from __future__ import annotations
import importlib
import re
import sys
from pathlib import Path
from types import ModuleType
import yaml
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT / "src"))
sys.path.insert(0, str(ROOT))
PUBLIC_API = importlib.import_module("tests.public_api_contract").PUBLIC_API
DIRECTIVE = re.compile(r"^:::\s+([A-Za-z_][\w.]*)\s*$", re.MULTILINE)
def main() -> int:
reference_dir = ROOT / "docs" / "zh" / "reference"
directives: set[str] = set()
for path in reference_dir.glob("*.md"):
content = path.read_text(encoding="utf-8")
if content.startswith("---\n"):
metadata = yaml.safe_load(content.split("---", 2)[1]) or {}
if metadata.get("search", {}).get("exclude"):
continue
directives.update(DIRECTIVE.findall(content))
documented_objects: set[int] = set()
for identifier in directives:
obj = _resolve_identifier(identifier)
if isinstance(obj, ModuleType):
documented_objects.update(
id(getattr(obj, name))
for name in getattr(obj, "__all__", ())
)
else:
documented_objects.add(id(obj))
missing: list[str] = []
public_count = 0
for module in PUBLIC_API:
module_name = module.__name__
exports = tuple(getattr(module, "__all__", ()))
public_count += len(exports)
missing.extend(
f"{module_name}.{name}"
for name in exports
if id(getattr(module, name)) not in documented_objects
)
if missing:
print("Missing API reference directives:")
for identifier in missing:
print(f"- {identifier}")
return 1
print(
f"API reference covers {public_count} public exports "
f"from {len(PUBLIC_API)} modules."
)
return 0
def _resolve_identifier(identifier: str) -> object:
parts = identifier.split(".")
for index in range(len(parts), 0, -1):
module_name = ".".join(parts[:index])
try:
obj: object = importlib.import_module(module_name)
except ModuleNotFoundError:
continue
for name in parts[index:]:
obj = getattr(obj, name)
return obj
raise ValueError(f"Cannot resolve API documentation identifier: {identifier}")
if __name__ == "__main__":
raise SystemExit(main())