Private
Public Access
0
0

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.
This commit is contained in:
2026-06-10 19:53:44 -04:00
parent c501035609
commit ca48d33d16
+17 -2
View File
@@ -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_<timestamp>/`. |
| `.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