Fixed #24384 -- Allowed compilemessages to continue running after nonfatal errors.
Thanks Aymeric Augustin for the report and Carlton Gibson and Tim Graham for the reviews.
This commit is contained in:
parent
b30f9b131c
commit
a77f21880d
|
@ -86,6 +86,7 @@ class Command(BaseCommand):
|
||||||
locales = locale or all_locales
|
locales = locale or all_locales
|
||||||
locales = set(locales).difference(exclude)
|
locales = set(locales).difference(exclude)
|
||||||
|
|
||||||
|
self.has_errors = False
|
||||||
for basedir in basedirs:
|
for basedir in basedirs:
|
||||||
if locales:
|
if locales:
|
||||||
dirs = [os.path.join(basedir, l, 'LC_MESSAGES') for l in locales]
|
dirs = [os.path.join(basedir, l, 'LC_MESSAGES') for l in locales]
|
||||||
|
@ -98,6 +99,9 @@ class Command(BaseCommand):
|
||||||
if locations:
|
if locations:
|
||||||
self.compile_messages(locations)
|
self.compile_messages(locations)
|
||||||
|
|
||||||
|
if self.has_errors:
|
||||||
|
raise CommandError('compilemessages generated one or more errors.')
|
||||||
|
|
||||||
def compile_messages(self, locations):
|
def compile_messages(self, locations):
|
||||||
"""
|
"""
|
||||||
Locations is a list of tuples: [(directory, file), ...]
|
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))
|
self.stdout.write('processing file %s in %s\n' % (f, dirpath))
|
||||||
po_path = os.path.join(dirpath, f)
|
po_path = os.path.join(dirpath, f)
|
||||||
if has_bom(po_path):
|
if has_bom(po_path):
|
||||||
raise CommandError("The %s file has a BOM (Byte Order Mark). "
|
self.stderr.write(
|
||||||
"Django only supports .po files encoded in "
|
'The %s file has a BOM (Byte Order Mark). Django only '
|
||||||
"UTF-8 and without any BOM." % po_path)
|
'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]
|
base_path = os.path.splitext(po_path)[0]
|
||||||
|
|
||||||
# Check writability on first location
|
# Check writability on first location
|
||||||
if i == 0 and not is_writable(base_path + '.mo'):
|
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. "
|
self.stderr.write(
|
||||||
"mo files will not be updated/created." % dirpath)
|
'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
|
return
|
||||||
|
|
||||||
args = [self.program] + self.program_options + [
|
args = [self.program] + self.program_options + [
|
||||||
|
@ -124,7 +134,7 @@ class Command(BaseCommand):
|
||||||
output, errors, status = popen_wrapper(args)
|
output, errors, status = popen_wrapper(args)
|
||||||
if status:
|
if status:
|
||||||
if errors:
|
if errors:
|
||||||
msg = "Execution of %s failed: %s" % (self.program, errors)
|
self.stderr.write('Execution of %s failed: %s.' % (self.program, errors))
|
||||||
else:
|
else:
|
||||||
msg = "Execution of %s failed" % self.program
|
self.stderr.write('Execution of %s failed.' % self.program)
|
||||||
raise CommandError(msg)
|
self.has_errors = True
|
||||||
|
|
|
@ -35,9 +35,10 @@ class PoFileTests(MessageCompilationTests):
|
||||||
MO_FILE = 'locale/%s/LC_MESSAGES/django.mo' % LOCALE
|
MO_FILE = 'locale/%s/LC_MESSAGES/django.mo' % LOCALE
|
||||||
|
|
||||||
def test_bom_rejection(self):
|
def test_bom_rejection(self):
|
||||||
with self.assertRaises(CommandError) as cm:
|
stderr = StringIO()
|
||||||
call_command('compilemessages', locale=[self.LOCALE], stdout=StringIO())
|
with self.assertRaisesMessage(CommandError, 'compilemessages generated one or more errors.'):
|
||||||
self.assertIn("file has a BOM (Byte Order Mark)", cm.exception.args[0])
|
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))
|
self.assertFalse(os.path.exists(self.MO_FILE))
|
||||||
|
|
||||||
def test_no_write_access(self):
|
def test_no_write_access(self):
|
||||||
|
@ -47,9 +48,9 @@ class PoFileTests(MessageCompilationTests):
|
||||||
old_mode = os.stat(mo_file_en).st_mode
|
old_mode = os.stat(mo_file_en).st_mode
|
||||||
os.chmod(mo_file_en, stat.S_IREAD)
|
os.chmod(mo_file_en, stat.S_IREAD)
|
||||||
try:
|
try:
|
||||||
call_command('compilemessages', locale=['en'], stderr=err_buffer, verbosity=0)
|
with self.assertRaisesMessage(CommandError, 'compilemessages generated one or more errors.'):
|
||||||
err = err_buffer.getvalue()
|
call_command('compilemessages', locale=['en'], stderr=err_buffer, verbosity=0)
|
||||||
self.assertIn("not writable location", err)
|
self.assertIn('not writable location', err_buffer.getvalue())
|
||||||
finally:
|
finally:
|
||||||
os.chmod(mo_file_en, old_mode)
|
os.chmod(mo_file_en, old_mode)
|
||||||
|
|
||||||
|
@ -137,7 +138,7 @@ class CompilationErrorHandling(MessageCompilationTests):
|
||||||
def test_error_reported_by_msgfmt(self):
|
def test_error_reported_by_msgfmt(self):
|
||||||
# po file contains wrong po formatting.
|
# po file contains wrong po formatting.
|
||||||
with self.assertRaises(CommandError):
|
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):
|
def test_msgfmt_error_including_non_ascii(self):
|
||||||
# po file contains invalid msgstr content (triggers non-ascii error content).
|
# po file contains invalid msgstr content (triggers non-ascii error content).
|
||||||
|
@ -148,8 +149,10 @@ class CompilationErrorHandling(MessageCompilationTests):
|
||||||
cmd = MakeMessagesCommand()
|
cmd = MakeMessagesCommand()
|
||||||
if cmd.gettext_version < (0, 18, 3):
|
if cmd.gettext_version < (0, 18, 3):
|
||||||
self.skipTest("python-brace-format is a recent gettext addition.")
|
self.skipTest("python-brace-format is a recent gettext addition.")
|
||||||
with self.assertRaisesMessage(CommandError, "' cannot start a field name"):
|
stderr = StringIO()
|
||||||
call_command('compilemessages', locale=['ko'], verbosity=0)
|
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):
|
class ProjectAndAppTests(MessageCompilationTests):
|
||||||
|
|
Loading…
Reference in New Issue