From 6ab0d1358fc78077064aab88a4fb0a47ca116391 Mon Sep 17 00:00:00 2001 From: Ramiro Morales Date: Mon, 23 May 2016 22:43:55 -0300 Subject: [PATCH] Fixed #26645 -- Fixed potential makemessages failures on Windows. This was reflected by 27 i18n test errors (not failures) on such platform caused by corrupt intermediate PO catalog files fed to `msgmerge(1)`. Made it handle in-memory PO/POT file contents with normalized line separators (`'\n'`). We need to perform manually this after using `subprocess.Popen` as we can't pass it `universal_newlines=True`. Also fixes #26670 in the process as this commit refactors the same code section. --- .../core/management/commands/makemessages.py | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/django/core/management/commands/makemessages.py b/django/core/management/commands/makemessages.py index 2b47c81bf75..c0f9d58f9dd 100644 --- a/django/core/management/commands/makemessages.py +++ b/django/core/management/commands/makemessages.py @@ -153,16 +153,41 @@ class BuildFile(object): os.unlink(self.work_path) +def normalize_eols(raw_contents): + """ + Take a block of raw text that will be passed through str.splitlines() to + get universal newlines treatment. + + Return the resulting block of text with normalized `\n` EOL sequences ready + to be written to disk using current platform's native EOLs. + """ + lines_list = raw_contents.splitlines() + # Ensure last line has its EOL + if lines_list and lines_list[-1]: + lines_list.append('') + return '\n'.join(lines_list) + + def write_pot_file(potfile, msgs): """ Write the :param potfile: POT file with the :param msgs: contents, previously making sure its format is valid. """ + pot_lines = msgs.splitlines() if os.path.exists(potfile): # Strip the header - msgs = '\n'.join(dropwhile(len, msgs.split('\n'))) + lines = dropwhile(len, pot_lines) else: - msgs = msgs.replace('charset=CHARSET', 'charset=UTF-8') + lines = [] + found, header_read = False, False + for line in pot_lines: + if not found and not header_read: + found = True + line = line.replace('charset=CHARSET', 'charset=UTF-8') + if not line and not found: + header_read = True + lines.append(line) + msgs = '\n'.join(lines) with io.open(potfile, 'a', encoding='utf-8') as fp: fp.write(msgs) @@ -379,6 +404,7 @@ class Command(BaseCommand): "errors happened while running msguniq\n%s" % errors) elif self.verbosity > 0: self.stdout.write(errors) + msgs = normalize_eols(msgs) with io.open(potfile, 'w', encoding='utf-8') as fp: fp.write(msgs) potfiles.append(potfile) @@ -582,6 +608,7 @@ class Command(BaseCommand): msgs = fp.read() if not self.invoked_for_django: msgs = self.copy_plural_forms(msgs, locale) + msgs = normalize_eols(msgs) msgs = msgs.replace( "#. #-#-#-#-# %s.pot (PACKAGE VERSION) #-#-#-#-#\n" % self.domain, "") with io.open(pofile, 'w', encoding='utf-8') as fp: @@ -619,9 +646,9 @@ class Command(BaseCommand): self.stdout.write("copying plural forms: %s\n" % plural_form_line) lines = [] found = False - for line in msgs.split('\n'): + for line in msgs.splitlines(): if not found and (not line or plural_forms_re.search(line)): - line = '%s\n' % plural_form_line + line = plural_form_line found = True lines.append(line) msgs = '\n'.join(lines)