139 lines
5.4 KiB
Python
139 lines
5.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Summarize DBNames-Ext records by extension inventory and XML match status."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
from collections import Counter
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
|
|
def load_json(path: Path) -> dict[str, Any]:
|
|
return json.loads(path.read_text(encoding="utf-8"))
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description="Summarize extension DBNames records.")
|
|
parser.add_argument("--dbnames", type=Path, required=True)
|
|
parser.add_argument("--compare", type=Path, required=True)
|
|
parser.add_argument("--inventory", type=Path, required=True)
|
|
parser.add_argument("--output", type=Path, required=True)
|
|
args = parser.parse_args()
|
|
|
|
dbnames = load_json(args.dbnames)
|
|
compare = load_json(args.compare)
|
|
inventory = load_json(args.inventory)
|
|
|
|
extension_by_file = {}
|
|
for extension in inventory.get("extensions") or []:
|
|
file_name = extension.get("dbnames_ext_file_name")
|
|
if file_name:
|
|
extension_by_file[file_name] = extension
|
|
|
|
unmatched_guid_set = set(compare.get("unmatched_sql_guids") or [])
|
|
matched_guid_set = set(compare.get("matched_guids") or [])
|
|
unmatched_by_guid = {item["guid"]: item for item in compare.get("unmatched_sql") or []}
|
|
if not unmatched_guid_set:
|
|
unmatched_guid_set = set(unmatched_by_guid)
|
|
if not matched_guid_set:
|
|
matched_guid_set = {item["guid"] for item in compare.get("matches") or []}
|
|
|
|
summaries: dict[str, Any] = {}
|
|
for dbnames_file in dbnames.get("dbnames") or []:
|
|
file_name = dbnames_file.get("file_name")
|
|
if not str(file_name).startswith("DBNames-Ext-"):
|
|
continue
|
|
extension = extension_by_file.get(file_name)
|
|
key = file_name
|
|
item = summaries.setdefault(
|
|
key,
|
|
{
|
|
"dbnames_ext_file": file_name,
|
|
"extension_name": extension.get("extension_name") if extension else None,
|
|
"extension_guid": extension.get("dbnames_ext_guid") if extension else None,
|
|
"extension_order": extension.get("extension_order") if extension else None,
|
|
"record_count": 0,
|
|
"guid_count": 0,
|
|
"matched_guid_count": 0,
|
|
"unmatched_guid_count": 0,
|
|
"storage_role_counts": Counter(),
|
|
"matched_storage_role_counts": Counter(),
|
|
"unmatched_storage_role_counts": Counter(),
|
|
"unmatched_examples": [],
|
|
},
|
|
)
|
|
seen_guids = set()
|
|
for record in dbnames_file.get("records") or []:
|
|
if record.get("status") != "parsed":
|
|
continue
|
|
guid = record.get("guid")
|
|
role = record.get("storage_role")
|
|
item["record_count"] += 1
|
|
item["storage_role_counts"][role] += 1
|
|
if guid not in seen_guids:
|
|
seen_guids.add(guid)
|
|
item["guid_count"] += 1
|
|
if guid in matched_guid_set:
|
|
item["matched_guid_count"] += 1
|
|
elif guid in unmatched_guid_set:
|
|
item["unmatched_guid_count"] += 1
|
|
if len(item["unmatched_examples"]) < 20:
|
|
item["unmatched_examples"].append(
|
|
{
|
|
"guid": guid,
|
|
"storage_roles": (unmatched_by_guid.get(guid) or {}).get("storage_roles"),
|
|
"records": (unmatched_by_guid.get(guid) or {}).get("records", [])[:5],
|
|
}
|
|
)
|
|
else:
|
|
item["unmatched_guid_count"] += 1
|
|
if guid in matched_guid_set:
|
|
item["matched_storage_role_counts"][role] += 1
|
|
else:
|
|
item["unmatched_storage_role_counts"][role] += 1
|
|
|
|
output_items = []
|
|
for item in summaries.values():
|
|
output_items.append(
|
|
{
|
|
**{
|
|
key: value
|
|
for key, value in item.items()
|
|
if not key.endswith("_counts") and key != "unmatched_examples"
|
|
},
|
|
"storage_role_counts": dict(item["storage_role_counts"].most_common()),
|
|
"matched_storage_role_counts": dict(item["matched_storage_role_counts"].most_common()),
|
|
"unmatched_storage_role_counts": dict(item["unmatched_storage_role_counts"].most_common()),
|
|
"unmatched_examples": item["unmatched_examples"],
|
|
}
|
|
)
|
|
output_items.sort(key=lambda row: (-row["unmatched_guid_count"], row["dbnames_ext_file"]))
|
|
|
|
result = {
|
|
"schema": "onec_extension_dbnames_summary.v1",
|
|
"dbnames": str(args.dbnames),
|
|
"compare": str(args.compare),
|
|
"inventory": str(args.inventory),
|
|
"extension_file_count": len(output_items),
|
|
"extensions": output_items,
|
|
}
|
|
args.output.parent.mkdir(parents=True, exist_ok=True)
|
|
args.output.write_text(json.dumps(result, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
|
|
print(
|
|
json.dumps(
|
|
{
|
|
"output": str(args.output),
|
|
"extension_files": len(output_items),
|
|
"total_unmatched_guids": sum(item["unmatched_guid_count"] for item in output_items),
|
|
},
|
|
ensure_ascii=False,
|
|
)
|
|
)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|