新增cdsl

This commit is contained in:
2026-08-24 14:52:08 +08:00
parent fd8c0c37ad
commit 9f8a55ff07
3892 changed files with 2872721 additions and 9169 deletions
+46 -13
View File
@@ -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: