"""Transport-free LightBurn MOPA import seam; never authorizes encoding.""" from __future__ import annotations from decimal import Decimal, InvalidOperation import xml.etree.ElementTree as ET UNIT_CONTRACT = "frequency=Hz;QPulseWidth=ns" class ProjectImportError(ValueError): """Ambiguous or malformed process metadata.""" def _number(element: ET.Element, field: str) -> str | None: children = element.findall(field) if not children: return None if len(children) != 1 or set(children[0].attrib) != {"Value"}: raise ProjectImportError(f"ambiguous {field}") raw = children[0].get("Value", "") try: value = Decimal(raw) except InvalidOperation as exc: raise ProjectImportError(f"invalid {field}") from exc if not value.is_finite() or value <= 0 or value > Decimal("1e12"): raise ProjectImportError(f"invalid {field}") return raw def _layer_id(element: ET.Element) -> str | None: children = element.findall("index") if not children: return None if len(children) != 1 or set(children[0].attrib) != {"Value"}: raise ProjectImportError("ambiguous layer index") raw = children[0].get("Value", "") if not raw.isdecimal(): raise ProjectImportError("invalid layer index") return str(int(raw)) def import_project_mopa(data: bytes, *, unit_contract: str | None = None) -> dict: """Preserve observed XML fields and optionally normalize declared units. The caller must supply an independently established serialized-unit contract. No unit is inferred from magnitude. Missing pulse width is never defaulted. Results are offline metadata, not executable Rayforge workflow settings. """ if unit_contract not in (None, UNIT_CONTRACT): raise ProjectImportError("unsupported serialized-unit contract") if len(data) > 64 * 1024 * 1024: raise ProjectImportError("project exceeds offline import size limit") # Reject declarations, including UTF-16/32 encodings, before XML parsing. probe = data.replace(b"\x00", b"").upper() if b" 1 or (modes and set(modes[0].attrib) != {"Value"}): raise ProjectImportError("ambiguous image mode") image_mode = modes[0].get("Value") if modes else None normalized = None if unit_contract and all(value is not None for value in raw.values()): normalized = { "frequency_hz": float(Decimal(raw["frequency"])), "frequency_khz": float(Decimal(raw["frequency"]) / 1000), "pulse_width_ns": float(Decimal(raw["QPulseWidth"])), } layers.append({"element": setting.tag, "type": kind, "source_layer_id": layer_id, "raw": raw, "image_mode": image_mode, "normalized": normalized, "blockers": blockers}) if not layers: raise ProjectImportError("project has no process settings") return {"layers": layers, "unit_contract": unit_contract, "transport": None, "encoding_allowed": False, "hardware_use_allowed": False, "blockers": ["machine identity, correction and limits unverified", "offline import seam is not wired to host workflow"]}