Skip to content

Commit 76705d9

Browse files
committed
Fix subprocess.run() wrapper in tests
tests/test_child_procs.py::_run_subproc() - If any of the output streams is captured, we call `subprocess.run(..., check=False)` to get the chance to intercept and print the output, and only call `.check_returncode()` on the `CompletedProcess` afterwards - Fixed bug where if `text=False` we attempt to format the captured stream-content bytes as strings
1 parent fa9f0f3 commit 76705d9

1 file changed

Lines changed: 18 additions & 1 deletion

File tree

tests/test_child_procs.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,7 @@ def _run_subproc(
486486
cmd: Sequence[str] | str,
487487
/,
488488
*args,
489+
check: bool = False,
489490
env: Mapping[str, str] | None = None,
490491
**kwargs
491492
) -> subprocess.CompletedProcess:
@@ -497,6 +498,16 @@ def _run_subproc(
497498
cmd_str = cmd
498499
else:
499500
cmd_str = shlex.join(cmd)
501+
502+
# If we're capturing outputs, it may be for the best to wait until
503+
# we've processed the output streams to check the return code...
504+
check_rc_in_run = check
505+
for arg in 'stdout', 'stdin':
506+
if kwargs.get(arg) not in {None, subprocess.DEVNULL}:
507+
check_rc_in_run = False
508+
if kwargs.get('capture_output'):
509+
check_rc_in_run = False
510+
500511
print('Command:', cmd_str)
501512
if env is not None:
502513
diff: list[str] = []
@@ -522,23 +533,29 @@ def _run_subproc(
522533
time = monotonic()
523534
try:
524535
proc = subprocess.run( # type: ignore[call-overload]
525-
cmd, *args, env=env, **kwargs,
536+
cmd, *args, env=env, check=check_rc_in_run, **kwargs,
526537
)
527538
except Exception:
528539
status = 'error'
529540
raise
530541
else:
542+
assert proc is not None
543+
if check and not check_rc_in_run: # Perform missing check
544+
proc.check_returncode()
531545
status = proc.returncode
532546
return proc
533547
finally:
534548
time = monotonic() - time
535549
if proc is not None:
550+
captured: str | bytes | None
536551
for name, captured, stream in [
537552
('stdout', proc.stdout, sys.stdout),
538553
('stderr', proc.stderr, sys.stderr),
539554
]:
540555
if captured is None:
541556
continue
557+
if isinstance(captured, bytes): # `text=False`
558+
captured = captured.decode()
542559
print(f'{name}:\n{indent(captured, " ")}', file=stream)
543560
print(
544561
f'-- Process end (time elapsed: {time:.2f} s / '

0 commit comments

Comments
 (0)