diff --git a/django/core/management/commands/compilemessages.py b/django/core/management/commands/compilemessages.py index bf704a4e8d..77dd0f085c 100644 --- a/django/core/management/commands/compilemessages.py +++ b/django/core/management/commands/compilemessages.py @@ -86,6 +86,7 @@ class Command(BaseCommand): locales = locale or all_locales locales = set(locales).difference(exclude) + self.has_errors = False for basedir in basedirs: if locales: dirs = [os.path.join(basedir, l, 'LC_MESSAGES') for l in locales] @@ -98,6 +99,9 @@ class Command(BaseCommand): if locations: self.compile_messages(locations) + if self.has_errors: + raise CommandError('compilemessages generated one or more errors.') + def compile_messages(self, locations): """ Locations is a list of tuples: [(directory, file), ...] @@ -107,15 +111,21 @@ class Command(BaseCommand): self.stdout.write('processing file %s in %s\n' % (f, dirpath)) po_path = os.path.join(dirpath, f) if has_bom(po_path): - raise CommandError("The %s file has a BOM (Byte Order Mark). " - "Django only supports .po files encoded in " - "UTF-8 and without any BOM." % po_path) + self.stderr.write( + 'The %s file has a BOM (Byte Order Mark). Django only ' + 'supports .po files encoded in UTF-8 and without any BOM.' % po_path + ) + 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'): - self.stderr.write("The po files under %s are in a seemingly not writable location. " - "mo files will not be updated/created." % dirpath) + self.stderr.write( + 'The po files under %s are in a seemingly not writable location. ' + 'mo files will not be updated/created.' % dirpath + ) + self.has_errors = True return args = [self.program] + self.program_options + [ @@ -124,7 +134,7 @@ class Command(BaseCommand): output, errors, status = popen_wrapper(args) if status: if errors: - msg = "Execution of %s failed: %s" % (self.program, errors) + self.stderr.write('Execution of %s failed: %s.' % (self.program, errors)) else: - msg = "Execution of %s failed" % self.program - raise CommandError(msg) + self.stderr.write('Execution of %s failed.' % self.program) + self.has_errors = True diff --git a/tests/i18n/test_compilation.py b/tests/i18n/test_compilation.py index 02114fa2dd..11266b7a58 100644 --- a/tests/i18n/test_compilation.py +++ b/tests/i18n/test_compilation.py @@ -35,9 +35,10 @@ class PoFileTests(MessageCompilationTests): MO_FILE = 'locale/%s/LC_MESSAGES/django.mo' % LOCALE def test_bom_rejection(self): - with self.assertRaises(CommandError) as cm: - call_command('compilemessages', locale=[self.LOCALE], stdout=StringIO()) - self.assertIn("file has a BOM (Byte Order Mark)", cm.exception.args[0]) + stderr = StringIO() + with self.assertRaisesMessage(CommandError, 'compilemessages generated one or more errors.'): + call_command('compilemessages', locale=[self.LOCALE], stdout=StringIO(), stderr=stderr) + self.assertIn('file has a BOM (Byte Order Mark)', stderr.getvalue()) self.assertFalse(os.path.exists(self.MO_FILE)) def test_no_write_access(self): @@ -47,9 +48,9 @@ class PoFileTests(MessageCompilationTests): old_mode = os.stat(mo_file_en).st_mode os.chmod(mo_file_en, stat.S_IREAD) try: - call_command('compilemessages', locale=['en'], stderr=err_buffer, verbosity=0) - err = err_buffer.getvalue() - self.assertIn("not writable location", err) + 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) @@ -137,7 +138,7 @@ class CompilationErrorHandling(MessageCompilationTests): def test_error_reported_by_msgfmt(self): # po file contains wrong po formatting. with self.assertRaises(CommandError): - call_command('compilemessages', locale=['ja'], verbosity=0) + call_command('compilemessages', locale=['ja'], verbosity=0, stderr=StringIO()) def test_msgfmt_error_including_non_ascii(self): # po file contains invalid msgstr content (triggers non-ascii error content). @@ -148,8 +149,10 @@ class CompilationErrorHandling(MessageCompilationTests): cmd = MakeMessagesCommand() if cmd.gettext_version < (0, 18, 3): self.skipTest("python-brace-format is a recent gettext addition.") - with self.assertRaisesMessage(CommandError, "' cannot start a field name"): - call_command('compilemessages', locale=['ko'], verbosity=0) + stderr = StringIO() + with self.assertRaisesMessage(CommandError, 'compilemessages generated one or more errors'): + call_command('compilemessages', locale=['ko'], stdout=StringIO(), stderr=stderr) + self.assertIn("' cannot start a field name", stderr.getvalue()) class ProjectAndAppTests(MessageCompilationTests):