新增cdsl
This commit is contained in:
@@ -32,6 +32,7 @@ from cdsl_engine.semantic_validation import validate_semantic_cdsl # noqa: E402
|
||||
|
||||
METERS_TO_MM = 1000.0
|
||||
EPSILON_MM = 1e-4
|
||||
EVIDENCE_V2_SUFFIX = ".solidworks_evidence_v2.json"
|
||||
SUPPORTED_ATOMS = {
|
||||
"extrude_add_blind",
|
||||
"extrude_add_two_sided",
|
||||
@@ -870,7 +871,17 @@ def _topologically_order_features(features: list[dict[str, Any]]) -> list[dict[s
|
||||
return ordered
|
||||
|
||||
|
||||
def convert_evidence(evidence: dict[str, Any], *, source_name: str, step_path: Path | None = None) -> tuple[dict[str, Any], dict[str, Any]]:
|
||||
def _part_id_from_source_name(source_name: str) -> str:
|
||||
"""Build a schema-valid ID from the entire evidence file name."""
|
||||
stem = Path(source_name).name.removesuffix(EVIDENCE_V2_SUFFIX)
|
||||
part_id = re.sub(r"[^A-Za-z0-9_-]+", "-", stem).strip("-")
|
||||
if len(part_id) < 3:
|
||||
part_id = f"part-{part_id}".rstrip("-")
|
||||
return part_id[:80]
|
||||
|
||||
|
||||
def convert_evidence(evidence: dict[str, Any], *, source_name: str, step_path: Path | None = None,
|
||||
part_id: str | None = None) -> tuple[dict[str, Any], dict[str, Any]]:
|
||||
if evidence.get("schema") != "solidworks.cad_evidence.v2":
|
||||
raise ValueError("Expected schema solidworks.cad_evidence.v2")
|
||||
features = sorted((item for item in evidence.get("features") or [] if isinstance(item, dict)), key=lambda item: int(_number(item.get("sequence"))))
|
||||
@@ -1105,7 +1116,7 @@ def convert_evidence(evidence: dict[str, Any], *, source_name: str, step_path: P
|
||||
})
|
||||
cdsl_features = _topologically_order_features(cdsl_features)
|
||||
|
||||
part_id = re.sub(r"[^A-Za-z0-9_-]+", "-", Path(source_name).name.split(".")[0]).strip("-") or "part"
|
||||
part_id = part_id or _part_id_from_source_name(source_name)
|
||||
truth = evidence.get("document_truth") or {}
|
||||
step_summary = step.summary(truth)
|
||||
cdsl = {
|
||||
@@ -1133,34 +1144,56 @@ def _write_json(path: Path, value: Any) -> None:
|
||||
path.write_text(json.dumps(value, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
|
||||
|
||||
|
||||
def _convert_path(source: Path, output_dir: Path, truth_dir: Path | None, overwrite: bool) -> dict[str, Any]:
|
||||
part_id = source.name.split(".")[0]
|
||||
def _convert_path(source: Path, output_dir: Path, truth_dir: Path | None, overwrite: bool,
|
||||
source_name: str, truth_relative_path: Path, part_id: str) -> dict[str, Any]:
|
||||
cdsl_path = output_dir / f"{part_id}.cdsl.json"
|
||||
diagnostic_path = output_dir / f"{part_id}.diagnostic.json"
|
||||
if not overwrite and cdsl_path.exists() and diagnostic_path.exists():
|
||||
return {"part_id": part_id, "status": "skipped", "cdsl": cdsl_path.name, "diagnostic": diagnostic_path.name}
|
||||
return {
|
||||
"part_id": part_id, "source": source_name, "status": "skipped",
|
||||
"cdsl": cdsl_path.name, "diagnostic": diagnostic_path.name,
|
||||
}
|
||||
try:
|
||||
evidence = json.loads(source.read_text(encoding="utf-8"))
|
||||
step_path = (truth_dir / f"{part_id}.step") if truth_dir else None
|
||||
cdsl, diagnostic = convert_evidence(evidence, source_name=source.name, step_path=step_path)
|
||||
step_path = (truth_dir / truth_relative_path) if truth_dir else None
|
||||
cdsl, diagnostic = convert_evidence(evidence, source_name=source_name, step_path=step_path, part_id=part_id)
|
||||
_write_json(cdsl_path, cdsl)
|
||||
_write_json(diagnostic_path, diagnostic)
|
||||
return {"part_id": part_id, "status": "converted", "cdsl": cdsl_path.name, "diagnostic": diagnostic_path.name,
|
||||
return {"part_id": part_id, "source": source_name, "status": "converted", "cdsl": cdsl_path.name, "diagnostic": diagnostic_path.name,
|
||||
"future_rebuild_ready": diagnostic["semantic_validation"]["future_rebuild_ready"],
|
||||
"deferred_feature_count": len(diagnostic["semantic_validation"]["deferred_feature_ids"]),
|
||||
"unresolved_feature_count": len(diagnostic["semantic_validation"]["unresolved"])}
|
||||
except Exception as error:
|
||||
_write_json(diagnostic_path, {"source": source.name, "part_id": part_id, "error": str(error)})
|
||||
return {"part_id": part_id, "status": "failed", "diagnostic": diagnostic_path.name, "error": str(error)}
|
||||
_write_json(diagnostic_path, {"source": source_name, "part_id": part_id, "error": str(error)})
|
||||
return {"part_id": part_id, "source": source_name, "status": "failed", "diagnostic": diagnostic_path.name, "error": str(error)}
|
||||
|
||||
|
||||
def batch_convert(evidence_dir: Path, output_dir: Path, *, truth_dir: Path | None = None, workers: int = 1,
|
||||
fail_fast: bool = False, overwrite: bool = False) -> dict[str, Any]:
|
||||
sources = sorted(evidence_dir.glob("*.solidworks_evidence_v2.json"))
|
||||
sources = sorted(evidence_dir.rglob(f"*{EVIDENCE_V2_SUFFIX}"))
|
||||
if not sources:
|
||||
raise ValueError(f"No *.solidworks_evidence_v2.json files found in {evidence_dir}")
|
||||
raise ValueError(f"No *{EVIDENCE_V2_SUFFIX} files found in {evidence_dir}")
|
||||
sources_by_base_id: dict[str, list[Path]] = {}
|
||||
for source in sources:
|
||||
base_id = _part_id_from_source_name(source.name)
|
||||
sources_by_base_id.setdefault(base_id, []).append(source)
|
||||
part_id_by_source: dict[Path, str] = {}
|
||||
for base_id, matching_sources in sources_by_base_id.items():
|
||||
if len(matching_sources) == 1:
|
||||
part_id_by_source[matching_sources[0]] = base_id
|
||||
continue
|
||||
for source in matching_sources:
|
||||
relative_name = source.relative_to(evidence_dir).as_posix()
|
||||
digest = hashlib.sha256(relative_name.encode("utf-8")).hexdigest()[:10]
|
||||
part_id_by_source[source] = f"{base_id[:69]}-{digest}"
|
||||
if len(set(part_id_by_source.values())) != len(part_id_by_source):
|
||||
raise ValueError("Unable to create unique output part IDs from evidence source paths")
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
convert = lambda source: _convert_path(source, output_dir, truth_dir, overwrite)
|
||||
def convert(source: Path) -> dict[str, Any]:
|
||||
relative = source.relative_to(evidence_dir)
|
||||
step_relative = Path(str(relative).removesuffix(EVIDENCE_V2_SUFFIX) + ".step")
|
||||
return _convert_path(source, output_dir, truth_dir, overwrite, relative.as_posix(), step_relative,
|
||||
part_id_by_source[source])
|
||||
results: list[dict[str, Any]] = []
|
||||
if workers == 1:
|
||||
for source in sources:
|
||||
|
||||
Reference in New Issue
Block a user