4e7877e05c
接入 SCDM probe/edit/cache/校验链路,增强孔组、阵列、关系式和参数表交互。 支持阵列相邻段间距、移动意图切换、结果回滚校验,并补充对应回归脚本。
178 lines
5.8 KiB
Python
178 lines
5.8 KiB
Python
from __future__ import annotations
|
|
|
|
import argparse
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parent.parent
|
|
SCRIPT_DIR = PROJECT_ROOT / "scripts"
|
|
|
|
|
|
STAGES: tuple[tuple[str, str, tuple[tuple[str, tuple[str, ...]], ...]], ...] = (
|
|
(
|
|
"face",
|
|
"Face first-level edit baseline",
|
|
(
|
|
("Face edit suite", ("verify_face_edit_suite.py",)),
|
|
("Face isolated worker edits", ("verify_isolated_face_edit.py",)),
|
|
),
|
|
),
|
|
(
|
|
"hole-slot",
|
|
"Hole and slot first-level edit baseline",
|
|
(
|
|
("Hole/slot edit suite", ("verify_hole_slot_edit_suite.py",)),
|
|
),
|
|
),
|
|
(
|
|
"edge",
|
|
"Edge first-level edit baseline",
|
|
(
|
|
("Edge edit suite", ("verify_edge_edit_suite.py",)),
|
|
("Edge isolated worker edits", ("verify_edge_isolated_edit.py",)),
|
|
),
|
|
),
|
|
(
|
|
"boss",
|
|
"Boss first-level edit baseline",
|
|
(
|
|
("Boss edit suite", ("verify_boss_edit_suite.py",)),
|
|
),
|
|
),
|
|
(
|
|
"round-chamfer",
|
|
"Round and chamfer first-level edit baseline",
|
|
(
|
|
("Round/chamfer edit suite", ("verify_round_chamfer_edit_suite.py",)),
|
|
),
|
|
),
|
|
(
|
|
"shell",
|
|
"Shell thickness first-level edit baseline",
|
|
(
|
|
("Shell edit suite", ("verify_shell_edit_suite.py",)),
|
|
),
|
|
),
|
|
(
|
|
"analytic",
|
|
"Analytic surface edit baseline",
|
|
(
|
|
("Analytic surface edits", ("verify_analytic_surface_resize.py",)),
|
|
("Cone semi-angle isolated edits", ("verify_cone_semi_angle_isolation.py",)),
|
|
),
|
|
),
|
|
)
|
|
|
|
QUICK_COMMANDS: tuple[tuple[str, tuple[str, ...]], ...] = (
|
|
("Smoke test", ("main.py", "--smoke-test")),
|
|
("Property editor specs", ("verify_property_editor_specs.py",)),
|
|
("Property table editor UI", ("verify_property_card_editor_ui.py",)),
|
|
("Relation formula rules", ("verify_relation_formula_rules.py",)),
|
|
("Parametric component export", ("verify_parametric_component_export.py",)),
|
|
("SCDM backend discovery", ("verify_scdm_backend.py",)),
|
|
("SCDM runtime status", ("verify_scdm_status.py",)),
|
|
("SCDM probe pipeline", ("verify_scdm_probe_pipeline.py",)),
|
|
("SCDM edit runner", ("verify_scdm_edit_runner.py",)),
|
|
("SCDM result validator", ("verify_scdm_result_validator.py",)),
|
|
("Analysis Situs hole bridge", ("verify_asitus_hole_bridge.py",)),
|
|
("ICEPAK cylindrical same-domain hole", ("verify_icepak_cylindrical_region_selection.py",)),
|
|
("Feature recognition priority", ("verify_feature_recognition_summary.py",)),
|
|
("First-level fact graph", ("verify_first_level_fact_graph.py",)),
|
|
("Associated feature probe and display budget", ("verify_associated_features.py",)),
|
|
("First-level acceptance docs", ("verify_first_level_acceptance_docs.py",)),
|
|
)
|
|
|
|
|
|
def _stage_names() -> tuple[str, ...]:
|
|
return tuple(stage[0] for stage in STAGES)
|
|
|
|
|
|
def _selected_stages(names: tuple[str, ...]) -> tuple[tuple[str, str, tuple[tuple[str, tuple[str, ...]], ...]], ...]:
|
|
if not names:
|
|
return STAGES
|
|
selected = {name.strip() for name in names if name.strip()}
|
|
return tuple(stage for stage in STAGES if stage[0] in selected)
|
|
|
|
|
|
def _run(label: str, command: tuple[str, ...], *, index: int, total: int) -> None:
|
|
print(f"\n[{index}/{total}] {label}", flush=True)
|
|
target = SCRIPT_DIR / command[0]
|
|
if not target.exists():
|
|
target = PROJECT_ROOT / command[0]
|
|
env = os.environ.copy()
|
|
env.setdefault("PYTHONIOENCODING", "utf-8")
|
|
env.setdefault("PYTHONUTF8", "1")
|
|
subprocess.run(
|
|
(sys.executable, str(target), *command[1:]),
|
|
cwd=PROJECT_ROOT,
|
|
env=env,
|
|
check=True,
|
|
)
|
|
|
|
|
|
def _display_command(command: tuple[str, ...]) -> str:
|
|
target = SCRIPT_DIR / command[0]
|
|
prefix = "scripts\\"
|
|
if not target.exists():
|
|
prefix = ""
|
|
args = " ".join(command[1:])
|
|
return f"python {prefix}{command[0]} {args}".rstrip()
|
|
|
|
|
|
def _commands_for(stages: tuple[tuple[str, str, tuple[tuple[str, tuple[str, ...]], ...]], ...]) -> list[tuple[str, tuple[str, ...]]]:
|
|
commands: list[tuple[str, tuple[str, ...]]] = []
|
|
for _stage_name, stage_label, cases in stages:
|
|
for label, command in cases:
|
|
commands.append((f"{stage_label}: {label}", command))
|
|
return commands
|
|
|
|
|
|
def main(argv: tuple[str, ...] | None = None) -> int:
|
|
parser = argparse.ArgumentParser(
|
|
description="Run staged first-level geometry edit verification suites.",
|
|
)
|
|
parser.add_argument(
|
|
"--stage",
|
|
action="append",
|
|
choices=_stage_names(),
|
|
help="Only run one stage. Repeat this option to run multiple stages.",
|
|
)
|
|
parser.add_argument(
|
|
"--quick",
|
|
action="store_true",
|
|
help="Run lightweight first-level regression checks instead of the full geometry suites.",
|
|
)
|
|
parser.add_argument(
|
|
"--list",
|
|
action="store_true",
|
|
help="Print the staged verification plan without running it.",
|
|
)
|
|
args = parser.parse_args(argv)
|
|
|
|
if args.quick:
|
|
commands = list(QUICK_COMMANDS)
|
|
heading = "quick first-level regression checks"
|
|
else:
|
|
stages = _selected_stages(tuple(args.stage or ()))
|
|
commands = _commands_for(stages)
|
|
heading = "first-level edit suites"
|
|
|
|
if args.list:
|
|
print(f"{heading}:")
|
|
for index, (label, command) in enumerate(commands, start=1):
|
|
print(f"{index}. {label}: {_display_command(command)}")
|
|
return 0
|
|
|
|
total = len(commands)
|
|
for index, (label, command) in enumerate(commands, start=1):
|
|
_run(label, command, index=index, total=total)
|
|
print(f"\n{heading} passed.", flush=True)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|