Localized exception message hacking check
As per [1], this patch adds a new hacking check that verifies raised exceptions don't use unlocalized string messages. This patch also adds unit tests for the new check and enables checks for neutron-lib itself (as per tox.ini). Note: Perhaps this check better belongs in openstack-dev/hacking but it seems we already have a number of more generic checks in neutron. We can discuss that here need be. NB: Without [1] this new hacking check fails when running pep8 on neutron-lib. [1] https://review.openstack.org/#/c/324374/ Change-Id: Ia13f190ec6843ab360d115871d345c4ddc302cc5
This commit is contained in:
@@ -19,3 +19,4 @@ Neutron Specific Commandments
|
||||
- [N531] Validate that LOG messages, except debug ones, have translations
|
||||
- [N532] Validate that LOG.warning is used instead of LOG.warn. The latter is deprecated.
|
||||
- [N533] Validate that debug level logs are not translated
|
||||
- [N534] Exception messages should be translated
|
||||
|
||||
@@ -160,3 +160,4 @@ def factory(register):
|
||||
register(translation_checks.validate_log_translations)
|
||||
register(translation_checks.no_translate_debug_logs)
|
||||
register(translation_checks.check_log_warn_deprecated)
|
||||
register(translation_checks.check_raised_localized_exceptions)
|
||||
|
||||
@@ -75,3 +75,18 @@ def no_translate_debug_logs(logical_line, filename):
|
||||
for hint in _all_hints:
|
||||
if logical_line.startswith("LOG.debug(%s(" % hint):
|
||||
yield(0, "N533 Don't translate debug level logs")
|
||||
|
||||
|
||||
def check_raised_localized_exceptions(logical_line, filename):
|
||||
# NOTE(boden): tox.ini doesn't permit per check exclusion
|
||||
if "/tests/" in filename:
|
||||
return
|
||||
|
||||
logical_line = logical_line.strip()
|
||||
raised_search = re.compile(
|
||||
r"raise (?:\w*)\((.*)\)").match(logical_line)
|
||||
if raised_search:
|
||||
exception_msg = raised_search.groups()[0]
|
||||
if exception_msg.startswith("\"") or exception_msg.startswith("\'"):
|
||||
msg = "N534: Untranslated exception message."
|
||||
yield (logical_line.index(exception_msg), msg)
|
||||
|
||||
@@ -19,12 +19,12 @@ from neutron_lib.tests import _base as base
|
||||
|
||||
class HackingTestCase(base.BaseTestCase):
|
||||
|
||||
def assertLinePasses(self, func, line):
|
||||
def assertLinePasses(self, func, *args):
|
||||
with testtools.ExpectedException(StopIteration):
|
||||
next(func(line))
|
||||
next(func(*args))
|
||||
|
||||
def assertLineFails(self, func, line):
|
||||
self.assertIsInstance(next(func(line)), tuple)
|
||||
def assertLineFails(self, func, *args):
|
||||
self.assertIsInstance(next(func(*args)), tuple)
|
||||
|
||||
def test_use_jsonutils(self):
|
||||
def __get_msg(fun):
|
||||
@@ -149,3 +149,19 @@ class HackingTestCase(base.BaseTestCase):
|
||||
bad = "LOG.warn(_LW('i am deprecated!'))"
|
||||
self.assertEqual(
|
||||
1, len(list(tc.check_log_warn_deprecated(bad, 'f'))))
|
||||
|
||||
def test_check_localized_exception_messages(self):
|
||||
f = tc.check_raised_localized_exceptions
|
||||
self.assertLineFails(f, " raise KeyError('Error text')", '')
|
||||
self.assertLineFails(f, ' raise KeyError("Error text")', '')
|
||||
self.assertLinePasses(f, ' raise KeyError(_("Error text"))', '')
|
||||
self.assertLinePasses(f, ' raise KeyError(_ERR("Error text"))', '')
|
||||
self.assertLinePasses(f, " raise KeyError(translated_msg)", '')
|
||||
self.assertLinePasses(f, '# raise KeyError("Not translated")', '')
|
||||
self.assertLinePasses(f, 'print("raise KeyError("Not '
|
||||
'translated")")', '')
|
||||
|
||||
def test_check_localized_exception_message_skip_tests(self):
|
||||
f = tc.check_raised_localized_exceptions
|
||||
self.assertLinePasses(f, "raise KeyError('Error text')",
|
||||
'neutron_lib/tests/unit/mytest.py')
|
||||
|
||||
Reference in New Issue
Block a user