Commit 6481a14d authored by Jason Madden's avatar Jason Madden

Fix subprocess doctests under py3; fix raising the right exception if a child...

Fix subprocess doctests under py3; fix raising the right exception if a child fails to exec under py2
parent 0768732f
...@@ -9,6 +9,7 @@ import traceback ...@@ -9,6 +9,7 @@ import traceback
from gevent.event import AsyncResult from gevent.event import AsyncResult
from gevent.hub import get_hub, linkproxy, sleep, getcurrent, integer_types, string_types, xrange from gevent.hub import get_hub, linkproxy, sleep, getcurrent, integer_types, string_types, xrange
from gevent.hub import PY3 from gevent.hub import PY3
from gevent.hub import reraise
from gevent.fileobject import FileObject from gevent.fileobject import FileObject
from gevent.greenlet import Greenlet, joinall from gevent.greenlet import Greenlet, joinall
spawn = Greenlet.spawn spawn = Greenlet.spawn
...@@ -164,14 +165,17 @@ if PY3: ...@@ -164,14 +165,17 @@ if PY3:
CalledProcessError object will have the return code in the returncode CalledProcessError object will have the return code in the returncode
attribute and output in the output attribute. attribute and output in the output attribute.
The arguments are the same as for the Popen constructor. Example: The arguments are the same as for the Popen constructor. Example:
>>> check_output(["ls", "-l", "/dev/null"]) >>> check_output(["ls", "-1", "/dev/null"])
b'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n' b'/dev/null\n'
The stdout argument is not allowed as it is used internally. The stdout argument is not allowed as it is used internally.
To capture standard error in the result, use stderr=STDOUT. To capture standard error in the result, use stderr=STDOUT.
>>> check_output(["/bin/sh", "-c", >>> check_output(["/bin/sh", "-c",
... "ls -l non_existent_file ; exit 0"], ... "ls -l non_existent_file ; exit 0"],
... stderr=STDOUT) ... stderr=STDOUT)
b'ls: non_existent_file: No such file or directory\n' b'ls: non_existent_file: No such file or directory\n'
There is an additional optional argument, "input", allowing you to There is an additional optional argument, "input", allowing you to
pass a string to the subprocess's stdin. If you use this argument pass a string to the subprocess's stdin. If you use this argument
you may not also use the Popen constructor's "stdin" argument, as you may not also use the Popen constructor's "stdin" argument, as
...@@ -179,6 +183,7 @@ if PY3: ...@@ -179,6 +183,7 @@ if PY3:
>>> check_output(["sed", "-e", "s/foo/bar/"], >>> check_output(["sed", "-e", "s/foo/bar/"],
... input=b"when in the course of fooman events\n") ... input=b"when in the course of fooman events\n")
b'when in the course of barman events\n' b'when in the course of barman events\n'
If universal_newlines=True is passed, the return value will be a If universal_newlines=True is passed, the return value will be a
string rather than bytes. string rather than bytes.
""" """
...@@ -321,7 +326,6 @@ class Popen(object): ...@@ -321,7 +326,6 @@ class Popen(object):
# We wrap OS handles *before* launching the child, otherwise a # We wrap OS handles *before* launching the child, otherwise a
# quickly terminating child could make our fds unwrappable # quickly terminating child could make our fds unwrappable
# (see #8458). # (see #8458).
if mswindows: if mswindows:
if p2cwrite is not None: if p2cwrite is not None:
p2cwrite = msvcrt.open_osfhandle(p2cwrite.Detach(), 0) p2cwrite = msvcrt.open_osfhandle(p2cwrite.Detach(), 0)
...@@ -361,7 +365,9 @@ class Popen(object): ...@@ -361,7 +365,9 @@ class Popen(object):
# Cleanup if the child failed starting. # Cleanup if the child failed starting.
# (gevent: New in python3, but reported as gevent bug in #347. # (gevent: New in python3, but reported as gevent bug in #347.
# Note that under Py2, any error raised below will replace the # Note that under Py2, any error raised below will replace the
# original error. This could be worked around using hub.reraise) # original error so we have to use reraise)
if not PY3:
exc_info = sys.exc_info()
for f in filter(None, (self.stdin, self.stdout, self.stderr)): for f in filter(None, (self.stdin, self.stdout, self.stderr)):
try: try:
f.close() f.close()
...@@ -383,7 +389,11 @@ class Popen(object): ...@@ -383,7 +389,11 @@ class Popen(object):
os.close(fd) os.close(fd)
except OSError: except OSError:
pass pass
if not PY3:
try:
reraise(*exc_info)
finally:
del exc_info
raise raise
def __repr__(self): def __repr__(self):
......
...@@ -45,9 +45,9 @@ if __name__ == '__main__': ...@@ -45,9 +45,9 @@ if __name__ == '__main__':
tests_count = 0 tests_count = 0
modules_count = 0 modules_count = 0
for m, path in sorted(modules): for m, path in sorted(modules):
with open(path, 'r') as f: with open(path, 'rb') as f:
contents = f.read() contents = f.read()
if re.search(r'^\s*>>> ', contents, re.M): if re.search(br'^\s*>>> ', contents, re.M):
try: try:
s = doctest.DocTestSuite(m, extraglobs=globs) s = doctest.DocTestSuite(m, extraglobs=globs)
test_count = len(s._tests) # pylint: disable=W0212 test_count = len(s._tests) # pylint: disable=W0212
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment