Initial SQL-only 1C adapter baseline
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
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())
|
||||
Reference in New Issue
Block a user