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:
		
							
								
								
									
										10
									
								
								README.rst
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								README.rst
									
									
									
									
									
								
							@@ -129,3 +129,13 @@ register. Such as:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  [hacking]
 | 
					  [hacking]
 | 
				
			||||||
  local-check-factory = nova.tests.hacking.factory
 | 
					  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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -145,20 +145,29 @@ class ProxyChecks(GlobalCheck):
 | 
				
			|||||||
    name = 'ProxyChecker'
 | 
					    name = 'ProxyChecker'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def add_options(cls, parser):
 | 
					    def parse_options(cls, options):
 | 
				
			||||||
        # We're looking for local checks, so we need to include the local
 | 
					        # We're looking for local checks, so we need to include the local
 | 
				
			||||||
        # dir in the search path
 | 
					        # dir in the search path
 | 
				
			||||||
        sys.path.append('.')
 | 
					        sys.path.append('.')
 | 
				
			||||||
 | 
					        local_check_fact = options.factory or CONF.get('local-check-factory')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not options.factory:
 | 
				
			||||||
 | 
					            # local factory on CLI trumps everything else
 | 
				
			||||||
            local_check = CONF.get_multiple('local-check', default=[])
 | 
					            local_check = CONF.get_multiple('local-check', default=[])
 | 
				
			||||||
            for check_path in set(local_check):
 | 
					            for check_path in set(local_check):
 | 
				
			||||||
                if check_path.strip():
 | 
					                if check_path.strip():
 | 
				
			||||||
                    checker = pbr.util.resolve_name(check_path)
 | 
					                    checker = pbr.util.resolve_name(check_path)
 | 
				
			||||||
                    pep8.register_check(checker)
 | 
					                    pep8.register_check(checker)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        local_check_fact = CONF.get('local-check-factory')
 | 
					 | 
				
			||||||
        if local_check_fact:
 | 
					        if local_check_fact:
 | 
				
			||||||
            factory = pbr.util.resolve_name(local_check_fact)
 | 
					            factory = pbr.util.resolve_name(local_check_fact)
 | 
				
			||||||
            factory(pep8.register_check)
 | 
					            factory(pep8.register_check)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        sys.path.pop()
 | 
					        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')
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,8 +14,10 @@
 | 
				
			|||||||
# limitations under the License.
 | 
					# limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from flake8 import engine
 | 
					from flake8 import engine
 | 
				
			||||||
 | 
					import mock
 | 
				
			||||||
import pep8
 | 
					import pep8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from hacking import core
 | 
				
			||||||
import hacking.tests
 | 
					import hacking.tests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -34,3 +36,11 @@ class HackingTestCase(hacking.tests.TestCase):
 | 
				
			|||||||
                               report=report)
 | 
					                               report=report)
 | 
				
			||||||
        checker.check_all()
 | 
					        checker.check_all()
 | 
				
			||||||
        self.assertIn("L100", report.counters)
 | 
					        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)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user