diff --git a/django/core/management/commands/compilemessages.py b/django/core/management/commands/compilemessages.py index df188cec84..44e0520b47 100644 --- a/django/core/management/commands/compilemessages.py +++ b/django/core/management/commands/compilemessages.py @@ -2,6 +2,7 @@ import codecs import concurrent.futures import glob import os +from pathlib import Path from django.core.management.base import BaseCommand, CommandError from django.core.management.utils import ( @@ -10,7 +11,7 @@ from django.core.management.utils import ( def has_bom(fn): - with open(fn, 'rb') as f: + with fn.open('rb') as f: sample = f.read(4) return sample.startswith((codecs.BOM_UTF8, codecs.BOM_UTF16_LE, codecs.BOM_UTF16_BE)) @@ -123,7 +124,9 @@ class Command(BaseCommand): for i, (dirpath, f) in enumerate(locations): if self.verbosity > 0: self.stdout.write('processing file %s in %s' % (f, dirpath)) - po_path = os.path.join(dirpath, f) + po_path = Path(dirpath) / f + mo_path = po_path.with_suffix('.mo') + if has_bom(po_path): self.stderr.write( 'The %s file has a BOM (Byte Order Mark). Django only ' @@ -131,10 +134,9 @@ class Command(BaseCommand): ) self.has_errors = True continue - base_path = os.path.splitext(po_path)[0] # Check writability on first location - if i == 0 and not is_writable(base_path + '.mo'): + if i == 0 and not is_writable(mo_path): self.stderr.write( 'The po files under %s are in a seemingly not writable location. ' 'mo files will not be updated/created.' % dirpath @@ -142,9 +144,7 @@ class Command(BaseCommand): self.has_errors = True return - args = [self.program] + self.program_options + [ - '-o', base_path + '.mo', base_path + '.po' - ] + args = [self.program, *self.program_options, '-o', mo_path, po_path] futures.append(executor.submit(popen_wrapper, args)) for future in concurrent.futures.as_completed(futures): diff --git a/tests/i18n/test_compilation.py b/tests/i18n/test_compilation.py index 04958bcbb4..fbacaee221 100644 --- a/tests/i18n/test_compilation.py +++ b/tests/i18n/test_compilation.py @@ -34,6 +34,7 @@ class PoFileTests(MessageCompilationTests): LOCALE = 'es_AR' MO_FILE = 'locale/%s/LC_MESSAGES/django.mo' % LOCALE + MO_FILE_EN = 'locale/en/LC_MESSAGES/django.mo' def test_bom_rejection(self): stderr = StringIO() @@ -43,17 +44,17 @@ class PoFileTests(MessageCompilationTests): self.assertFalse(os.path.exists(self.MO_FILE)) def test_no_write_access(self): - mo_file_en = 'locale/en/LC_MESSAGES/django.mo' + mo_file_en = Path(self.MO_FILE_EN) err_buffer = StringIO() - # put file in read-only mode - old_mode = os.stat(mo_file_en).st_mode - os.chmod(mo_file_en, stat.S_IREAD) + # Put file in read-only mode. + old_mode = mo_file_en.stat().st_mode + mo_file_en.chmod(stat.S_IREAD) try: with self.assertRaisesMessage(CommandError, 'compilemessages generated one or more errors.'): call_command('compilemessages', locale=['en'], stderr=err_buffer, verbosity=0) self.assertIn('not writable location', err_buffer.getvalue()) finally: - os.chmod(mo_file_en, old_mode) + mo_file_en.chmod(old_mode) class PoFileContentsTests(MessageCompilationTests):