90 lines
3.4 KiB
Python
90 lines
3.4 KiB
Python
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
import yaml
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
DEFAULT_START_LINKS = ROOT / "plugins" / "1c" / "rag" / "official-docs" / "start-links.json"
|
|
DEFAULT_SOURCES = ROOT / "plugins" / "1c" / "rag" / "official-docs" / "sources.yaml"
|
|
DEFAULT_OUTPUT = ROOT / "reports" / "1c-official-docs-start-coverage.json"
|
|
|
|
|
|
def load_json(path: Path) -> dict[str, Any]:
|
|
return json.loads(path.read_text(encoding="utf-8-sig")) if path.exists() else {}
|
|
|
|
|
|
def load_yaml(path: Path) -> dict[str, Any]:
|
|
data = yaml.safe_load(path.read_text(encoding="utf-8"))
|
|
return data if isinstance(data, dict) else {}
|
|
|
|
|
|
def check_coverage(start_links_path: Path, sources_path: Path) -> dict[str, Any]:
|
|
start_links = load_json(start_links_path)
|
|
sources_config = load_yaml(sources_path)
|
|
source_urls = {str(item.get("url") or "") for item in sources_config.get("sources") or []}
|
|
candidates = start_links.get("start_links") or []
|
|
rows = []
|
|
by_category: dict[str, dict[str, int]] = {}
|
|
for item in candidates:
|
|
category = str(item.get("category") or "unknown")
|
|
active = str(item.get("url") or "") in source_urls
|
|
by_category.setdefault(category, {"candidates": 0, "active": 0, "inactive": 0})
|
|
by_category[category]["candidates"] += 1
|
|
by_category[category]["active" if active else "inactive"] += 1
|
|
rows.append({**item, "active": active})
|
|
inactive = [item for item in rows if not item["active"]]
|
|
counts = {
|
|
"sources": len(source_urls),
|
|
"candidates": len(rows),
|
|
"active_candidates": sum(1 for item in rows if item["active"]),
|
|
"inactive_candidates": len(inactive),
|
|
}
|
|
findings = []
|
|
required_categories = {
|
|
"dev_section",
|
|
"dev_section_index",
|
|
"developer_glossary",
|
|
"development_standards",
|
|
"methodical_support",
|
|
"platform_doc",
|
|
}
|
|
for category in sorted(required_categories):
|
|
stats = by_category.get(category) or {}
|
|
if stats.get("active", 0) == 0:
|
|
findings.append({"severity": "error", "message": f"no active source for required category {category}"})
|
|
return {
|
|
"schema": "onec_its_start_link_coverage.v1",
|
|
"passed": not any(item["severity"] == "error" for item in findings),
|
|
"start_links": str(start_links_path),
|
|
"sources": str(sources_path),
|
|
"counts": counts,
|
|
"by_category": dict(sorted(by_category.items())),
|
|
"findings": findings,
|
|
"inactive_samples": inactive[:50],
|
|
}
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description="Compare discovered 1C:ITS start links with active sources.yaml seeds.")
|
|
parser.add_argument("--start-links", type=Path, default=DEFAULT_START_LINKS)
|
|
parser.add_argument("--sources", type=Path, default=DEFAULT_SOURCES)
|
|
parser.add_argument("--output", type=Path, default=DEFAULT_OUTPUT)
|
|
parser.add_argument("--print", action="store_true", dest="print_report")
|
|
args = parser.parse_args()
|
|
|
|
report = check_coverage(args.start_links, args.sources)
|
|
args.output.parent.mkdir(parents=True, exist_ok=True)
|
|
args.output.write_text(json.dumps(report, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
|
|
if args.print_report:
|
|
print(json.dumps(report, ensure_ascii=False, indent=2))
|
|
return 0 if report["passed"] else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|