Skip to content

Commit 83e0c74

Browse files
committed
run: refactor _handle_process_output()
Handle events selector and all lines of process output in this function. This also reduces the number of statements and branches in run_command().
1 parent 1119a19 commit 83e0c74

File tree

1 file changed

+40
-38
lines changed

1 file changed

+40
-38
lines changed

lib/rift/run.py

Lines changed: 40 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,30 @@
4545
'RunResult', ['returncode', 'out', 'err']
4646
)
4747

48-
def _handle_process_output(process, selector):
49-
"""Handle process output events with registered selectors."""
48+
def _handle_process_output(process, live_output, buf_out, buf_err):
49+
"""Handle process output until it is terminated."""
50+
51+
# Process output lines handlers
52+
def handle_stdout_line(line):
53+
buf_out.write(line)
54+
if live_output:
55+
sys.stdout.write(line)
56+
def handle_stderr_line(line):
57+
buf_err.write(line)
58+
if live_output:
59+
sys.stderr.write(line)
60+
61+
# Process output event handlers
62+
def handle_stdout_event(stream):
63+
handle_stdout_line(stream.readline())
64+
def handle_stderr_event(stream):
65+
handle_stderr_line(stream.readline())
66+
67+
# Register callback for read events from subprocess stdout/stderr streams
68+
selector = selectors.DefaultSelector()
69+
selector.register(process.stdout, selectors.EVENT_READ, handle_stdout_event)
70+
selector.register(process.stderr, selectors.EVENT_READ, handle_stderr_event)
71+
5072
# Loop until subprocess is terminated
5173
while process.poll() is None:
5274
# Wait for events and handle them with their registered callbacks
@@ -55,6 +77,19 @@ def _handle_process_output(process, selector):
5577
callback = key.data
5678
callback(key.fileobj)
5779

80+
# Close selector
81+
selector.close()
82+
83+
# The loop above stops processing output as soon as the process is
84+
# terminated. However, there may still be buffered output to flush.
85+
for line in process.stdout:
86+
handle_stdout_line(line)
87+
for line in process.stderr:
88+
handle_stderr_line(line)
89+
90+
# Ensure process is terminated
91+
process.wait()
92+
5893
def run_command(
5994
cmd,
6095
live_output=True,
@@ -105,43 +140,10 @@ def run_command(
105140
else:
106141
buf_err = io.StringIO()
107142

108-
# Process output lines handlers
109-
def handle_stdout(stream):
110-
line = stream.readline()
111-
buf_out.write(line)
112-
if live_output:
113-
sys.stdout.write(line)
114-
def handle_stderr(stream):
115-
line = stream.readline()
116-
buf_err.write(line)
117-
if live_output:
118-
sys.stderr.write(line)
119-
120-
# Register callback for read events from subprocess stdout/stderr streams
121-
selector = selectors.DefaultSelector()
122-
selector.register(process.stdout, selectors.EVENT_READ, handle_stdout)
123-
selector.register(process.stderr, selectors.EVENT_READ, handle_stderr)
124-
125-
# Handle process output with registered selectors
126-
_handle_process_output(process, selector)
127-
128-
# _handle_process_output stops processing output as soon as the process
129-
# is terminated. However, there may still be buffered output to flush.
130-
for line in process.stdout:
131-
buf_out.write(line)
132-
if live_output:
133-
sys.stdout.write(line)
134-
for line in process.stderr:
135-
buf_err.write(line)
136-
if live_output:
137-
sys.stdout.write(line)
138-
139-
# Ensure process is terminated
140-
process.wait()
141-
142-
# Store buffered output
143-
selector.close()
143+
# Handle process output
144+
_handle_process_output(process, live_output, buf_out, buf_err)
144145

146+
# Get values for out/err buffers and close them
145147
out = buf_out.getvalue()
146148
buf_out.close()
147149
if merge_out_err:

0 commit comments

Comments
 (0)