From ca48d33d1615f23261302551e8e457eac7d740b3 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Wed, 10 Jun 2026 19:53:44 -0400 Subject: [PATCH] docs(simulations): update live_gui fixture signature to _LiveGuiHandle The live_gui fixture in tests/conftest.py:467 now yields a _LiveGuiHandle object (not a tuple). The handle exposes: - .process, .gui_script, .workspace (Path to per-run workspace) - .is_alive(), .ensure_alive(), .respawn_count - __iter__ and __getitem__ for backward-compatible tuple unpacking Also document the xdist O_EXCL file-lock coordination pattern and the PYTEST_XDIST_WORKER env var owner/client role split. --- docs/guide_simulations.md | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/docs/guide_simulations.md b/docs/guide_simulations.md index d79bc41c..fe5f5dc3 100644 --- a/docs/guide_simulations.md +++ b/docs/guide_simulations.md @@ -28,12 +28,14 @@ Defined in `tests/conftest.py`, this session-scoped fixture manages the lifecycl ```python @pytest.fixture(scope="session") -def live_gui() -> Generator[tuple[subprocess.Popen, str], None, None]: +def live_gui(request) -> Generator["_LiveGuiHandle", None, None]: process = subprocess.Popen( ["uv", "run", "python", "-u", gui_script, "--enable-test-hooks"], stdout=log_file, stderr=log_file, text=True, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP if os.name == 'nt' else 0 ) + # ... (readiness polling + xdist coordination) ... + yield _LiveGuiHandle(process, gui_script, workspace=temp_workspace) ``` - **`-u` flag**: Disables output buffering for real-time log capture. @@ -69,7 +71,20 @@ finally: Sends `reset_session()` via `ApiHookClient` before killing to prevent stale state files. -**Yield value:** `(process: subprocess.Popen, gui_script: str)`. +**Yield value:** A `_LiveGuiHandle` object (defined in `tests/conftest.py:416-465`): + +| Property | Type | Purpose | +|---|---|---| +| `.process` | `subprocess.Popen` | The sloppy.py subprocess. | +| `.gui_script` | `str` | Absolute path to `sloppy.py` that was launched. | +| `.workspace` | `Path` | Absolute path to the per-run workspace under `tests/artifacts/live_gui_workspace_/`. | +| `.is_alive()` | `() -> bool` | True if the subprocess is still running. | +| `.ensure_alive()` | `() -> None` | Stub — increments `respawn_count` if dead; full respawn is between test sessions. | +| `.respawn_count` | `int` | Diagnostic counter for subprocess deaths. | + +**Backward compatibility:** The handle supports tuple unpacking (`process, gui_script = handle`) via `__iter__`, and indexing (`handle[0]` = process, `handle[1]` = gui_script) via `__getitem__`. Tests written against the old tuple-yielding fixture still work without modification. + +**Xdist coordination:** The fixture uses an `O_EXCL`-atomic file lock at `tests/artifacts/live_gui_workspace_*/.live_gui_owner.lock`. The first xdist worker to acquire it spawns the subprocess; other workers wait and yield a null handle (`process=None`). Worker ID is read from `PYTEST_XDIST_WORKER`. ### Session Isolation