hopfule fix

This commit is contained in:
Anthony Scopatz 2016-10-26 00:40:47 -04:00
parent 7ceb158154
commit 6288644fe5
4 changed files with 27 additions and 8 deletions

View file

@ -51,6 +51,6 @@
* Added a minimum time buffer time for command pipelines to check for
if previous commands have executed successfully. This is helpful
for pipelines where the last command takes a long time to start up,
such as GNU Parallel.
such as GNU Parallel. This also checks to make sure that output has occured.
**Security:** None

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python
import sys
with open(sys.argv[0]) as f:
with open(sys.argv[-1]) as f:
for line in f:
print(line, end='')

View file

@ -137,8 +137,8 @@ g
with open('tttt', 'w') as fp:
fp.write("Wow mom!\\n")
cat tttt | wc
""", " 1 2 9 <stdin>", 0),
![cat tttt | wc]
""", " 1 2 9 <stdin>\n", 0),
]
@ -152,7 +152,7 @@ def test_script(case):
@skip_if_on_windows
@pytest.mark.parametrize('cmd, fmt, exp', [
('pwd', None, os.getcwd() + '\n'),
('pwd', None, lambda: os.getcwd() + '\n'),
('echo WORKING', None, 'WORKING\n'),
('ls -f', lambda out: out.splitlines().sort(), os.listdir().sort()),
])
@ -163,17 +163,21 @@ def test_single_command(cmd, fmt, exp):
out, err, rtn = run_xonsh(cmd, stderr=sp.DEVNULL)
if callable(fmt):
out = fmt(out)
if callable(exp):
exp = exp()
assert out == exp
assert rtn == 0
@skip_if_on_windows
@pytest.mark.parametrize('cmd, exp', [
('pwd', os.getcwd() + '\n'),
('pwd', lambda: os.getcwd() + '\n'),
])
def test_redirect_out_to_file(cmd, exp, tmpdir):
outfile = tmpdir.mkdir('xonsh_test_dir').join('xonsh_test_file')
command = '{} > {}'.format(cmd, outfile)
out, _, _ = run_xonsh(command)
content = outfile.read()
if callable(exp):
exp = exp()
assert content == exp

View file

@ -1484,6 +1484,7 @@ class CommandPipeline:
stderr = NonBlockingFDReader(stderr.fileno(), timeout=timeout)
# read from process while it is running
check_prev_done = len(self.procs) == 1
prev_end_time = None
while proc.poll() is None:
if getattr(proc, 'suspended', False):
return
@ -1504,8 +1505,22 @@ class CommandPipeline:
yield from stdout_lines
stderr_lines = safe_readlines(stderr, 1024)
self.stream_stderr(stderr_lines)
if not check_prev_done and (stdout_lines or stderr_lines):
check_prev_done = True
if not check_prev_done:
# if we are piping...
if (stdout_lines or stderr_lines):
# see if we have some output.
check_prev_done = True
elif prev_end_time is None:
# or see if we already know that the next-to-last
# proc in teh pipeline has ended.
if self.procs[-2].poll() is not None:
# if it has, record the time
prev_end_time = time.time()
elif time.time() - prev_end_time >= 0.1:
# if we still don't have any output, even though the
# next-to-last proc has finished, wait a bit to make
# sure we have fully started up, etc.
check_prev_done = True
time.sleep(timeout)
# read from process now that it is over
yield from safe_readlines(stdout)