From 41239ab7d9f50419e59ad8f9d022571f31aecbfc Mon Sep 17 00:00:00 2001 From: Joshua Oreman Date: Sat, 19 Jan 2019 17:01:46 -0800 Subject: [PATCH] Add Process.stdio as a convenience StapledStream of stdin and stdout This is intended to make it more ergonomic to speak a back-and-forth protocol with a subprocess. --- newsfragments/862.feature.rst | 4 ++++ trio/_subprocess.py | 13 +++++++++++-- trio/tests/test_subprocess.py | 7 ++++--- 3 files changed, 19 insertions(+), 5 deletions(-) create mode 100644 newsfragments/862.feature.rst diff --git a/newsfragments/862.feature.rst b/newsfragments/862.feature.rst new file mode 100644 index 0000000000..81991208fe --- /dev/null +++ b/newsfragments/862.feature.rst @@ -0,0 +1,4 @@ +Add :attr:`trio.Process.stdio`, which is a :class:`~trio.StapledStream` of +:attr:`~trio.Process.stdin` and :attr:`~trio.Process.stdout` if both of those +are available, and ``None`` otherwise. This is intended to make it more +ergonomic to speak a back-and-forth protocol with a subprocess. diff --git a/trio/_subprocess.py b/trio/_subprocess.py index 41e93dcfe7..32dc786c21 100644 --- a/trio/_subprocess.py +++ b/trio/_subprocess.py @@ -6,8 +6,8 @@ from . import _core from ._abc import AsyncResource -from ._sync import CapacityLimiter, Lock -from ._threads import run_sync_in_worker_thread +from ._highlevel_generic import StapledStream +from ._sync import Lock from ._subprocess_platform import ( wait_child_exiting, create_pipe_to_child_stdin, create_pipe_from_child_output @@ -91,6 +91,10 @@ class Process(AsyncResource): standard error, the written bytes become available for you to read here. Only available if the :class:`Process` was constructed using ``stderr=PIPE``; otherwise this will be None. + stdio (trio.StapledStream or None): A stream that sends data to + the child's standard input and receives from the child's standard + output. Only available if both :attr:`stdin` and :attr:`stdout` are + available; otherwise this will be None. """ @@ -152,6 +156,11 @@ def __init__( if self.stderr is not None: os.close(stderr) + if self.stdin is not None and self.stdout is not None: + self.stdio = StapledStream(self.stdin, self.stdout) + else: + self.stdio = None + self.args = self._proc.args self.pid = self._proc.pid diff --git a/trio/tests/test_subprocess.py b/trio/tests/test_subprocess.py index 9a5880336c..071b95b15f 100644 --- a/trio/tests/test_subprocess.py +++ b/trio/tests/test_subprocess.py @@ -175,12 +175,12 @@ async def test_stderr_stdout(): ) as proc: assert proc.stdout is not None assert proc.stderr is None - await proc.stdin.send_all(b"1234") - await proc.stdin.aclose() + await proc.stdio.send_all(b"1234") + await proc.stdio.send_eof() output = [] while True: - chunk = await proc.stdout.receive_some(16) + chunk = await proc.stdio.receive_some(16) if chunk == b"": break output.append(chunk) @@ -208,6 +208,7 @@ async def test_stderr_stdout(): stderr=subprocess.STDOUT, ) as proc: os.close(w) + assert proc.stdio is None assert proc.stdout is None assert proc.stderr is None await proc.stdin.send_all(b"1234")