mirror of
https://github.com/python/cpython.git
synced 2025-12-04 16:43:27 +00:00
Issue #16903: Popen.communicate() on Unix now accepts strings when
universal_newlines is true as on Windows.
This commit is contained in:
parent
0b4591e0eb
commit
b3f194d109
4 changed files with 40 additions and 5 deletions
|
|
@ -538,8 +538,9 @@ Instances of the :class:`Popen` class have the following methods:
|
||||||
|
|
||||||
Interact with process: Send data to stdin. Read data from stdout and stderr,
|
Interact with process: Send data to stdin. Read data from stdout and stderr,
|
||||||
until end-of-file is reached. Wait for process to terminate. The optional
|
until end-of-file is reached. Wait for process to terminate. The optional
|
||||||
*input* argument should be a byte string to be sent to the child process, or
|
*input* argument should be data to be sent to the child process, or
|
||||||
``None``, if no data should be sent to the child.
|
``None``, if no data should be sent to the child. The type of *input*
|
||||||
|
must be bytes or, if *universal_newlines* was ``True``, a string.
|
||||||
|
|
||||||
:meth:`communicate` returns a tuple ``(stdoutdata, stderrdata)``.
|
:meth:`communicate` returns a tuple ``(stdoutdata, stderrdata)``.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1519,6 +1519,8 @@ class Popen(object):
|
||||||
fd2output[self.stderr.fileno()] = stderr = []
|
fd2output[self.stderr.fileno()] = stderr = []
|
||||||
|
|
||||||
input_offset = 0
|
input_offset = 0
|
||||||
|
if self.universal_newlines and isinstance(input, str):
|
||||||
|
input = input.encode(self.stdin.encoding)
|
||||||
while fd2file:
|
while fd2file:
|
||||||
try:
|
try:
|
||||||
ready = poller.poll()
|
ready = poller.poll()
|
||||||
|
|
@ -1571,6 +1573,8 @@ class Popen(object):
|
||||||
stderr = []
|
stderr = []
|
||||||
|
|
||||||
input_offset = 0
|
input_offset = 0
|
||||||
|
if self.universal_newlines and isinstance(input, str):
|
||||||
|
input = input.encode(self.stdin.encoding)
|
||||||
while read_set or write_set:
|
while read_set or write_set:
|
||||||
try:
|
try:
|
||||||
rlist, wlist, xlist = select.select(read_set, write_set, [])
|
rlist, wlist, xlist = select.select(read_set, write_set, [])
|
||||||
|
|
|
||||||
|
|
@ -608,8 +608,6 @@ class ProcessTestCase(BaseTestCase):
|
||||||
universal_newlines=1)
|
universal_newlines=1)
|
||||||
self.addCleanup(p.stdout.close)
|
self.addCleanup(p.stdout.close)
|
||||||
self.addCleanup(p.stderr.close)
|
self.addCleanup(p.stderr.close)
|
||||||
# BUG: can't give a non-empty stdin because it breaks both the
|
|
||||||
# select- and poll-based communicate() implementations.
|
|
||||||
(stdout, stderr) = p.communicate()
|
(stdout, stderr) = p.communicate()
|
||||||
self.assertEqual(stdout,
|
self.assertEqual(stdout,
|
||||||
"line2\nline4\nline5\nline6\nline7\nline8")
|
"line2\nline4\nline5\nline6\nline7\nline8")
|
||||||
|
|
@ -640,6 +638,35 @@ class ProcessTestCase(BaseTestCase):
|
||||||
p.communicate()
|
p.communicate()
|
||||||
self.assertEqual(p.returncode, 0)
|
self.assertEqual(p.returncode, 0)
|
||||||
|
|
||||||
|
def test_universal_newlines_communicate_stdin_stdout_stderr(self):
|
||||||
|
# universal newlines through communicate(), with stdin, stdout, stderr
|
||||||
|
p = subprocess.Popen([sys.executable, "-c",
|
||||||
|
'import sys,os;' + SETBINARY + '''\nif True:
|
||||||
|
s = sys.stdin.buffer.readline()
|
||||||
|
sys.stdout.buffer.write(s)
|
||||||
|
sys.stdout.buffer.write(b"line2\\r")
|
||||||
|
sys.stderr.buffer.write(b"eline2\\n")
|
||||||
|
s = sys.stdin.buffer.read()
|
||||||
|
sys.stdout.buffer.write(s)
|
||||||
|
sys.stdout.buffer.write(b"line4\\n")
|
||||||
|
sys.stdout.buffer.write(b"line5\\r\\n")
|
||||||
|
sys.stderr.buffer.write(b"eline6\\r")
|
||||||
|
sys.stderr.buffer.write(b"eline7\\r\\nz")
|
||||||
|
'''],
|
||||||
|
stdin=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
universal_newlines=True)
|
||||||
|
self.addCleanup(p.stdout.close)
|
||||||
|
self.addCleanup(p.stderr.close)
|
||||||
|
(stdout, stderr) = p.communicate("line1\nline3\n")
|
||||||
|
self.assertEqual(p.returncode, 0)
|
||||||
|
self.assertEqual("line1\nline2\nline3\nline4\nline5\n", stdout)
|
||||||
|
# Python debug build push something like "[42442 refs]\n"
|
||||||
|
# to stderr at exit of subprocess.
|
||||||
|
# Don't use assertStderrEqual because it strips CR and LF from output.
|
||||||
|
self.assertTrue(stderr.startswith("eline2\neline6\neline7\n"))
|
||||||
|
|
||||||
def test_universal_newlines_communicate_encodings(self):
|
def test_universal_newlines_communicate_encodings(self):
|
||||||
# Check that universal newlines mode works for various encodings,
|
# Check that universal newlines mode works for various encodings,
|
||||||
# in particular for encodings in the UTF-16 and UTF-32 families.
|
# in particular for encodings in the UTF-16 and UTF-32 families.
|
||||||
|
|
|
||||||
|
|
@ -212,6 +212,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #16903: Popen.communicate() on Unix now accepts strings when
|
||||||
|
universal_newlines is true as on Windows.
|
||||||
|
|
||||||
- Issue #6083: Fix multiple segmentation faults occured when PyArg_ParseTuple
|
- Issue #6083: Fix multiple segmentation faults occured when PyArg_ParseTuple
|
||||||
parses nested mutating sequence.
|
parses nested mutating sequence.
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue