local-check-factory CLI option

Today hacking only provides consumers specifying the local check
factory function via tox.ini (in the '[hacking]' section). While this works
fine in a number of cases, others need a way to specify multiple
check factories without using multiple tox.ini files.

For example, we'd like a library project to define a common set of hacking
check functions for consumers. Some of those factory functions
may register checks we want consumers to run in 'warn only' mode.
From a tox.ini perspective, we'd like to be able to do this:

[testenv:pep8]
commands =
     # run mandatory checks in fail mode
      flake8 --factory a.b.c.mandatory
      # run incubating checks in warn-only mode
      flake8 --factory a.b.c.incubating --exit-zero

Today the above isn't possible without 2 separate tox.ini files;
each to specify the local-check-factory. While we can use our
own flake8 extension [1], it would be better to have this
support built right into hacking enabling a broader set of use
cases.

This patch adds a CLI option called --local-check-factory that
allows consumers to pass a local-check-factory via CLI. If
specified on CLI, it overrides anything in tox.ini. Using this
patch consumers can achieve the use case noted above and this
should also be backwards compatible.

[1] https://review.openstack.org/#/c/350723/14/neutron_lib/hacking/checks.py@286

Change-Id: I26f68e11d21938a13974c4e7684eea604dfc2e69
This commit is contained in:
Boden R 2016-11-15 13:39:40 -07:00
parent 6be124c025
commit e72ce1831a
3 changed files with 36 additions and 7 deletions

View File

@ -129,3 +129,13 @@ register. Such as:
[hacking]
local-check-factory = nova.tests.hacking.factory
In addition, hacking provides a flake8 option to specify the
``local-check-factory`` on the CLI. When specified via CLI with
the ``--local-check-factory`` option to flake8, the specified
factory takes precedence over ``tox.ini`` and the local checks
from ``tox.ini`` are not used.
For example, via CLI (any check specified in ``tox.ini`` are ignored)::
flake8 --local-check-factory mypkg.warn_checks --exit-zero

View File

@ -145,20 +145,29 @@ class ProxyChecks(GlobalCheck):
name = 'ProxyChecker'
@classmethod
def add_options(cls, parser):
def parse_options(cls, options):
# We're looking for local checks, so we need to include the local
# dir in the search path
sys.path.append('.')
local_check_fact = options.factory or CONF.get('local-check-factory')
local_check = CONF.get_multiple('local-check', default=[])
for check_path in set(local_check):
if check_path.strip():
checker = pbr.util.resolve_name(check_path)
pep8.register_check(checker)
if not options.factory:
# local factory on CLI trumps everything else
local_check = CONF.get_multiple('local-check', default=[])
for check_path in set(local_check):
if check_path.strip():
checker = pbr.util.resolve_name(check_path)
pep8.register_check(checker)
local_check_fact = CONF.get('local-check-factory')
if local_check_fact:
factory = pbr.util.resolve_name(local_check_fact)
factory(pep8.register_check)
sys.path.pop()
@classmethod
def add_options(cls, parser):
# allow local check factory to be specified as CLI option to flake8
# in which case its used as the sole source of checks
parser.add_option('--local-check-factory', action='store',
type='string', dest='factory')

View File

@ -14,8 +14,10 @@
# limitations under the License.
from flake8 import engine
import mock
import pep8
from hacking import core
import hacking.tests
@ -34,3 +36,11 @@ class HackingTestCase(hacking.tests.TestCase):
report=report)
checker.check_all()
self.assertIn("L100", report.counters)
@mock.patch.object(core, 'CONF')
def test_local_check_factory_cli_option(self, mock_conf):
mock_opts = mock.Mock()
mock_opts.factory = 'mypkg.factory'
self.assertRaises(
ImportError, core.ProxyChecks.parse_options, mock_opts)
self.assertFalse(mock_conf.called)