[Python-checkins] cpython (3.2): Issue #15595: Fix subprocess.Popen(universal_newlines=True)

andrew.svetlov python-checkins at python.org
Sun Aug 19 21:20:17 CEST 2012


http://hg.python.org/cpython/rev/a0f7c2f79bce
changeset:   78655:a0f7c2f79bce
branch:      3.2
parent:      78648:f5e0561e9aa9
user:        Andrew Svetlov <andrew.svetlov at gmail.com>
date:        Sun Aug 19 22:13:41 2012 +0300
summary:
  Issue #15595: Fix subprocess.Popen(universal_newlines=True)
for certain locales (utf-16 and utf-32 family).

Patch by Chris Jerdonek.

files:
  Lib/subprocess.py           |   4 +-
  Lib/test/test_subprocess.py |  33 +++++++++++++++++++++++++
  Misc/NEWS                   |   3 ++
  3 files changed, 38 insertions(+), 2 deletions(-)


diff --git a/Lib/subprocess.py b/Lib/subprocess.py
--- a/Lib/subprocess.py
+++ b/Lib/subprocess.py
@@ -755,8 +755,8 @@
 
 
     def _translate_newlines(self, data, encoding):
-        data = data.replace(b"\r\n", b"\n").replace(b"\r", b"\n")
-        return data.decode(encoding)
+        data = data.decode(encoding)
+        return data.replace("\r\n", "\n").replace("\r", "\n")
 
     def __enter__(self):
         return self
diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py
--- a/Lib/test/test_subprocess.py
+++ b/Lib/test/test_subprocess.py
@@ -4,6 +4,7 @@
 import sys
 import signal
 import io
+import locale
 import os
 import errno
 import tempfile
@@ -560,6 +561,38 @@
         p.communicate()
         self.assertEqual(p.returncode, 0)
 
+    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.
+        # See issue #15595.
+        #
+        # UTF-16 and UTF-32-BE are sufficient to check both with BOM and
+        # without, and UTF-16 and UTF-32.
+        for encoding in ['utf-16', 'utf-32-be']:
+            old_getpreferredencoding = locale.getpreferredencoding
+            # Indirectly via io.TextIOWrapper, Popen() defaults to
+            # locale.getpreferredencoding(False) and earlier in Python 3.2 to
+            # locale.getpreferredencoding().
+            def getpreferredencoding(do_setlocale=True):
+                return encoding
+            code = ("import sys; "
+                    r"sys.stdout.buffer.write('1\r\n2\r3\n4'.encode('%s'))" %
+                    encoding)
+            args = [sys.executable, '-c', code]
+            try:
+                locale.getpreferredencoding = getpreferredencoding
+                # We set stdin to be non-None because, as of this writing,
+                # a different code path is used when the number of pipes is
+                # zero or one.
+                popen = subprocess.Popen(args, universal_newlines=True,
+                                         stdin=subprocess.PIPE,
+                                         stdout=subprocess.PIPE)
+                stdout, stderr = popen.communicate(input='')
+            finally:
+                locale.getpreferredencoding = old_getpreferredencoding
+
+            self.assertEqual(stdout, '1\n2\n3\n4')
+
     def test_no_leaking(self):
         # Make sure we leak no resources
         if not mswindows:
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -104,6 +104,9 @@
 Library
 -------
 
+- Issue #15595: Fix subprocess.Popen(universal_newlines=True)
+  for certain locales (utf-16 and utf-32 family). Patch by Chris Jerdonek.
+
 - Issue #15477: In cmath and math modules, add workaround for platforms whose
   system-supplied log1p function doesn't respect signs of zeros.
 

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list