diff --git a/doc/source/user/hacking.rst b/doc/source/user/hacking.rst index e191f7921..7520f5a2e 100644 --- a/doc/source/user/hacking.rst +++ b/doc/source/user/hacking.rst @@ -3,35 +3,43 @@ Hacking Checks ============== The ``neutron_lib.hacking`` package implements a number of public -`hacking checks `_ intended to help +`flake8 checks `__ intended to help adopters validate their compliance with the latest hacking standards. To adopt neutron-lib's hacking checks: -#. Update your project's ``tox.ini`` to use - ``neutron_lib.hacking.checks.factory`` for its ``local-check-factory``. +#. Update your project's ``tox.ini`` to include hacking checks from + neutron-lib. More specifically, copy hacking checks under + "Checks for neutron and related projects" in + ``[flake8.local-plugin] extension`` in neutron-lib ``tox.ini`` + to ``[flake8.local-plugin] extension`` in your project's ``tox.ini``. For example in your ``tox.ini``:: - [hacking] - local-check-factory = neutron_lib.hacking.checks.factory + [flake8:local-plugins] + extension = + # Checks from neutron-lib + N521 = neutron_lib.hacking.checks:use_jsonutils + N524 = neutron_lib.hacking.checks:check_no_contextlib_nested + N529 = neutron_lib.hacking.checks:no_mutable_default_args + N530 = neutron_lib.hacking.checks:check_neutron_namespace_imports + N532 = neutron_lib.hacking.translation_checks:check_log_warn_deprecated + N534 = neutron_lib.hacking.translation_checks:check_raised_localized_exceptions + N536 = neutron_lib.hacking.checks:assert_equal_none + N537 = neutron_lib.hacking.translation_checks:no_translate_logs - If your project needs to register additional project specific hacking - checks, you can define your own factory function that calls neutron-lib's - ``factory`` function. + Under certain circumstances, adopters may need to ignore specific + neutron-lib hacking checks temporarily. You can ignore such checks + just by commenting out them (hopefully with a proper reason). - For example in your project's python source:: + If your project has its own hacking checks, you can add more rules + to ``[flake8.local-plugin] extension`` along with hacking checks + from neutron-lib. - def my_factory(register): - # register neutron-lib checks - neutron_lib_checks.factory(register) - # register project specific checks - register(my_project_check) + .. note:: - And use your project's own factory in ``tox.ini``:: - - [hacking] - local-check-factory = myproject.mypkg.my_factory + The above configuration assumes hacking 2.x. + If your project uses hacking 1.x, see :ref:`hacking1_support` below. #. Update your project's ``tox.ini`` enable any flake8 extensions neutron-lib's ``tox.ini`` does. These are hacking checks otherwise disabled by default @@ -54,12 +62,40 @@ To adopt neutron-lib's hacking checks: hacking checks will be communicated via openstack-discuss email list and `neutron meetings `_. - Under certain circumstances, adopters may need to ignore specific - neutron-lib hacking checks temporarily. This can be done using the - ``ignore`` property in the ``[flake8]`` section of your ``tox.ini``. - For example, to ignore the hacking check ``N536`` your tox.ini might - have:: +.. _hacking1_support: - [flake8] - # temporarily ignore N536 while fixing failing checks - ignore = N536 +Hacking 1.x support +------------------- + +If your project uses hacking 1.x, you need a different way to consume hacking +checks from neutron-lib. + +.. warning:: + + hacking 1.x support is deprecated and will be dropped once all neutron + related projects migrate to hacking 2.x. + +Update your project's ``tox.ini`` to use +``neutron_lib.hacking.checks.factory`` for its ``local-check-factory``. + +For example in your ``tox.ini``:: + + [hacking] + local-check-factory = neutron_lib.hacking.checks.factory + +If your project needs to register additional project specific hacking +checks, you can define your own factory function that calls neutron-lib's +``factory`` function. + +For example in your project's python source:: + + def my_factory(register): + # register neutron-lib checks + neutron_lib_checks.factory(register) + # register project specific checks + register(my_project_check) + +And use your project's own factory in ``tox.ini``:: + + [hacking] + local-check-factory = myproject.mypkg.my_factory diff --git a/neutron_lib/hacking/checks.py b/neutron_lib/hacking/checks.py index 5deb44d71..a15235254 100644 --- a/neutron_lib/hacking/checks.py +++ b/neutron_lib/hacking/checks.py @@ -14,6 +14,8 @@ import re +from hacking import core + from neutron_lib.hacking import translation_checks # Guidelines for writing new hacking checks @@ -41,6 +43,7 @@ assert_is_none_re = re.compile( r"assertIs(Not)?\(.*,\s+None\)(( |\t)*#.*)?$|assertIs(Not)?\(None,") +@core.flake8ext def use_jsonutils(logical_line, filename): """N521 - jsonutils must be used instead of json. @@ -105,6 +108,7 @@ def _check_namespace_imports(failure_code, namespace, new_ns, logical_line, return (0, msg_o or msg) +@core.flake8ext def check_no_contextlib_nested(logical_line, filename): """N524 - Use of contextlib.nested is deprecated. @@ -123,6 +127,7 @@ def check_no_contextlib_nested(logical_line, filename): yield(0, msg) +@core.flake8ext def no_mutable_default_args(logical_line): """N529 - Method's default argument shouldn't be mutable. @@ -139,6 +144,7 @@ def no_mutable_default_args(logical_line): # Chances are that most projects will need to put an ignore on this rule # until they can fully migrate to the lib. +@core.flake8ext def check_neutron_namespace_imports(logical_line): """N530 - Direct neutron imports not allowed. @@ -154,6 +160,7 @@ def check_neutron_namespace_imports(logical_line): yield x +@core.flake8ext def check_no_eventlet_imports(logical_line): """N535 - Usage of Python eventlet module not allowed. @@ -167,6 +174,7 @@ def check_no_eventlet_imports(logical_line): yield logical_line.index('eventlet'), msg +@core.flake8ext def assert_equal_none(logical_line): """N536 - Use assertIsNone.""" if assert_equal_none_re.search(logical_line): @@ -180,6 +188,8 @@ def assert_equal_none(logical_line): yield logical_line.index('assert'), msg +# TODO(amotoki): Drop this once all neutron related projects +# have switched to hacking 2.x def factory(register): """Hacking check factory for neutron-lib adopter compliant checks. @@ -197,18 +207,3 @@ def factory(register): register(translation_checks.check_log_warn_deprecated) register(translation_checks.check_raised_localized_exceptions) register(assert_equal_none) - - -def _neutron_lib_factory(register): - """Hacking check factory for neutron-lib internal project checks. - - Hacking check factory for use with tox.ini. This factory registers all - checks that are run with the neutron-lib project itself. - - :param register: The function to register the check functions with. - :returns: None. - """ - factory(register) - - # neutron-lib project specific checks below - register(check_no_eventlet_imports) diff --git a/neutron_lib/hacking/translation_checks.py b/neutron_lib/hacking/translation_checks.py index b3d0330db..36d807a91 100644 --- a/neutron_lib/hacking/translation_checks.py +++ b/neutron_lib/hacking/translation_checks.py @@ -14,6 +14,8 @@ import re +from hacking import core + _all_log_levels = {'critical', 'error', 'exception', 'info', 'warning', 'debug'} @@ -36,6 +38,7 @@ def _translation_checks_not_enforced(filename): return any(pat in filename for pat in ["/tests/", "rally-jobs/plugins/"]) +@core.flake8ext def check_log_warn_deprecated(logical_line, filename): """N532 - Use LOG.warning due to compatibility with py3. @@ -50,6 +53,7 @@ def check_log_warn_deprecated(logical_line, filename): yield (0, msg) +@core.flake8ext def check_raised_localized_exceptions(logical_line, filename): """N534 - Untranslated exception message. @@ -72,6 +76,7 @@ def check_raised_localized_exceptions(logical_line, filename): yield (logical_line.index(exception_msg), msg) +@core.flake8ext def no_translate_logs(logical_line, filename): """N537 - Don't translate logs. diff --git a/neutron_lib/placement/client.py b/neutron_lib/placement/client.py index 30dda2c8a..52445e4f0 100644 --- a/neutron_lib/placement/client.py +++ b/neutron_lib/placement/client.py @@ -117,7 +117,7 @@ class NoAuthClient(object): LOG.exception('requests Timeout, let\'s retry it...') except requests.ConnectionError: LOG.exception('Connection Error appeared') - except requests.RequestException as e: + except requests.RequestException: LOG.exception('Some really weird thing happened, let\'s ' 'retry it') time.sleep(self.timeout) diff --git a/neutron_lib/tests/unit/hacking/test_checks.py b/neutron_lib/tests/unit/hacking/test_checks.py index d08d0cf5d..4433edeea 100644 --- a/neutron_lib/tests/unit/hacking/test_checks.py +++ b/neutron_lib/tests/unit/hacking/test_checks.py @@ -40,17 +40,6 @@ class HackingTestCase(base.BaseTestCase): def test_factory(self): self.assertGreater(len(self._get_factory_checks(checks.factory)), 0) - def test_neutron_lib_factory(self): - lib_checks = self._get_factory_checks(checks._neutron_lib_factory) - other_checks = self._get_factory_checks(checks.factory) - - self.assertGreater(len(lib_checks), 0) - - if other_checks: - for other_check in other_checks: - # lib checks are superset of all checks - self.assertTrue(other_check in lib_checks) - def test_use_jsonutils(self): def __get_msg(fun): msg = ("N521: jsonutils.%(fun)s must be used instead of " diff --git a/test-requirements.txt b/test-requirements.txt index 81e2e8311..1bdb04264 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -2,7 +2,7 @@ # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. -hacking>=1.1.0,<1.2.0 # Apache-2.0 +hacking>=2.0.0,<2.1 # Apache-2.0 bandit!=1.6.0,>=1.1.0 # Apache-2.0 coverage!=4.4,>=4.0 # Apache-2.0 diff --git a/tox.ini b/tox.ini index b4913b6d9..206be29a7 100644 --- a/tox.ini +++ b/tox.ini @@ -101,6 +101,20 @@ show-source = True exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build,tools import-order-style = pep8 +[flake8:local-plugins] +extension = + # Checks for neutron and related projects + N521 = neutron_lib.hacking.checks:use_jsonutils + N524 = neutron_lib.hacking.checks:check_no_contextlib_nested + N529 = neutron_lib.hacking.checks:no_mutable_default_args + N530 = neutron_lib.hacking.checks:check_neutron_namespace_imports + N532 = neutron_lib.hacking.translation_checks:check_log_warn_deprecated + N534 = neutron_lib.hacking.translation_checks:check_raised_localized_exceptions + N536 = neutron_lib.hacking.checks:assert_equal_none + N537 = neutron_lib.hacking.translation_checks:no_translate_logs + # Checks specific to neutron-lib only + N535 = neutron_lib.hacking.checks:check_no_eventlet_imports + [testenv:bandit] # B104: Possible binding to all interfaces # B303: Blacklist use of insecure MD2, MD4, MD5, or SHA1 hash functions @@ -110,7 +124,6 @@ commands = bandit -r neutron_lib -x tests -n5 -s B104,B303,B311 [hacking] import_exceptions = neutron_lib._i18n -local-check-factory = neutron_lib.hacking.checks._neutron_lib_factory [testenv:lower-constraints] deps =