]> granicus.if.org Git - python/commitdiff
Issue #15595: Fix subprocess.Popen(universal_newlines=True)
authorAndrew Svetlov <andrew.svetlov@gmail.com>
Sun, 19 Aug 2012 19:13:41 +0000 (22:13 +0300)
committerAndrew Svetlov <andrew.svetlov@gmail.com>
Sun, 19 Aug 2012 19:13:41 +0000 (22:13 +0300)
for certain locales (utf-16 and utf-32 family).

Patch by Chris Jerdonek.

Lib/subprocess.py
Lib/test/test_subprocess.py
Misc/NEWS

index 179f41a85f56c82def6489d77e07f0dede23c66c..106af8b26194e03cb9ccd40466462fc6af089ea9 100644 (file)
@@ -755,8 +755,8 @@ class Popen(object):
 
 
     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
index 9e92a962277e5001b2fb24422be1a0249517bc3c..620cd8e5f35f14abdb4dc5d3205eef44eab67d36 100644 (file)
@@ -4,6 +4,7 @@ import subprocess
 import sys
 import signal
 import io
+import locale
 import os
 import errno
 import tempfile
@@ -560,6 +561,38 @@ class ProcessTestCase(BaseTestCase):
         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:
index 86b178b64c1b4b2d92be8483237bb8c62953a7cb..52e297c7805b45f9e426f5b26ec0f3ca15015a5d 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -104,6 +104,9 @@ Core and Builtins
 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.