fix(host): enforce flush=True to prevent pipeline block buffering
This commit is contained in:
parent
27a905c22b
commit
005d2d8458
4 changed files with 41 additions and 4 deletions
|
|
@ -46,7 +46,7 @@ def run_command(
|
||||||
if on_stderr is not None:
|
if on_stderr is not None:
|
||||||
on_stderr(line)
|
on_stderr(line)
|
||||||
if passthrough:
|
if passthrough:
|
||||||
print(line, file=sys.stderr)
|
print(line, file=sys.stderr, flush=True)
|
||||||
|
|
||||||
def terminate_process() -> None:
|
def terminate_process() -> None:
|
||||||
emit_stderr_message("cancellation requested; terminating subprocess")
|
emit_stderr_message("cancellation requested; terminating subprocess")
|
||||||
|
|
@ -82,7 +82,7 @@ def run_command(
|
||||||
if callback is not None:
|
if callback is not None:
|
||||||
callback(line)
|
callback(line)
|
||||||
if passthrough:
|
if passthrough:
|
||||||
print(line, file=output_stream)
|
print(line, file=output_stream, flush=True)
|
||||||
stream.close()
|
stream.close()
|
||||||
|
|
||||||
stdout_thread = threading.Thread(
|
stdout_thread = threading.Thread(
|
||||||
|
|
|
||||||
|
|
@ -47,3 +47,21 @@ def test_cancelled_command_raises_cancelled_error() -> None:
|
||||||
def test_run_command_avoids_runtime_unsafe_nested_annotations() -> None:
|
def test_run_command_avoids_runtime_unsafe_nested_annotations() -> None:
|
||||||
source = inspect.getsource(run_command)
|
source = inspect.getsource(run_command)
|
||||||
assert "subprocess.Popen[str].stdout" not in source
|
assert "subprocess.Popen[str].stdout" not in source
|
||||||
|
|
||||||
|
|
||||||
|
def test_run_command_passthrough_writes_to_sys_streams(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||||
|
import sys
|
||||||
|
from io import StringIO
|
||||||
|
|
||||||
|
mock_stdout = StringIO()
|
||||||
|
mock_stderr = StringIO()
|
||||||
|
monkeypatch.setattr(sys, "stdout", mock_stdout)
|
||||||
|
monkeypatch.setattr(sys, "stderr", mock_stderr)
|
||||||
|
|
||||||
|
run_command(
|
||||||
|
["python3", "-c", "import sys; print('passed out'); print('passed err', file=sys.stderr)"],
|
||||||
|
passthrough=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert mock_stdout.getvalue() == "passed out\n"
|
||||||
|
assert mock_stderr.getvalue() == "passed err\n"
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ def run_command(
|
||||||
if on_stderr is not None:
|
if on_stderr is not None:
|
||||||
on_stderr(line)
|
on_stderr(line)
|
||||||
if passthrough:
|
if passthrough:
|
||||||
print(line, file=sys.stderr)
|
print(line, file=sys.stderr, flush=True)
|
||||||
|
|
||||||
def terminate_process() -> None:
|
def terminate_process() -> None:
|
||||||
emit_stderr_message("cancellation requested; terminating subprocess")
|
emit_stderr_message("cancellation requested; terminating subprocess")
|
||||||
|
|
@ -86,7 +86,7 @@ def run_command(
|
||||||
if callback is not None:
|
if callback is not None:
|
||||||
callback(line)
|
callback(line)
|
||||||
if passthrough:
|
if passthrough:
|
||||||
print(line, file=output_stream)
|
print(line, file=output_stream, flush=True)
|
||||||
stream.close()
|
stream.close()
|
||||||
|
|
||||||
stdout_thread = threading.Thread(
|
stdout_thread = threading.Thread(
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,25 @@
|
||||||
|
import sys
|
||||||
|
from io import StringIO
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
def test_run_command_passthrough_writes_to_sys_streams(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||||
|
from l4d2web.services.host_commands import run_command
|
||||||
|
|
||||||
|
mock_stdout = StringIO()
|
||||||
|
mock_stderr = StringIO()
|
||||||
|
monkeypatch.setattr(sys, "stdout", mock_stdout)
|
||||||
|
monkeypatch.setattr(sys, "stderr", mock_stderr)
|
||||||
|
|
||||||
|
run_command(
|
||||||
|
["python3", "-c", "import sys; print('passed out'); print('passed err', file=sys.stderr)"],
|
||||||
|
passthrough=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert mock_stdout.getvalue() == "passed out\n"
|
||||||
|
assert mock_stderr.getvalue() == "passed err\n"
|
||||||
|
|
||||||
|
|
||||||
def test_run_command_streams_stdout_and_stderr_callbacks() -> None:
|
def test_run_command_streams_stdout_and_stderr_callbacks() -> None:
|
||||||
from l4d2web.services.host_commands import run_command
|
from l4d2web.services.host_commands import run_command
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue