Files
FreeCADWasmDev/tools/generate_python_family_adapter_manifest.py
wangdequan 9a7c4f0335 Save FreeCAD Web workspace sources and user validation evidence
IFC native binding remains incomplete; preserve accurate test results.
2026-09-15 22:01:58 +08:00

66 lines
5.2 KiB
Python

#!/usr/bin/env python3
"""Generate an implementation-stage adapter map for one module+tier batch."""
from __future__ import annotations
import argparse
import hashlib
import json
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
ADAPTERS = {
"Assembly": ("assembly.worker.ts", "assembly.pythonFamily", "src/WebAssembly/FreeCADCoreProbe/AssemblyRuntimeProbe.cpp"),
"BIM": ("bim.worker.ts", "bim.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/BimRuntimeProbe.cpp"),
"CAM": ("cam.worker.ts", "cam.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/CAMRuntimeProbe.cpp"),
"Draft": ("draft.worker.ts", "draft.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/DraftRuntimeProbe.cpp"),
"Fem": ("fem.worker.ts", "fem.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/FemGenericFamilyProbe.cpp"),
"Import": ("import.worker.ts", "import.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/ImportRuntimeProbe.cpp"),
"Material": ("material.worker.ts", "material.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/MaterialKernelProbe.cpp"),
"Measure": ("measure.worker.ts", "measure.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/MeasureRuntimeProbe.cpp"),
"Mesh": ("mesh.worker.ts", "mesh.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/MeshRuntimeProbe.cpp"),
"MeshPart": ("meshpart.worker.ts", "meshpart.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/MeshPartRuntimeProbe.cpp"),
"Part": ("part.worker.ts", "part.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/PartBoxProbe.cpp"),
"PartDesign": ("partdesign-python.worker.ts", "partdesign.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/PartDesignRuntimeProbe.cpp"),
"Plot": ("plot-python.worker.ts", "plot.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/PlotRuntimeProbe.cpp"),
"Points": ("points.worker.ts", "points.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/PointsRuntimeProbe.cpp"),
"ReverseEngineering": ("reverseengineering-python.worker.ts", "reverseengineering.pythonFamilyBatch", "src/Mod/ReverseEngineering/InitGui.py"),
"Robot": ("robot-python.worker.ts", "robot.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/RobotRuntimeProbeFixed.cpp"),
"Sandbox": ("sandbox-python.worker.ts", "sandbox.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/SandboxRuntimeProbe.cpp"),
"Show": ("show-python.worker.ts", "show.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/ShowRuntimeProbe.cpp"),
"Sketcher": ("sketcher-python.worker.ts", "sketcher.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/SketcherProbe.cpp"),
"Spreadsheet": ("spreadsheet-python.worker.ts", "spreadsheet.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/SpreadsheetRuntimeProbe.cpp"),
"Surface": ("surface-python.worker.ts", "surface.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/SurfaceFamilyProbe.cpp"),
"TechDraw": ("techdraw-python.worker.ts", "techdraw.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/TechDrawRuntimeProbe.cpp"),
"TemplatePyMod": ("templatepymod-python.worker.ts", "templatepymod.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/TemplatePyModRuntimeProbe.cpp"),
"OpenSCAD": ("openscad.worker.ts", "openscad.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/OpenSCADRuntimeProbe.cpp"),
}
parser = argparse.ArgumentParser()
parser.add_argument("module")
parser.add_argument("tier")
parser.add_argument("--output")
args = parser.parse_args()
if args.module not in ADAPTERS:
raise SystemExit(f"no adapter mapping for {args.module}")
manifest_path = ROOT / "docs/p6/python-api-manifest.json"
rows = json.loads(manifest_path.read_text(encoding="utf-8"))["records"]
selected = [row for row in rows if row["module"] == args.module and row["tier"] == args.tier]
worker, command, native_source = ADAPTERS[args.module]
records = [{"apiId": row["id"], "name": row["name"], "kind": row["kind"], "family": row["family"], "sourcePath": row.get("evidence", {}).get("path"), "route": command, "adapterStatus": "module_adapter_ready_pending_method", "disposition": row["disposition"]} for row in selected]
output = {
"schema": "freecad-web-python-family-adapter-manifest/v1",
"taskId": f"FW-P6-FPA-IMPL-{args.module.upper()}-{args.tier.upper().replace('-', '_')}",
"source": {"manifest": "docs/p6/python-api-manifest.json", "manifestSha256": hashlib.sha256(manifest_path.read_bytes()).hexdigest()},
"module": args.module,
"tier": args.tier,
"count": len(records),
"route": {"worker": worker, "command": command, "nativeSource": native_source},
"records": records,
"boundaries": ["module adapter readiness is not method-level parameter/return evidence", "original disposition is preserved until the matching coverage gate"],
}
short_tier = {"tier-1-readonly": "tier1", "tier-2-pure": "tier2", "tier-3-stateful": "tier3"}.get(args.tier, args.tier.replace("-", ""))
out = ROOT / (args.output or f"docs/p6/{args.module.lower()}-{short_tier}-adapter-manifest.json")
out.write_text(json.dumps(output, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
print(json.dumps({"output": str(out.relative_to(ROOT)), "module": args.module, "tier": args.tier, "count": len(records), "sha256": hashlib.sha256(out.read_bytes()).hexdigest()}, ensure_ascii=False))