105 lines
3.6 KiB
Python
105 lines
3.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Inspect cached SGX endpoint responses and summarize JSON structure."""
|
|
|
|
import json
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
CACHE = ROOT / "discovery" / "cache"
|
|
FAIL = CACHE / "fail"
|
|
|
|
|
|
def summarize(value: Any, max_depth: int = 2, max_items: int = 5) -> Any:
|
|
"""Return a compact, depth-limited summary of a JSON value."""
|
|
if max_depth == 0:
|
|
if isinstance(value, dict):
|
|
return {k: type(v).__name__ for k, v in list(value.items())[:max_items]}
|
|
if isinstance(value, list):
|
|
return f"list[{len(value)}]"
|
|
return type(value).__name__
|
|
|
|
if isinstance(value, dict):
|
|
out = {}
|
|
for k, v in list(value.items())[:max_items]:
|
|
out[k] = summarize(v, max_depth - 1, max_items)
|
|
if len(value) > max_items:
|
|
out["..."] = f"+{len(value) - max_items} more"
|
|
return out
|
|
|
|
if isinstance(value, list):
|
|
n = len(value)
|
|
if n == 0:
|
|
return "list[0]"
|
|
sample = [summarize(v, max_depth - 1, max_items) for v in value[:max_items]]
|
|
if n > max_items:
|
|
sample.append(f"... +{n - max_items} more")
|
|
return [f"list[{n}]"] + sample
|
|
|
|
return value
|
|
|
|
|
|
def inspect(path: Path) -> dict:
|
|
result = {
|
|
"path": str(path.relative_to(ROOT)),
|
|
"size": path.stat().st_size,
|
|
"valid_json": False,
|
|
"top_keys": [],
|
|
"summary": None,
|
|
"array_samples": {},
|
|
"error": "",
|
|
}
|
|
try:
|
|
data = json.loads(path.read_text(encoding="utf-8", errors="replace"))
|
|
result["valid_json"] = True
|
|
if isinstance(data, dict):
|
|
result["top_keys"] = list(data.keys())
|
|
result["summary"] = summarize(data, max_depth=2, max_items=6)
|
|
|
|
# Sample arrays of dicts up to 3 entries, limited depth.
|
|
def find_arrays(obj, prefix=""):
|
|
if isinstance(obj, list) and obj and isinstance(obj[0], dict):
|
|
result["array_samples"][prefix] = {
|
|
"count": len(obj),
|
|
"first_keys": list(obj[0].keys())[:20],
|
|
"samples": obj[:3],
|
|
}
|
|
elif isinstance(obj, dict):
|
|
for k, v in obj.items():
|
|
find_arrays(v, f"{prefix}.{k}" if prefix else k)
|
|
elif isinstance(obj, list):
|
|
for i, v in enumerate(obj[:3]):
|
|
find_arrays(v, f"{prefix}[{i}]")
|
|
|
|
find_arrays(data)
|
|
except Exception as exc:
|
|
result["error"] = str(exc)
|
|
return result
|
|
|
|
|
|
def main():
|
|
print("# Cache inspection summary\n")
|
|
for directory in (CACHE, FAIL):
|
|
if not directory.exists():
|
|
continue
|
|
label = "FAIL" if directory.name == "fail" else "OK"
|
|
for path in sorted(directory.glob("*.json")):
|
|
if path.name.endswith(".meta.json"):
|
|
continue
|
|
result = inspect(path)
|
|
status = "VALID" if result["valid_json"] else "INVALID"
|
|
print(f"## {path.name} [{label}] ({status}, {result['size']} bytes)")
|
|
if result["error"]:
|
|
print(f"- Error: {result['error']}")
|
|
if result["top_keys"]:
|
|
print(f"- Top-level keys: {result['top_keys']}")
|
|
if result["array_samples"]:
|
|
for key, info in result["array_samples"].items():
|
|
print(f"- Array `{key}`: {info['count']} items, keys: {info['first_keys']}")
|
|
print(f"- Summary: {json.dumps(result['summary'], ensure_ascii=False)}")
|
|
print()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|