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:
Takashi NATSUME 2016-08-02 14:39:30 +09:00
parent 48051ece73
commit cd3be63409
3 changed files with 78 additions and 0 deletions

View File

@ -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.

View File

@ -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)

View File

@ -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)