from pathlib import Path p = Path(r"C:\Users\User\Desktop\바이브코딩\pier_T\Code\교각모델링앱\runner.py") s = p.read_text(encoding="utf-8") reps = [ # result written atomically, so the runner can act as soon as it appears (""" json.dump(res, open(SPEC["result"], "w", encoding="utf-8"), ensure_ascii=False, indent=1) if opened is not None:""", """ tmp = SPEC["result"] + ".tmp" json.dump(res, open(tmp, "w", encoding="utf-8"), ensure_ascii=False, indent=1) os.replace(tmp, SPEC["result"]) if opened is not None:"""), ("""import io, json, sys, time, traceback""", """import io, json, os, sys, time, traceback"""), ("""def run_job(steps, save=None, units_mm_tolerance=None, timeout=1800, open_path=None): \"\"\"Run `steps` in a fresh Rhino; return the result dict (raises RhinoJobError on failure). open_path: run the steps on that .3dm opened headless (reload test) instead of the empty active doc. \"\"\"""", """def _window_title(pid): \"\"\"Main window title of a process (diagnosis of a stalled Rhino, e.g. a modal dialog).\"\"\" try: out = subprocess.run(["powershell", "-NoProfile", "-Command", f"(Get-Process -Id {pid}).MainWindowTitle"], capture_output=True, text=True, timeout=20) return out.stdout.strip() except Exception as e: return f"? ({e})" def _launch_and_wait(job, timeout, exit_grace): \"\"\"Start Rhino on job.py; return when result.json exists. A Rhino that does not exit within `exit_grace` seconds after writing the result is killed (2026-10-12: Rhino sometimes stalled on exit). Raises RhinoJobError if no result appears within `timeout` (Rhino killed; its window title is reported).\"\"\" rp = job / "result.json" # Pass a raw command line: Rhino only honours /runscript="..." (quote after '='), while a list argument # would be quoted as a whole ("/runscript=...") and silently ignored. proc = subprocess.Popen(f'"{RHINO_EXE}" /nosplash /notemplate ' f'/runscript="_-RunPythonScript {job / "job.py"} _-Exit"') t0 = time.time() while not rp.exists(): if proc.poll() is not None: raise RhinoJobError(f"Rhino exited (code {proc.returncode}) without a result: {job}") if time.time() - t0 > timeout: title = _window_title(proc.pid) proc.kill() raise RhinoJobError(f"Rhino gave no result within {timeout}s (window: '{title}'): {job}") time.sleep(0.5) try: proc.wait(timeout=exit_grace) return "exited" except subprocess.TimeoutExpired: title = _window_title(proc.pid) proc.kill() return f"killed after result (did not exit in {exit_grace}s, window: '{title}')" def run_job(steps, save=None, units_mm_tolerance=None, timeout=600, open_path=None, retries=1, exit_grace=20): \"\"\"Run `steps` in a fresh Rhino; return the result dict (raises RhinoJobError on failure). open_path: run the steps on that .3dm opened headless (reload test) instead of the empty active doc. timeout: seconds to wait for the result; a stalled launch is killed and retried `retries` times. \"\"\""""), (""" t0 = time.time() # Pass a raw command line: Rhino only honours /runscript="..." (quote after '='), while a list argument # would be quoted as a whole ("/runscript=...") and silently ignored. proc = subprocess.Popen(f'"{RHINO_EXE}" /nosplash /notemplate ' f'/runscript="_-RunPythonScript {job / "job.py"} _-Exit"') try: proc.wait(timeout=timeout) except subprocess.TimeoutExpired: proc.kill() raise RhinoJobError(f"Rhino job timed out after {timeout}s: {job}") rp = job / "result.json" if not rp.exists(): raise RhinoJobError(f"Rhino exited without a result: {job}") res = json.loads(rp.read_text(encoding="utf-8")) res["job_dir"], res["wall_secs"] = str(job), round(time.time() - t0, 1)""", """ t0, attempts = time.time(), [] for attempt in range(retries + 1): try: exit_note = _launch_and_wait(job, timeout, exit_grace) break except RhinoJobError as e: attempts.append(str(e)) if attempt == retries: raise RhinoJobError(" | ".join(attempts)) res = json.loads((job / "result.json").read_text(encoding="utf-8")) res["job_dir"], res["wall_secs"] = str(job), round(time.time() - t0, 1) res["rhino_exit"], res["failed_attempts"] = exit_note, attempts"""), ] for a, b in reps: assert s.count(a) == 1, a[:60] s = s.replace(a, b) p.write_text(s, encoding="utf-8") print("patched")