author | Andrew Halberstadt <ahalberstadt@mozilla.com> |
Mon, 13 Apr 2015 15:36:56 -0400 | |
changeset 239689 | 15b5a4242cf2d6ff9fa875bb1bb1f10327210117 |
parent 239688 | cf8981c64f564160c881699a8c644c6930980b24 |
child 239690 | 905f210de15b765757b461479fa61dac3b838a68 |
push id | 58615 |
push user | ahalberstadt@mozilla.com |
push date | Fri, 17 Apr 2015 18:18:34 +0000 |
treeherder | mozilla-inbound@15b5a4242cf2 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | gps |
bugs | 1154006 |
milestone | 40.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/python/mach/mach/base.py +++ b/python/mach/mach/base.py @@ -78,16 +78,17 @@ class MethodHandler(object): 'description', # Functions used to 'skip' commands if they don't meet the conditions # in a given context. 'conditions', # argparse.ArgumentParser instance to use as the basis for command # arguments. + '_parser', 'parser', # Arguments added to this command's parser. This is a 2-tuple of # positional and named arguments, respectively. 'arguments', # Argument groups added to this command's parser. 'argument_group_names', @@ -103,13 +104,22 @@ class MethodHandler(object): subcommand_handlers=None): self.cls = cls self.method = method self.name = name self.category = category self.description = description self.conditions = conditions or [] - self.parser = parser self.arguments = arguments or [] self.argument_group_names = argument_group_names or [] self.pass_context = pass_context self.subcommand_handlers = subcommand_handlers or {} + self._parser = parser + + @property + def parser(self): + # creating cli parsers at command dispatch time can potentially be + # expensive, make it possible to lazy load them. + if callable(self._parser): + self._parser = self._parser() + return self._parser +
--- a/python/mach/mach/decorators.py +++ b/python/mach/mach/decorators.py @@ -142,18 +142,19 @@ class Command(object): The decorator accepts arguments that define basic attributes of the command. The following arguments are recognized: category -- The string category to which this command belongs. Mach's help will group commands by category. description -- A brief description of what the command does. - parser -- an optional argparse.ArgumentParser instance to use as - the basis for the command arguments. + parser -- an optional argparse.ArgumentParser instance or callable + that returns an argparse.ArgumentParser instance to use as the + basis for the command arguments. For example: @Command('foo', category='misc', description='Run the foo action') def foo(self): pass """ def __init__(self, name, category=None, description=None, conditions=None,
--- a/python/mach/mach/dispatcher.py +++ b/python/mach/mach/dispatcher.py @@ -166,16 +166,17 @@ class CommandAction(argparse.Action): parser_args = { 'add_help': False, 'usage': usage, } if handler.parser: subparser = handler.parser + subparser.context = self._context else: subparser = argparse.ArgumentParser(**parser_args) remainder = None for arg in handler.arguments: # Remove our group keyword; it's not needed here. group_name = arg[1].get('group') @@ -320,16 +321,17 @@ class CommandAction(argparse.Action): # the help output. parser_args = { 'formatter_class': CommandFormatter, 'add_help': False, } if handler.parser: c_parser = handler.parser + c_parser.context = self._context c_parser.formatter_class = NoUsageFormatter # Accessing _action_groups is a bit shady. We are highly dependent # on the argparse implementation not changing. We fail fast to # detect upstream changes so we can intelligently react to them. group = c_parser._action_groups[1] # By default argparse adds two groups called "positional arguments" # and "optional arguments". We want to rename these to reflect standard
--- a/testing/mochitest/mach_commands.py +++ b/testing/mochitest/mach_commands.py @@ -789,18 +789,16 @@ def setup_argument_parser(): b2g_args = parser.add_argument_group('B2G Arguments', 'Arguments specific \ to running mochitest on B2G devices and emulator') b2g_args = add_mochitest_b2g_args(b2g_args) structured.commandline.add_logging_group(parser) return parser -_st_parser = setup_argument_parser() - # condition filters def is_platform_in(*platforms): def is_platform_supported(cls): for p in platforms: c = getattr(conditions, 'is_{}'.format(p), None) if c and c(cls): @@ -834,56 +832,56 @@ class MachCommands(MachCommandBase): for attr in ('b2g_home', 'xre_path', 'device_name', 'target_out'): setattr(self, attr, getattr(context, attr, None)) @Command( 'mochitest-plain', category='testing', conditions=[is_platform_in('firefox', 'mulet', 'b2g', 'b2g_desktop', 'android')], description='Run a plain mochitest (integration test, plain web page).', - parser=_st_parser) + parser=setup_argument_parser) def run_mochitest_plain(self, test_paths, **kwargs): if is_platform_in('firefox', 'mulet')(self): return self.run_mochitest(test_paths, 'plain', **kwargs) elif conditions.is_emulator(self): return self.run_mochitest_remote(test_paths, **kwargs) elif conditions.is_b2g_desktop(self): return self.run_b2g_desktop(test_paths, **kwargs) elif conditions.is_android(self): return self.run_mochitest_android(test_paths, **kwargs) @Command( 'mochitest-chrome', category='testing', conditions=[is_platform_in('firefox', 'emulator', 'android')], description='Run a chrome mochitest (integration test with some XUL).', - parser=_st_parser) + parser=setup_argument_parser) def run_mochitest_chrome(self, test_paths, **kwargs): if conditions.is_firefox(self): return self.run_mochitest(test_paths, 'chrome', **kwargs) elif conditions.is_b2g(self) and conditions.is_emulator(self): return self.run_mochitest_remote(test_paths, chrome=True, **kwargs) elif conditions.is_android(self): return self.run_mochitest_android(test_paths, chrome=True, **kwargs) @Command( 'mochitest-browser', category='testing', conditions=[conditions.is_firefox], description='Run a mochitest with browser chrome (integration test with a standard browser).', - parser=_st_parser) + parser=setup_argument_parser) def run_mochitest_browser(self, test_paths, **kwargs): return self.run_mochitest(test_paths, 'browser', **kwargs) @Command( 'mochitest-devtools', category='testing', conditions=[conditions.is_firefox], description='Run a devtools mochitest with browser chrome (integration test with a standard browser with the devtools frame).', - parser=_st_parser) + parser=setup_argument_parser) def run_mochitest_devtools(self, test_paths, **kwargs): return self.run_mochitest(test_paths, 'devtools', **kwargs) @Command('jetpack-package', category='testing', conditions=[conditions.is_firefox], description='Run a jetpack package test.') def run_mochitest_jetpack_package(self, test_paths, **kwargs): return self.run_mochitest(test_paths, 'jetpack-package', **kwargs) @@ -894,49 +892,49 @@ class MachCommands(MachCommandBase): def run_mochitest_jetpack_addon(self, test_paths, **kwargs): return self.run_mochitest(test_paths, 'jetpack-addon', **kwargs) @Command( 'mochitest-metro', category='testing', conditions=[conditions.is_firefox], description='Run a mochitest with metro browser chrome (tests for Windows touch interface).', - parser=_st_parser) + parser=setup_argument_parser) def run_mochitest_metro(self, test_paths, **kwargs): return self.run_mochitest(test_paths, 'metro', **kwargs) @Command('mochitest-a11y', category='testing', conditions=[conditions.is_firefox], description='Run an a11y mochitest (accessibility tests).', - parser=_st_parser) + parser=setup_argument_parser) def run_mochitest_a11y(self, test_paths, **kwargs): return self.run_mochitest(test_paths, 'a11y', **kwargs) @Command( 'webapprt-test-chrome', category='testing', conditions=[conditions.is_firefox], description='Run a webapprt chrome mochitest (Web App Runtime with the browser chrome).', - parser=_st_parser) + parser=setup_argument_parser) def run_mochitest_webapprt_chrome(self, test_paths, **kwargs): return self.run_mochitest(test_paths, 'webapprt-chrome', **kwargs) @Command( 'webapprt-test-content', category='testing', conditions=[conditions.is_firefox], description='Run a webapprt content mochitest (Content rendering of the Web App Runtime).', - parser=_st_parser) + parser=setup_argument_parser) def run_mochitest_webapprt_content(self, test_paths, **kwargs): return self.run_mochitest(test_paths, 'webapprt-content', **kwargs) @Command('mochitest', category='testing', conditions=[conditions.is_firefox], description='Run any flavor of mochitest (integration test).', - parser=_st_parser) + parser=setup_argument_parser) @CommandArgument('-f', '--flavor', choices=FLAVORS.keys(), help='Only run tests of this flavor.') def run_mochitest_general(self, test_paths, flavor=None, test_objects=None, **kwargs): self._preruntest() from mozbuild.testing import TestResolver