Files
deb-python-neutron-lib/neutron_lib/hacking/checks.py
Takashi NATSUME eb32fd4fbd 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 the following hacking rule for it.

- [N536] String interpolation should be delayed at logging calls.

We need this to ensure that all projects using the neutron-lib
hacking rules still have enforcement of the log policies
of the project.

See the oslo i18n guideline.

* http://docs.openstack.org/developer/oslo.i18n/guidelines.html

Change-Id: I901dcbfbd53d5d19db651473d2891bc8e8a59710
Related-Bug: #1596829
2016-08-15 09:53:28 +09:00

175 lines
6.5 KiB
Python

# Copyright (c) 2014 OpenStack Foundation.
#
# 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
from debtcollector import removals
from neutron_lib.hacking import translation_checks
# Guidelines for writing new hacking checks
#
# - Use only for Neutron specific tests. OpenStack general tests
# should be submitted to the common 'hacking' module.
# - Pick numbers in the range N5xx. 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 N5xx value.
# - List the new rule in the top level HACKING.rst file
# - Add test cases for each new rule to
# neutron_lib/tests/unit/hacking/test_checks.py
mutable_default_args = re.compile(r"^\s*def .+\((.+=\{\}|.+=\[\])")
namespace_imports_dot = re.compile(r"import[\s]+([\w]+)[.][^\s]+")
namespace_imports_from_dot = re.compile(r"from[\s]+([\w]+)[.]")
namespace_imports_from_root = re.compile(r"from[\s]+([\w]+)[\s]+import[\s]+")
contextlib_nested = re.compile(r"^\s*with (contextlib\.)?nested\(")
def use_jsonutils(logical_line, filename):
msg = "N521: jsonutils.%(fun)s must be used instead of json.%(fun)s"
# Some files in the tree are not meant to be run from inside Neutron
# itself, so we should not complain about them not using jsonutils
json_check_skipped_patterns = [
"neutron/plugins/ml2/drivers/openvswitch/agent/xenapi/etc/xapi.d/"
"plugins/netwrap",
]
for pattern in json_check_skipped_patterns:
if pattern in filename:
return
if "json." in logical_line:
json_funcs = ['dumps(', 'dump(', 'loads(', 'load(']
for f in json_funcs:
pos = logical_line.find('json.%s' % f)
if pos != -1:
yield (pos, msg % {'fun': f[:-1]})
def _check_imports(regex, submatch, logical_line):
m = re.match(regex, logical_line)
if m and m.group(1) == submatch:
return True
def _check_namespace_imports(failure_code, namespace, new_ns, logical_line,
message_override=None):
if message_override is not None:
msg_o = "%s: %s" % (failure_code, message_override)
else:
msg_o = None
if _check_imports(namespace_imports_from_dot, namespace, logical_line):
msg = ("%s: '%s' must be used instead of '%s'.") % (
failure_code,
logical_line.replace('%s.' % namespace, new_ns),
logical_line)
return (0, msg_o or msg)
elif _check_imports(namespace_imports_from_root, namespace, logical_line):
msg = ("%s: '%s' must be used instead of '%s'.") % (
failure_code,
logical_line.replace(
'from %s import ' % namespace, 'import %s' % new_ns),
logical_line)
return (0, msg_o or msg)
elif _check_imports(namespace_imports_dot, namespace, logical_line):
msg = ("%s: '%s' must be used instead of '%s'.") % (
failure_code,
logical_line.replace('import', 'from').replace('.', ' import '),
logical_line)
return (0, msg_o or msg)
@removals.remove(removal_version='P release')
def check_oslo_namespace_imports(logical_line):
x = _check_namespace_imports('N523', 'oslo', 'oslo_', logical_line)
if x is not None:
yield x
def check_no_contextlib_nested(logical_line, filename):
msg = ("N524: contextlib.nested is deprecated. With Python 2.7 and later "
"the with-statement supports multiple nested objects. See https://"
"docs.python.org/2/library/contextlib.html#contextlib.nested for "
"more information.")
if contextlib_nested.match(logical_line):
yield(0, msg)
def check_python3_xrange(logical_line):
if re.search(r"\bxrange\s*\(", logical_line):
yield(0, "N525: Do not use xrange. Use range, or six.moves.range for "
"large loops.")
def check_no_basestring(logical_line):
if re.search(r"\bbasestring\b", logical_line):
msg = ("N526: basestring is not Python3-compatible, use "
"six.string_types instead.")
yield(0, msg)
def check_python3_no_iteritems(logical_line):
if re.search(r".*\.iteritems\(\)", logical_line):
msg = ("N527: Use dict.items() instead of dict.iteritems() to be "
"compatible with both Python 2 and Python 3. In Python 2, "
"dict.items() may be inefficient for very large dictionaries. "
"If you can prove that you need the optimization of an "
"iterator for Python 2, then you can use six.iteritems(dict).")
yield(0, msg)
def no_mutable_default_args(logical_line):
msg = "N529: Method's default argument shouldn't be mutable!"
if mutable_default_args.match(logical_line):
yield (0, msg)
# Chances are that most projects will need to put an ignore on this rule
# until they can fully migrate to the lib.
def check_neutron_namespace_imports(logical_line):
x = _check_namespace_imports(
'N530', 'neutron', 'neutron_lib.', logical_line,
message_override="direct neutron imports not allowed")
if x is not None:
yield x
def check_no_eventlet_imports(logical_line):
"""N535 - Usage of Python eventlet module not allowed."""
if re.match(r'(import|from)\s+[(]?eventlet', logical_line):
msg = 'N535: Usage of Python eventlet module not allowed'
yield logical_line.index('eventlet'), msg
def factory(register):
register(use_jsonutils)
register(check_no_contextlib_nested)
register(check_python3_xrange)
register(check_no_basestring)
register(check_python3_no_iteritems)
register(no_mutable_default_args)
register(check_neutron_namespace_imports)
register(check_no_eventlet_imports)
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)
register(translation_checks.check_delayed_string_interpolation)