argparse: lazily construct common arguments
Continuing to shave small bits of time off startup -- `spack.cmd.common.arguments` constructs many `Args` objects at module scope, which has to be done for all commands that import it. Instead of doing this at load time, do it lazily. - [x] construct Args objects lazily - [x] remove the module-scoped argparse fixture - [x] make the mock config scope set dirty to False by default (like the regular scope) This *seems* to reduce load time slightly
This commit is contained in:
parent
e7dc8a2bea
commit
b2e9696052
3 changed files with 108 additions and 60 deletions
|
@ -18,9 +18,22 @@
|
||||||
|
|
||||||
__all__ = ['add_common_arguments']
|
__all__ = ['add_common_arguments']
|
||||||
|
|
||||||
|
#: dictionary of argument-generating functions, keyed by name
|
||||||
_arguments = {}
|
_arguments = {}
|
||||||
|
|
||||||
|
|
||||||
|
def arg(fn):
|
||||||
|
"""Decorator for a function that generates a common argument.
|
||||||
|
|
||||||
|
This ensures that argument bunches are created lazily. Decorate
|
||||||
|
argument-generating functions below with @arg so that
|
||||||
|
``add_common_arguments()`` can find them.
|
||||||
|
|
||||||
|
"""
|
||||||
|
_arguments[fn.__name__] = fn
|
||||||
|
return fn
|
||||||
|
|
||||||
|
|
||||||
def add_common_arguments(parser, list_of_arguments):
|
def add_common_arguments(parser, list_of_arguments):
|
||||||
"""Extend a parser with extra arguments
|
"""Extend a parser with extra arguments
|
||||||
|
|
||||||
|
@ -32,7 +45,8 @@ def add_common_arguments(parser, list_of_arguments):
|
||||||
if argument not in _arguments:
|
if argument not in _arguments:
|
||||||
message = 'Trying to add non existing argument "{0}" to a command'
|
message = 'Trying to add non existing argument "{0}" to a command'
|
||||||
raise KeyError(message.format(argument))
|
raise KeyError(message.format(argument))
|
||||||
x = _arguments[argument]
|
|
||||||
|
x = _arguments[argument]()
|
||||||
parser.add_argument(*x.flags, **x.kwargs)
|
parser.add_argument(*x.flags, **x.kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@ -118,64 +132,104 @@ def __call__(self, parser, namespace, values, option_string=None):
|
||||||
setattr(namespace, self.dest, deptype)
|
setattr(namespace, self.dest, deptype)
|
||||||
|
|
||||||
|
|
||||||
_arguments['constraint'] = Args(
|
@arg
|
||||||
|
def constraint():
|
||||||
|
return Args(
|
||||||
'constraint', nargs=argparse.REMAINDER, action=ConstraintAction,
|
'constraint', nargs=argparse.REMAINDER, action=ConstraintAction,
|
||||||
help='constraint to select a subset of installed packages')
|
help='constraint to select a subset of installed packages')
|
||||||
|
|
||||||
_arguments['yes_to_all'] = Args(
|
|
||||||
|
@arg
|
||||||
|
def yes_to_all():
|
||||||
|
return Args(
|
||||||
'-y', '--yes-to-all', action='store_true', dest='yes_to_all',
|
'-y', '--yes-to-all', action='store_true', dest='yes_to_all',
|
||||||
help='assume "yes" is the answer to every confirmation request')
|
help='assume "yes" is the answer to every confirmation request')
|
||||||
|
|
||||||
_arguments['recurse_dependencies'] = Args(
|
|
||||||
'-r', '--dependencies', action='store_true', dest='recurse_dependencies',
|
@arg
|
||||||
|
def recurse_dependencies():
|
||||||
|
return Args(
|
||||||
|
'-r', '--dependencies', action='store_true',
|
||||||
|
dest='recurse_dependencies',
|
||||||
help='recursively traverse spec dependencies')
|
help='recursively traverse spec dependencies')
|
||||||
|
|
||||||
_arguments['recurse_dependents'] = Args(
|
|
||||||
|
@arg
|
||||||
|
def recurse_dependents():
|
||||||
|
return Args(
|
||||||
'-R', '--dependents', action='store_true', dest='dependents',
|
'-R', '--dependents', action='store_true', dest='dependents',
|
||||||
help='also uninstall any packages that depend on the ones given '
|
help='also uninstall any packages that depend on the ones given '
|
||||||
'via command line')
|
'via command line')
|
||||||
|
|
||||||
_arguments['clean'] = Args(
|
|
||||||
|
@arg
|
||||||
|
def clean():
|
||||||
|
return Args(
|
||||||
'--clean',
|
'--clean',
|
||||||
action='store_false',
|
action='store_false',
|
||||||
default=spack.config.get('config:dirty'),
|
default=spack.config.get('config:dirty'),
|
||||||
dest='dirty',
|
dest='dirty',
|
||||||
help='unset harmful variables in the build environment (default)')
|
help='unset harmful variables in the build environment (default)')
|
||||||
|
|
||||||
_arguments['deptype'] = Args(
|
|
||||||
|
@arg
|
||||||
|
def deptype():
|
||||||
|
return Args(
|
||||||
'--deptype', action=DeptypeAction, default=dep.all_deptypes,
|
'--deptype', action=DeptypeAction, default=dep.all_deptypes,
|
||||||
help="comma-separated list of deptypes to traverse\ndefault=%s"
|
help="comma-separated list of deptypes to traverse\ndefault=%s"
|
||||||
% ','.join(dep.all_deptypes))
|
% ','.join(dep.all_deptypes))
|
||||||
|
|
||||||
_arguments['dirty'] = Args(
|
|
||||||
|
@arg
|
||||||
|
def dirty():
|
||||||
|
return Args(
|
||||||
'--dirty',
|
'--dirty',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
default=spack.config.get('config:dirty'),
|
default=spack.config.get('config:dirty'),
|
||||||
dest='dirty',
|
dest='dirty',
|
||||||
help='preserve user environment in the spack build environment (danger!)')
|
help="preserve user environment in spack's build environment (danger!)"
|
||||||
|
)
|
||||||
|
|
||||||
_arguments['long'] = Args(
|
|
||||||
|
@arg
|
||||||
|
def long():
|
||||||
|
return Args(
|
||||||
'-l', '--long', action='store_true',
|
'-l', '--long', action='store_true',
|
||||||
help='show dependency hashes as well as versions')
|
help='show dependency hashes as well as versions')
|
||||||
|
|
||||||
_arguments['very_long'] = Args(
|
|
||||||
|
@arg
|
||||||
|
def very_long():
|
||||||
|
return Args(
|
||||||
'-L', '--very-long', action='store_true',
|
'-L', '--very-long', action='store_true',
|
||||||
help='show full dependency hashes as well as versions')
|
help='show full dependency hashes as well as versions')
|
||||||
|
|
||||||
_arguments['tags'] = Args(
|
|
||||||
|
@arg
|
||||||
|
def tags():
|
||||||
|
return Args(
|
||||||
'-t', '--tags', action='append',
|
'-t', '--tags', action='append',
|
||||||
help='filter a package query by tags')
|
help='filter a package query by tags')
|
||||||
|
|
||||||
_arguments['jobs'] = Args(
|
|
||||||
|
@arg
|
||||||
|
def jobs():
|
||||||
|
return Args(
|
||||||
'-j', '--jobs', action=SetParallelJobs, type=int, dest='jobs',
|
'-j', '--jobs', action=SetParallelJobs, type=int, dest='jobs',
|
||||||
help='explicitly set number of parallel jobs')
|
help='explicitly set number of parallel jobs')
|
||||||
|
|
||||||
_arguments['install_status'] = Args(
|
|
||||||
|
@arg
|
||||||
|
def install_status():
|
||||||
|
return Args(
|
||||||
'-I', '--install-status', action='store_true', default=False,
|
'-I', '--install-status', action='store_true', default=False,
|
||||||
help='show install status of packages. packages can be: '
|
help='show install status of packages. packages can be: '
|
||||||
'installed [+], missing and needed by an installed package [-], '
|
'installed [+], missing and needed by an installed package [-], '
|
||||||
'or not installed (no annotation)')
|
'or not installed (no annotation)')
|
||||||
|
|
||||||
_arguments['no_checksum'] = Args(
|
|
||||||
|
@arg
|
||||||
|
def no_checksum():
|
||||||
|
return Args(
|
||||||
'-n', '--no-checksum', action='store_true', default=False,
|
'-n', '--no-checksum', action='store_true', default=False,
|
||||||
help="do not use checksums to verify downloaded files (unsafe)")
|
help="do not use checksums to verify downloaded files (unsafe)")
|
||||||
|
|
|
@ -30,14 +30,6 @@
|
||||||
add = SpackCommand('add')
|
add = SpackCommand('add')
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='module')
|
|
||||||
def parser():
|
|
||||||
"""Returns the parser for the module command"""
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
spack.cmd.install.setup_parser(parser)
|
|
||||||
return parser
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def noop_install(monkeypatch):
|
def noop_install(monkeypatch):
|
||||||
def noop(*args, **kwargs):
|
def noop(*args, **kwargs):
|
||||||
|
@ -115,7 +107,9 @@ def test_install_package_already_installed(
|
||||||
(['--clean'], False),
|
(['--clean'], False),
|
||||||
(['--dirty'], True),
|
(['--dirty'], True),
|
||||||
])
|
])
|
||||||
def test_install_dirty_flag(parser, arguments, expected):
|
def test_install_dirty_flag(arguments, expected):
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
spack.cmd.install.setup_parser(parser)
|
||||||
args = parser.parse_args(arguments)
|
args = parser.parse_args(arguments)
|
||||||
assert args.dirty == expected
|
assert args.dirty == expected
|
||||||
|
|
||||||
|
|
|
@ -11,4 +11,4 @@ config:
|
||||||
misc_cache: ~/.spack/cache
|
misc_cache: ~/.spack/cache
|
||||||
verify_ssl: true
|
verify_ssl: true
|
||||||
checksum: true
|
checksum: true
|
||||||
dirty: True
|
dirty: false
|
||||||
|
|
Loading…
Reference in a new issue