Clarify eg-wrap contract + tighten `stdout` typing

Doc/type accuracy in `supervise_run_process()`:

- the docstring claimed the rc!=0 `CalledProcessError` had
  "no nursery-eg-wrapped CPE to catch/`collapse_eg`", but it
  IS raised as a task into the parent `tn`, so under
  `trio>=0.33` it surfaces `ExceptionGroup`-wrapped like any
  `tn.start()`-task raise. Say so + point at `except*` /
  `collapse_eg()` (matching the inline rc-check comment).
- widen `stdout: int` to `int|None` — the param accepts an
  explicit `None` (inherit) per its own docstring.
- note that stdout is NOT captured, so the CPE note carries
  only stderr (a cmd logging errors to stdout should
  `relay_stdout=True`).

Review: PR #465 (copilot-pull-request-reviewer)
https://github.com/goodboy/tractor/pull/465#pullrequestreview-4548191641

(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
wkt/start_or_cancel_tests_474
Gud Boi 2026-06-24 19:09:45 -04:00
parent 02cb789901
commit 6764251e6b
1 changed files with 13 additions and 6 deletions

View File

@ -160,7 +160,7 @@ async def supervise_run_process(
# non-relay `stdout` override; defaults (via `_UNSET`) to # non-relay `stdout` override; defaults (via `_UNSET`) to
# `DEVNULL` so we NEVER inherit (+ thus can't clobber) the # `DEVNULL` so we NEVER inherit (+ thus can't clobber) the
# parent controlling-tty. # parent controlling-tty.
stdout: int = _UNSET, stdout: int|None = _UNSET,
task_status: trio.TaskStatus[ task_status: trio.TaskStatus[
trio.Process trio.Process
@ -178,11 +178,14 @@ async def supervise_run_process(
- surfaces a rc!=0 `subprocess.CalledProcessError` - surfaces a rc!=0 `subprocess.CalledProcessError`
DETERMINISTICALLY: we pass `check=False` to `trio` and DETERMINISTICALLY: we pass `check=False` to `trio` and
do our OWN post-drain rc-check, (re)building + raising a do our OWN post-drain rc-check, (re)building + raising the
BARE CPE (with a `.stderr` note) from this coro's body CPE (with a `.stderr` note) from this coro's body AFTER the
AFTER the child exits so there's no nursery-eg-wrapped child exits so it's never wrapped by `trio.run_process`'s
CPE to catch/`collapse_eg`, and the relay reader is never INTERNAL nursery nor race-cancelled mid-drain. It IS still
race-cancelled mid-drain. raised as a task into the *parent* `tn`, so like any
`tn.start()`-task raise it surfaces `ExceptionGroup`-
wrapped under `trio>=0.33`; unwrap via `except*` or
`trionics.collapse_eg()`.
- ALWAYS isolates the parent controlling-tty - ALWAYS isolates the parent controlling-tty
(`stdin=DEVNULL`, and `stdout=DEVNULL` unless (`stdin=DEVNULL`, and `stdout=DEVNULL` unless
@ -339,6 +342,10 @@ async def supervise_run_process(
if stderr_accum is not None if stderr_accum is not None
else b'' else b''
) )
# NOTE: stdout is NOT captured (DEVNULL unless overridden)
# so the CPE carries only (tail-bounded) stderr; a cmd that
# logs failures to *stdout* should `relay_stdout=True` to
# surface them in the note.
cpe = subprocess.CalledProcessError( cpe = subprocess.CalledProcessError(
returncode=trio_proc.returncode, returncode=trio_proc.returncode,
cmd=trio_proc.args, cmd=trio_proc.args,