feat: 完善一级关系编辑 UI 与视图体验
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
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 card editor UI", ("verify_property_card_editor_ui.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())
|
||||
Reference in New Issue
Block a user