diff options
| author | Claude Paroz <claude@2xlibre.net> | 2015-11-04 21:50:16 +0100 |
|---|---|---|
| committer | Claude Paroz <claude@2xlibre.net> | 2015-11-19 15:17:47 +0100 |
| commit | fa08d27fb714534670b431fde0cd04a17d637585 (patch) | |
| tree | 2e72332507c5a343e1226e18c3ac4e60296ed8b2 /django | |
| parent | 58379d7e958fdf024f896b86f7df3415ce876200 (diff) | |
Fixed #25677 -- Prevented decoding errors in/after Popen calls
Thanks Gavin Wahl for the report and Tim Graham for the review.
Diffstat (limited to 'django')
| -rw-r--r-- | django/core/management/commands/makemessages.py | 31 | ||||
| -rw-r--r-- | django/core/management/utils.py | 12 |
2 files changed, 10 insertions, 33 deletions
diff --git a/django/core/management/commands/makemessages.py b/django/core/management/commands/makemessages.py index 866e325816..1fe17cad7f 100644 --- a/django/core/management/commands/makemessages.py +++ b/django/core/management/commands/makemessages.py @@ -16,7 +16,6 @@ from django.core.management.base import BaseCommand, CommandError from django.core.management.utils import ( find_command, handle_extensions, popen_wrapper, ) -from django.utils import six from django.utils._os import upath from django.utils.encoding import DEFAULT_LOCALE_ENCODING, force_str from django.utils.functional import cached_property @@ -35,26 +34,6 @@ def check_programs(*programs): "gettext tools 0.15 or newer installed." % program) -def gettext_popen_wrapper(args, os_err_exc_type=CommandError, stdout_encoding="utf-8"): - """ - Makes sure text obtained from stdout of gettext utilities is Unicode. - """ - # This both decodes utf-8 and cleans line endings. Simply using - # popen_wrapper(universal_newlines=True) doesn't properly handle the - # encoding. This goes back to popen's flaky support for encoding: - # https://bugs.python.org/issue6135. This is a solution for #23271, #21928. - # No need to do anything on Python 2 because it's already a byte-string there. - manual_io_wrapper = six.PY3 and stdout_encoding != DEFAULT_LOCALE_ENCODING - - stdout, stderr, status_code = popen_wrapper(args, os_err_exc_type=os_err_exc_type, - universal_newlines=not manual_io_wrapper) - if manual_io_wrapper: - stdout = io.TextIOWrapper(io.BytesIO(stdout), encoding=stdout_encoding).read() - if six.PY2: - stdout = stdout.decode(stdout_encoding) - return stdout, stderr, status_code - - @total_ordering class TranslatableFile(object): def __init__(self, dirpath, file_name, locale_dir): @@ -334,7 +313,7 @@ class Command(BaseCommand): def gettext_version(self): # Gettext tools will output system-encoded bytestrings instead of UTF-8, # when looking up the version. It's especially a problem on Windows. - out, err, status = gettext_popen_wrapper( + out, err, status = popen_wrapper( ['xgettext', '--version'], stdout_encoding=DEFAULT_LOCALE_ENCODING, ) @@ -357,7 +336,7 @@ class Command(BaseCommand): if not os.path.exists(potfile): continue args = ['msguniq'] + self.msguniq_options + [potfile] - msgs, errors, status = gettext_popen_wrapper(args) + msgs, errors, status = popen_wrapper(args) if errors: if status != STATUS_OK: raise CommandError( @@ -510,7 +489,7 @@ class Command(BaseCommand): input_files_list.flush() args.extend(['--files-from', input_files_list.name]) args.extend(self.xgettext_options) - msgs, errors, status = gettext_popen_wrapper(args) + msgs, errors, status = popen_wrapper(args) if errors: if status != STATUS_OK: @@ -553,7 +532,7 @@ class Command(BaseCommand): if os.path.exists(pofile): args = ['msgmerge'] + self.msgmerge_options + [pofile, potfile] - msgs, errors, status = gettext_popen_wrapper(args) + msgs, errors, status = popen_wrapper(args) if errors: if status != STATUS_OK: raise CommandError( @@ -572,7 +551,7 @@ class Command(BaseCommand): if self.no_obsolete: args = ['msgattrib'] + self.msgattrib_options + ['-o', pofile, pofile] - msgs, errors, status = gettext_popen_wrapper(args) + msgs, errors, status = popen_wrapper(args) if errors: if status != STATUS_OK: raise CommandError( diff --git a/django/core/management/utils.py b/django/core/management/utils.py index 53290e36d7..08efe11c87 100644 --- a/django/core/management/utils.py +++ b/django/core/management/utils.py @@ -10,24 +10,22 @@ from django.utils.encoding import DEFAULT_LOCALE_ENCODING, force_text from .base import CommandError -def popen_wrapper(args, os_err_exc_type=CommandError, universal_newlines=True): +def popen_wrapper(args, os_err_exc_type=CommandError, stdout_encoding='utf-8'): """ Friendly wrapper around Popen. Returns stdout output, stderr output and OS status code. """ try: - p = Popen(args, shell=False, stdout=PIPE, stderr=PIPE, - close_fds=os.name != 'nt', universal_newlines=universal_newlines) + p = Popen(args, shell=False, stdout=PIPE, stderr=PIPE, close_fds=os.name != 'nt') except OSError as e: - strerror = force_text(e.strerror, DEFAULT_LOCALE_ENCODING, - strings_only=True) + strerror = force_text(e.strerror, DEFAULT_LOCALE_ENCODING, strings_only=True) six.reraise(os_err_exc_type, os_err_exc_type('Error executing %s: %s' % (args[0], strerror)), sys.exc_info()[2]) output, errors = p.communicate() return ( - output, - force_text(errors, DEFAULT_LOCALE_ENCODING, strings_only=True), + force_text(output, stdout_encoding, strings_only=True, errors='strict'), + force_text(errors, DEFAULT_LOCALE_ENCODING, strings_only=True, errors='replace'), p.returncode ) |
