from __future__ import annotations import json from pathlib import Path import py_compile import sys import tempfile PROJECT_ROOT = Path(__file__).resolve().parent.parent if str(PROJECT_ROOT) not in sys.path: sys.path.insert(0, str(PROJECT_ROOT)) from step_editor.parametric_component import export_parametric_component def _assert(condition: bool, message: str) -> None: if not condition: raise AssertionError(message) def main() -> int: with tempfile.TemporaryDirectory(prefix="geom_param_component_export_") as temp_dir: root = Path(temp_dir) source_step = root / "source.step" source_step.write_text("ISO-10303-21;\nEND-ISO-10303-21;\n", encoding="utf-8") parameters = [ { "name": "面内长度", "displayName": "面内长度", "type": "number", "ioRole": "input", "default": "10", } ] edits = [ { "parameter": "面内长度", "displayName": "面内长度", "targetKind": "feature", "targetId": 0, "uiAction": "resize_face_width_local", "operation": "resize_face_size_local", "args": [0, {"param": "面内长度"}, "width"], "default": 10.0, "valueType": "positive", "scope": "local", "scopeLabel": "局部重建", "sourceStep": str(source_step), "parameterKey": "local_face_width", } ] main_py = export_parametric_component( parameters=parameters, edits=edits, source_step=source_step, component_root=root / "nodes", component_name="测试组件", ) text = main_py.read_text(encoding="utf-8") _assert("INPUT_PARAMETERS = " in text, "generated main.py should embed selected input parameter list") _assert("PARAMETERS = INPUT_PARAMETERS + OUTPUT_PARAMETERS" in text, "generated main.py should expose FlowEditor parameters") _assert("NODE_INFO = " in text, "generated main.py should expose FlowEditor node info") _assert("def execute(inputs, params, context):" in text, "generated main.py should expose FlowEditor execute entry") _assert("COMPONENT = " in text, "generated main.py should embed execution config") _assert("step_edit_config.json" not in text, "generated component should not require a sidecar config JSON") _assert(not (main_py.parent / "data.json").exists(), "component directory should not contain data.json") _assert(not (main_py.parent / "step_edit_config.json").exists(), "component directory should not contain step_edit_config.json") py_compile.compile(str(main_py), doraise=True) namespace: dict[str, object] = {} exec(compile(text, str(main_py), "exec"), namespace) embedded_input_parameters = namespace.get("INPUT_PARAMETERS") embedded_parameters = namespace.get("PARAMETERS") node_info = namespace.get("NODE_INFO") embedded_component = namespace.get("COMPONENT") _assert(embedded_input_parameters == parameters, f"embedded INPUT_PARAMETERS mismatch: {embedded_input_parameters}") _assert(isinstance(embedded_parameters, list), "embedded PARAMETERS should be a list") _assert(embedded_parameters[: len(parameters)] == parameters, f"embedded input parameter prefix mismatch: {embedded_parameters}") _assert(any(row.get("name") == "output_step" and row.get("ioRole") == "output" for row in embedded_parameters if isinstance(row, dict)), "generated PARAMETERS should include output_step output port") _assert(isinstance(node_info, dict), "NODE_INFO should be a dict") _assert(node_info.get("parameters") == embedded_parameters, "NODE_INFO should point to PARAMETERS") _assert(isinstance(embedded_component, dict), "embedded COMPONENT should be a dict") _assert(embedded_component.get("edits") == edits, f"embedded edits mismatch: {json.dumps(embedded_component, ensure_ascii=False)}") print("parametric component export ok") return 0 if __name__ == "__main__": raise SystemExit(main())