Add a hacking rule for string interpolation at logging
String interpolation should be delayed to be handled by the logging code, rather than being done at the point of the logging call. So add a hacking rule for it. See the oslo i18n guideline. * http://docs.openstack.org/developer/oslo.i18n/guidelines.html Change-Id: Ib7d97e6edbb8069c12b22505c0d6653b4a17ec78 Closes-Bug: #1596829
This commit is contained in:
parent
48051ece73
commit
cd3be63409
|
@ -48,3 +48,4 @@ Masakari Specific Commandments
|
|||
- [M327] Python 3: do not use dict.iterkeys.
|
||||
- [M328] Python 3: do not use dict.itervalues.
|
||||
- [M329] Deprecated library function os.popen()
|
||||
- [M330] String interpolation should be delayed at logging calls.
|
||||
|
|
|
@ -95,6 +95,9 @@ spawn_re = re.compile(
|
|||
contextlib_nested = re.compile(r"^with (contextlib\.)?nested\(")
|
||||
doubled_words_re = re.compile(
|
||||
r"\b(then?|[iao]n|i[fst]|but|f?or|at|and|[dt]o)\s+\1\b")
|
||||
log_string_interpolation = re.compile(r".*LOG\.(error|warning|info"
|
||||
r"|critical|exception|debug)"
|
||||
r"\([^,]*%[^,]*[,)]")
|
||||
|
||||
|
||||
def no_db_session_in_public_api(logical_line, filename):
|
||||
|
@ -418,6 +421,27 @@ def no_os_popen(logical_line):
|
|||
'Replace it using subprocess module. ')
|
||||
|
||||
|
||||
def check_delayed_string_interpolation(logical_line, filename, noqa):
|
||||
"""M330 String interpolation should be delayed at logging calls.
|
||||
|
||||
M330: LOG.debug('Example: %s' % 'bad')
|
||||
Okay: LOG.debug('Example: %s', 'good')
|
||||
"""
|
||||
msg = ("M330 String interpolation should be delayed to be "
|
||||
"handled by the logging code, rather than being done "
|
||||
"at the point of the logging call. "
|
||||
"Use ',' instead of '%'.")
|
||||
|
||||
if noqa:
|
||||
return
|
||||
|
||||
if '/tests/' in filename:
|
||||
return
|
||||
|
||||
if log_string_interpolation.match(logical_line):
|
||||
yield(logical_line.index('%'), msg)
|
||||
|
||||
|
||||
def factory(register):
|
||||
register(no_db_session_in_public_api)
|
||||
register(use_timeutils_utcnow)
|
||||
|
@ -445,3 +469,4 @@ def factory(register):
|
|||
register(check_python3_no_iterkeys)
|
||||
register(check_python3_no_itervalues)
|
||||
register(no_os_popen)
|
||||
register(check_delayed_string_interpolation)
|
||||
|
|
|
@ -481,3 +481,55 @@ class HackingTestCase(test.NoDBTestCase):
|
|||
errors = [(4, 0, 'M329'), (8, 8, 'M329')]
|
||||
self._assert_has_errors(code, checks.no_os_popen,
|
||||
expected_errors=errors)
|
||||
|
||||
def test_check_delayed_string_interpolation(self):
|
||||
checker = checks.check_delayed_string_interpolation
|
||||
code = """
|
||||
msg_w = _LW('Test string (%s)')
|
||||
msg_i = _LI('Test string (%s)')
|
||||
value = 'test'
|
||||
|
||||
LOG.error(_LE("Test string (%s)") % value)
|
||||
LOG.warning(msg_w % 'test%string')
|
||||
LOG.info(msg_i %
|
||||
"test%string%info")
|
||||
LOG.critical(
|
||||
_LC('Test string (%s)') % value,
|
||||
instance=instance)
|
||||
LOG.exception(_LE(" 'Test quotation %s' \"Test\"") % 'test')
|
||||
LOG.debug(' "Test quotation %s" \'Test\'' % "test")
|
||||
LOG.debug('Tesing %(test)s' %
|
||||
{'test': ','.join(
|
||||
['%s=%s' % (name, value)
|
||||
for name, value in test.items()])})
|
||||
"""
|
||||
|
||||
expected_errors = [(5, 34, 'M330'), (6, 18, 'M330'), (7, 15, 'M330'),
|
||||
(10, 28, 'M330'), (12, 49, 'M330'),
|
||||
(13, 40, 'M330'), (14, 28, 'M330')]
|
||||
self._assert_has_errors(code, checker, expected_errors=expected_errors)
|
||||
self._assert_has_no_errors(
|
||||
code, checker, filename='masakari/tests/unit/test_hacking.py')
|
||||
|
||||
code = """
|
||||
msg_w = _LW('Test string (%s)')
|
||||
msg_i = _LI('Test string (%s)')
|
||||
value = 'test'
|
||||
|
||||
LOG.error(_LE("Test string (%s)"), value)
|
||||
LOG.error(_LE("Test string (%s)") % value) # noqa
|
||||
LOG.warn(_LW('Test string (%s)'),
|
||||
value)
|
||||
LOG.info(msg_i,
|
||||
"test%string%info")
|
||||
LOG.critical(
|
||||
_LC('Test string (%s)'), value,
|
||||
instance=instance)
|
||||
LOG.exception(_LE(" 'Test quotation %s' \"Test\""), 'test')
|
||||
LOG.debug(' "Test quotation %s" \'Test\'', "test")
|
||||
LOG.debug('Tesing %(test)s',
|
||||
{'test': ','.join(
|
||||
['%s=%s' % (name, value)
|
||||
for name, value in test.items()])})
|
||||
"""
|
||||
self._assert_has_no_errors(code, checker)
|
||||
|
|
Loading…
Reference in New Issue