Add hacking check to ensure _ is imported
Added hacking check to ensure that _ is imported and allows multiple imports from i18n module per line. Change-Id: Ieffabd6f2fe866000c5dc1d9ce83acd2f9ab0450
This commit is contained in:
parent
7cfa3917a4
commit
f8c25dd2aa
|
@ -2,3 +2,8 @@ masakari-monitors Style Commandments
|
|||
===============================================
|
||||
|
||||
Read the OpenStack Style Commandments http://docs.openstack.org/developer/hacking/
|
||||
|
||||
masakari-monitors Specific Commandments
|
||||
------------------------------
|
||||
|
||||
- [M301] Ensure that the _() function is explicitly imported to ensure proper translations.
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
# Copyright (c) 2017, NTT Data
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import re
|
||||
|
||||
|
||||
"""
|
||||
Guidelines for writing new hacking checks
|
||||
|
||||
- Use only for masakarimonitors specific tests. OpenStack general tests
|
||||
should be submitted to the common 'hacking' module.
|
||||
- Pick numbers in the range M3xx. Find the current test with
|
||||
the highest allocated number and then pick the next value.
|
||||
- Keep the test method code in the source file ordered based
|
||||
on the M3xx value.
|
||||
- List the new rule in the top level HACKING.rst file
|
||||
- Add test cases for each new rule to masakarimonitors/tests/unit/
|
||||
test_hacking.py
|
||||
|
||||
"""
|
||||
|
||||
UNDERSCORE_IMPORT_FILES = []
|
||||
|
||||
translated_log = re.compile(
|
||||
r"(.)*LOG\.(audit|error|info|critical|exception)"
|
||||
"\(\s*_\(\s*('|\")")
|
||||
string_translation = re.compile(r"[^_]*_\(\s*('|\")")
|
||||
underscore_import_check = re.compile(r"(.)*import _(.)*")
|
||||
underscore_import_check_multi = re.compile(r"(.)*i18n\s+import(.)* _, (.)*")
|
||||
# We need this for cases where they have created their own _ function.
|
||||
custom_underscore_check = re.compile(r"(.)*_\s*=\s*(.)*")
|
||||
|
||||
|
||||
def check_explicit_underscore_import(logical_line, filename):
|
||||
"""Check for explicit import of the _ function
|
||||
|
||||
We need to ensure that any files that are using the _() function
|
||||
to translate logs are explicitly importing the _ function. We
|
||||
can't trust unit test to catch whether the import has been
|
||||
added so we need to check for it here.
|
||||
"""
|
||||
|
||||
# Build a list of the files that have _ imported. No further
|
||||
# checking needed once it is found.
|
||||
for file in UNDERSCORE_IMPORT_FILES:
|
||||
if file in filename:
|
||||
return
|
||||
if (underscore_import_check.match(logical_line) or
|
||||
underscore_import_check_multi.match(logical_line) or
|
||||
custom_underscore_check.match(logical_line)):
|
||||
UNDERSCORE_IMPORT_FILES.append(filename)
|
||||
elif(translated_log.match(logical_line) or
|
||||
string_translation.match(logical_line)):
|
||||
yield(0, "M301: Found use of _() without explicit import of _ !")
|
||||
|
||||
|
||||
def factory(register):
|
||||
register(check_explicit_underscore_import)
|
|
@ -0,0 +1,79 @@
|
|||
# Copyright 2017 NTT Data.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import testtools
|
||||
|
||||
from masakarimonitors.hacking import checks
|
||||
|
||||
|
||||
class HackingTestCase(testtools.TestCase):
|
||||
"""This class tests the hacking checks in masakarimonitors.hacking.checks by
|
||||
passing strings to the check methods like the pep8/flake8 parser would.
|
||||
The parser loops over each line in the file and then passes the
|
||||
parameters to the check method. The parameter names in the check method
|
||||
dictate what type of object is passed to the check method.
|
||||
|
||||
The parameter types are::
|
||||
|
||||
logical_line: A processed line with the following modifications:
|
||||
- Multi-line statements converted to a single line.
|
||||
- Stripped left and right.
|
||||
- Contents of strings replaced with "xxx" of same length.
|
||||
- Comments removed.
|
||||
physical_line: Raw line of text from the input file.
|
||||
lines: a list of the raw lines from the input file
|
||||
tokens: the tokens that contribute to this logical line
|
||||
line_number: line number in the input file
|
||||
total_lines: number of lines in the input file
|
||||
blank_lines: blank lines before this one
|
||||
indent_char: indentation character in this file (" " or "\t")
|
||||
indent_level: indentation (with tabs expanded to multiples of 8)
|
||||
previous_indent_level: indentation on previous line
|
||||
previous_logical: previous logical line
|
||||
filename: Path of the file being run through pep8
|
||||
|
||||
When running a test on a check method the return will be False/None if
|
||||
there is no violation in the sample input. If there is an error a tuple is
|
||||
returned with a position in the line, and a message. So to check the result
|
||||
just assertTrue if the check is expected to fail and assertFalse if it
|
||||
should pass.
|
||||
"""
|
||||
def test_check_explicit_underscore_import(self):
|
||||
self.assertEqual(len(list(checks.check_explicit_underscore_import(
|
||||
"LOG.info(_('My info message'))",
|
||||
"masakarimonitors/tests/other_files.py"))), 1)
|
||||
self.assertEqual(len(list(checks.check_explicit_underscore_import(
|
||||
"msg = _('My message')",
|
||||
"masakarimonitors/tests/other_files.py"))), 1)
|
||||
self.assertEqual(len(list(checks.check_explicit_underscore_import(
|
||||
"from masakarimonitors.i18n import _",
|
||||
"masakarimonitors/tests/other_files.py"))), 0)
|
||||
self.assertEqual(len(list(checks.check_explicit_underscore_import(
|
||||
"LOG.info(_('My info message'))",
|
||||
"masakarimonitors/tests/other_files.py"))), 0)
|
||||
self.assertEqual(len(list(checks.check_explicit_underscore_import(
|
||||
"msg = _('My message')",
|
||||
"masakarimonitors/tests/other_files.py"))), 0)
|
||||
self.assertEqual(len(list(checks.check_explicit_underscore_import(
|
||||
"from masakarimonitors.i18n import _, _LW",
|
||||
"masakarimonitors/tests/other_files2.py"))), 0)
|
||||
self.assertEqual(len(list(checks.check_explicit_underscore_import(
|
||||
"msg = _('My message')",
|
||||
"masakarimonitors/tests/other_files2.py"))), 0)
|
||||
self.assertEqual(len(list(checks.check_explicit_underscore_import(
|
||||
"_ = translations.ugettext",
|
||||
"masakarimonitors/tests/other_files3.py"))), 0)
|
||||
self.assertEqual(len(list(checks.check_explicit_underscore_import(
|
||||
"msg = _('My message')",
|
||||
"masakarimonitors/tests/other_files3.py"))), 0)
|
12
tox.ini
12
tox.ini
|
@ -35,9 +35,17 @@ commands =
|
|||
commands = oslo_debug_helper {posargs}
|
||||
|
||||
[flake8]
|
||||
# E123, E125 skipped as they are invalid PEP-8.
|
||||
# E123 - closing bracket does not match indentation of opening bracket's line
|
||||
# E125 - continuation line with same indent as next logical line
|
||||
# E128 - continuation line under-indented for visual indent
|
||||
# E265 - block comment should start with '# '
|
||||
# H405 - multi line docstring summary not separated with an empty line
|
||||
|
||||
show-source = True
|
||||
ignore = E123,E125
|
||||
ignore = E123,E125,E128,E265,H405
|
||||
builtins = _
|
||||
exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build
|
||||
|
||||
[hacking]
|
||||
import_exceptions = masakarimonitors.i18n
|
||||
|
||||
|
|
Loading…
Reference in New Issue