diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2013-02-04 14:47:39 (GMT) |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2013-02-04 14:47:39 (GMT) |
commit | b3f194d10951d5c23af885c6d55c45dfb0db0666 (patch) | |
tree | aa40c095d34ff160840f755604fb389f88487940 | |
parent | 0b4591e0eb80b78b4c6a4aa6a4071c74c253bde7 (diff) | |
download | cpython-b3f194d10951d5c23af885c6d55c45dfb0db0666.zip cpython-b3f194d10951d5c23af885c6d55c45dfb0db0666.tar.gz cpython-b3f194d10951d5c23af885c6d55c45dfb0db0666.tar.bz2 |
Issue #16903: Popen.communicate() on Unix now accepts strings when
universal_newlines is true as on Windows.
-rw-r--r-- | Doc/library/subprocess.rst | 7 | ||||
-rw-r--r-- | Lib/subprocess.py | 4 | ||||
-rw-r--r-- | Lib/test/test_subprocess.py | 31 | ||||
-rw-r--r-- | Misc/NEWS | 3 |
4 files changed, 40 insertions, 5 deletions
diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index fc456a1..b4adc02 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -537,9 +537,10 @@ Instances of the :class:`Popen` class have the following methods: .. method:: Popen.communicate(input=None) 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 - *input* argument should be a byte string to be sent to the child process, or - ``None``, if no data should be sent to the child. + until end-of-file is reached. Wait for process to terminate. The optional + *input* argument should be data to be sent to the child process, or + ``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)``. diff --git a/Lib/subprocess.py b/Lib/subprocess.py index f32f081e..1a21455 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -1519,6 +1519,8 @@ class Popen(object): fd2output[self.stderr.fileno()] = stderr = [] input_offset = 0 + if self.universal_newlines and isinstance(input, str): + input = input.encode(self.stdin.encoding) while fd2file: try: ready = poller.poll() @@ -1571,6 +1573,8 @@ class Popen(object): stderr = [] input_offset = 0 + if self.universal_newlines and isinstance(input, str): + input = input.encode(self.stdin.encoding) while read_set or write_set: try: rlist, wlist, xlist = select.select(read_set, write_set, []) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 921328f..45ba373 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -608,8 +608,6 @@ class ProcessTestCase(BaseTestCase): universal_newlines=1) self.addCleanup(p.stdout.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() self.assertEqual(stdout, "line2\nline4\nline5\nline6\nline7\nline8") @@ -640,6 +638,35 @@ class ProcessTestCase(BaseTestCase): p.communicate() 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): # Check that universal newlines mode works for various encodings, # in particular for encodings in the UTF-16 and UTF-32 families. @@ -212,6 +212,9 @@ Core and Builtins 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 parses nested mutating sequence. |