qa : fixed flake8 issues
This commit is contained in:
		@@ -37,7 +37,8 @@
 | 
			
		||||
#
 | 
			
		||||
# Settings for commands that modify configuration
 | 
			
		||||
#
 | 
			
		||||
# Commands that modify confguration By default modify the *highest* priority scope.
 | 
			
		||||
# Commands that modify confguration By default modify the *highest*
 | 
			
		||||
# priority scope.
 | 
			
		||||
default_modify_scope = spack.config.highest_precedence_scope().name
 | 
			
		||||
# Commands that list confguration list *all* scopes by default.
 | 
			
		||||
default_list_scope = None
 | 
			
		||||
@@ -49,7 +50,7 @@
 | 
			
		||||
ignore_files = r'^\.|^__init__.py$|^#'
 | 
			
		||||
 | 
			
		||||
SETUP_PARSER = "setup_parser"
 | 
			
		||||
DESCRIPTION  = "description"
 | 
			
		||||
DESCRIPTION = "description"
 | 
			
		||||
 | 
			
		||||
command_path = os.path.join(spack.lib_path, "spack", "cmd")
 | 
			
		||||
 | 
			
		||||
@@ -72,7 +73,7 @@ def get_module(name):
 | 
			
		||||
        module_name, fromlist=[name, SETUP_PARSER, DESCRIPTION],
 | 
			
		||||
        level=0)
 | 
			
		||||
 | 
			
		||||
    attr_setdefault(module, SETUP_PARSER, lambda *args: None) # null-op
 | 
			
		||||
    attr_setdefault(module, SETUP_PARSER, lambda *args: None)  # null-op
 | 
			
		||||
    attr_setdefault(module, DESCRIPTION, "")
 | 
			
		||||
 | 
			
		||||
    fn_name = get_cmd_function_name(name)
 | 
			
		||||
@@ -102,17 +103,17 @@ def parse_specs(args, **kwargs):
 | 
			
		||||
        specs = spack.spec.parse(args)
 | 
			
		||||
        for spec in specs:
 | 
			
		||||
            if concretize:
 | 
			
		||||
                spec.concretize() # implies normalize
 | 
			
		||||
                spec.concretize()  # implies normalize
 | 
			
		||||
            elif normalize:
 | 
			
		||||
                spec.normalize()
 | 
			
		||||
 | 
			
		||||
        return specs
 | 
			
		||||
 | 
			
		||||
    except spack.parse.ParseError, e:
 | 
			
		||||
    except spack.parse.ParseError as e:
 | 
			
		||||
        tty.error(e.message, e.string, e.pos * " " + "^")
 | 
			
		||||
        sys.exit(1)
 | 
			
		||||
 | 
			
		||||
    except spack.spec.SpecError, e:
 | 
			
		||||
    except spack.spec.SpecError as e:
 | 
			
		||||
        tty.error(e.message)
 | 
			
		||||
        sys.exit(1)
 | 
			
		||||
 | 
			
		||||
@@ -128,7 +129,7 @@ def elide_list(line_list, max_num=10):
 | 
			
		||||
           [1, 2, 3, '...', 6]
 | 
			
		||||
    """
 | 
			
		||||
    if len(line_list) > max_num:
 | 
			
		||||
        return line_list[:max_num-1] + ['...'] + line_list[-1:]
 | 
			
		||||
        return line_list[:max_num - 1] + ['...'] + line_list[-1:]
 | 
			
		||||
    else:
 | 
			
		||||
        return line_list
 | 
			
		||||
 | 
			
		||||
@@ -139,8 +140,8 @@ def disambiguate_spec(spec):
 | 
			
		||||
        tty.die("Spec '%s' matches no installed packages." % spec)
 | 
			
		||||
 | 
			
		||||
    elif len(matching_specs) > 1:
 | 
			
		||||
        args =  ["%s matches multiple packages." % spec,
 | 
			
		||||
                 "Matching packages:"]
 | 
			
		||||
        args = ["%s matches multiple packages." % spec,
 | 
			
		||||
                "Matching packages:"]
 | 
			
		||||
        args += ["  " + str(s) for s in matching_specs]
 | 
			
		||||
        args += ["Use a more specific spec."]
 | 
			
		||||
        tty.die(*args)
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@
 | 
			
		||||
def add_common_arguments(parser, list_of_arguments):
 | 
			
		||||
    for argument in list_of_arguments:
 | 
			
		||||
        if argument not in _arguments:
 | 
			
		||||
            message = 'Trying to add the non existing argument "{0}" to a command'
 | 
			
		||||
            message = 'Trying to add the non existing argument "{0}" to a command'  # NOQA: ignore=E501
 | 
			
		||||
            raise KeyError(message.format(argument))
 | 
			
		||||
        x = _arguments[argument]
 | 
			
		||||
        parser.add_argument(*x.flags, **x.kwargs)
 | 
			
		||||
@@ -44,9 +44,9 @@ def add_common_arguments(parser, list_of_arguments):
 | 
			
		||||
class ConstraintAction(argparse.Action):
 | 
			
		||||
    """Constructs a list of specs based on a constraint given on the command line
 | 
			
		||||
 | 
			
		||||
    An instance of this class is supposed to be used as an argument action in a parser.
 | 
			
		||||
 | 
			
		||||
    It will read a constraint and will attach a list of matching specs to the namespace
 | 
			
		||||
    An instance of this class is supposed to be used as an argument action
 | 
			
		||||
    in a parser. It will read a constraint and will attach a list of matching
 | 
			
		||||
    specs to the namespace
 | 
			
		||||
    """
 | 
			
		||||
    qualifiers = {}
 | 
			
		||||
 | 
			
		||||
@@ -59,30 +59,38 @@ def __call__(self, parser, namespace, values, option_string=None):
 | 
			
		||||
            specs = [x for x in specs if x.satisfies(values, strict=True)]
 | 
			
		||||
        namespace.specs = specs
 | 
			
		||||
 | 
			
		||||
_arguments['constraint'] = Bunch(flags=('constraint',),
 | 
			
		||||
                                 kwargs={
 | 
			
		||||
                                     'nargs': '*',
 | 
			
		||||
                                     'help': 'Optional constraint to select a subset of installed packages',
 | 
			
		||||
                                     'action': ConstraintAction
 | 
			
		||||
                                 })
 | 
			
		||||
parms = Bunch(
 | 
			
		||||
    flags=('constraint',),
 | 
			
		||||
    kwargs={
 | 
			
		||||
        'nargs': '*',
 | 
			
		||||
        'help': 'Constraint to select a subset of installed packages',
 | 
			
		||||
        'action': ConstraintAction
 | 
			
		||||
    })
 | 
			
		||||
_arguments['constraint'] = parms
 | 
			
		||||
 | 
			
		||||
_arguments['module_type'] = Bunch(flags=('-m', '--module-type'),
 | 
			
		||||
                                  kwargs={
 | 
			
		||||
                                      'help': 'Type of module files',
 | 
			
		||||
                                      'default': 'tcl',
 | 
			
		||||
                                      'choices': spack.modules.module_types
 | 
			
		||||
                                  })
 | 
			
		||||
parms = Bunch(
 | 
			
		||||
    flags=('-m', '--module-type'),
 | 
			
		||||
    kwargs={
 | 
			
		||||
        'help': 'Type of module files',
 | 
			
		||||
        'default': 'tcl',
 | 
			
		||||
        'choices': spack.modules.module_types
 | 
			
		||||
    })
 | 
			
		||||
_arguments['module_type'] = parms
 | 
			
		||||
 | 
			
		||||
_arguments['yes_to_all'] = Bunch(flags=('-y', '--yes-to-all'),
 | 
			
		||||
                                 kwargs={
 | 
			
		||||
                                     'action': 'store_true',
 | 
			
		||||
                                     'dest': 'yes_to_all',
 | 
			
		||||
                                     'help': 'Assume "yes" is the answer to every confirmation asked to the user.'
 | 
			
		||||
                                 })
 | 
			
		||||
parms = Bunch(
 | 
			
		||||
    flags=('-y', '--yes-to-all'),
 | 
			
		||||
    kwargs={
 | 
			
		||||
        'action': 'store_true',
 | 
			
		||||
        'dest': 'yes_to_all',
 | 
			
		||||
        'help': 'Assume "yes" is the answer to every confirmation asked to the user.'  # NOQA: ignore=E501
 | 
			
		||||
    })
 | 
			
		||||
_arguments['yes_to_all'] = parms
 | 
			
		||||
 | 
			
		||||
_arguments['recurse_dependencies'] = Bunch(flags=('-r', '--dependencies'),
 | 
			
		||||
                                           kwargs={
 | 
			
		||||
                                               'action': 'store_true',
 | 
			
		||||
                                               'dest': 'recurse_dependencies',
 | 
			
		||||
                                               'help': 'Recursively traverse spec dependencies'
 | 
			
		||||
                                           })
 | 
			
		||||
parms = Bunch(
 | 
			
		||||
    flags=('-r', '--dependencies'),
 | 
			
		||||
    kwargs={
 | 
			
		||||
        'action': 'store_true',
 | 
			
		||||
        'dest': 'recurse_dependencies',
 | 
			
		||||
        'help': 'Recursively traverse spec dependencies'
 | 
			
		||||
    })
 | 
			
		||||
_arguments['recurse_dependencies'] = parms
 | 
			
		||||
 
 | 
			
		||||
@@ -58,8 +58,14 @@ def setup_parser(subparser):
 | 
			
		||||
 | 
			
		||||
    # spack module refresh
 | 
			
		||||
    refresh_parser = sp.add_parser('refresh', help='Regenerate module files')
 | 
			
		||||
    refresh_parser.add_argument('--delete-tree', help='Delete the module file tree before refresh', action='store_true')
 | 
			
		||||
    arguments.add_common_arguments(refresh_parser, ['constraint', 'module_type', 'yes_to_all'])
 | 
			
		||||
    refresh_parser.add_argument(
 | 
			
		||||
        '--delete-tree',
 | 
			
		||||
        help='Delete the module file tree before refresh',
 | 
			
		||||
        action='store_true'
 | 
			
		||||
    )
 | 
			
		||||
    arguments.add_common_arguments(
 | 
			
		||||
        refresh_parser, ['constraint', 'module_type', 'yes_to_all']
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    # spack module find
 | 
			
		||||
    find_parser = sp.add_parser('find', help='Find module files for packages')
 | 
			
		||||
@@ -67,12 +73,14 @@ def setup_parser(subparser):
 | 
			
		||||
 | 
			
		||||
    # spack module rm
 | 
			
		||||
    rm_parser = sp.add_parser('rm', help='Remove module files')
 | 
			
		||||
    arguments.add_common_arguments(rm_parser, ['constraint', 'module_type', 'yes_to_all'])
 | 
			
		||||
    arguments.add_common_arguments(
 | 
			
		||||
        rm_parser, ['constraint', 'module_type', 'yes_to_all']
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    # spack module loads
 | 
			
		||||
    loads_parser = sp.add_parser(
 | 
			
		||||
        'loads',
 | 
			
		||||
        help='Prompt the list of modules associated with packages that satisfy a constraint'
 | 
			
		||||
        help='Prompt the list of modules associated with a constraint'
 | 
			
		||||
    )
 | 
			
		||||
    loads_parser.add_argument(
 | 
			
		||||
        '--input-only', action='store_false', dest='shell',
 | 
			
		||||
@@ -82,7 +90,9 @@ def setup_parser(subparser):
 | 
			
		||||
        '-p', '--prefix', dest='prefix', default='',
 | 
			
		||||
        help='Prepend to module names when issuing module load commands'
 | 
			
		||||
    )
 | 
			
		||||
    arguments.add_common_arguments(loads_parser, ['constraint', 'module_type', 'recurse_dependencies'])
 | 
			
		||||
    arguments.add_common_arguments(
 | 
			
		||||
        loads_parser, ['constraint', 'module_type', 'recurse_dependencies']
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MultipleMatches(Exception):
 | 
			
		||||
@@ -100,20 +110,20 @@ def loads(mtype, specs, args):
 | 
			
		||||
    if args.recurse_dependencies:
 | 
			
		||||
        specs_from_user_constraint = specs[:]
 | 
			
		||||
        specs = []
 | 
			
		||||
        # FIXME : during module file creation nodes seem to be visited multiple
 | 
			
		||||
        # FIXME : times even if cover='nodes' is given. This work around permits
 | 
			
		||||
        # FIXME : to get a unique list of spec anyhow. Do we miss a merge
 | 
			
		||||
        # FIXME : step among nodes that refer to the same package?
 | 
			
		||||
        # FIXME : during module file creation nodes seem to be visited
 | 
			
		||||
        # FIXME : multiple times even if cover='nodes' is given. This
 | 
			
		||||
        # FIXME : work around permits to get a unique list of spec anyhow.
 | 
			
		||||
        # FIXME : (same problem as in spack/modules.py)
 | 
			
		||||
        seen = set()
 | 
			
		||||
        seen_add = seen.add
 | 
			
		||||
        for spec in specs_from_user_constraint:
 | 
			
		||||
            specs.extend(
 | 
			
		||||
                [item for item in spec.traverse(order='post', cover='nodes') if not (item in seen or seen_add(item))]
 | 
			
		||||
                [item for item in spec.traverse(order='post', cover='nodes') if not (item in seen or seen_add(item))]  # NOQA: ignore=E501
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
    module_cls = module_types[mtype]
 | 
			
		||||
    modules = [(spec, module_cls(spec).use_name) for spec in specs if os.path.exists(module_cls(spec).file_name)]
 | 
			
		||||
    modules = [(spec, module_cls(spec).use_name)
 | 
			
		||||
               for spec in specs if os.path.exists(module_cls(spec).file_name)]
 | 
			
		||||
 | 
			
		||||
    module_commands = {
 | 
			
		||||
        'tcl': 'module load ',
 | 
			
		||||
@@ -127,7 +137,8 @@ def loads(mtype, specs, args):
 | 
			
		||||
 | 
			
		||||
    prompt_template = '{comment}{command}{prefix}{name}'
 | 
			
		||||
    for spec, mod in modules:
 | 
			
		||||
        d['comment'] = '' if not args.shell else '# {0}\n'.format(spec.format())
 | 
			
		||||
        d['comment'] = '' if not args.shell else '# {0}\n'.format(
 | 
			
		||||
            spec.format())
 | 
			
		||||
        d['name'] = mod
 | 
			
		||||
        print(prompt_template.format(**d))
 | 
			
		||||
 | 
			
		||||
@@ -157,7 +168,8 @@ def find(mtype, specs, args):
 | 
			
		||||
def rm(mtype, specs, args):
 | 
			
		||||
    """Deletes module files associated with items in specs"""
 | 
			
		||||
    module_cls = module_types[mtype]
 | 
			
		||||
    specs_with_modules = [spec for spec in specs if os.path.exists(module_cls(spec).file_name)]
 | 
			
		||||
    specs_with_modules = [
 | 
			
		||||
        spec for spec in specs if os.path.exists(module_cls(spec).file_name)]
 | 
			
		||||
    modules = [module_cls(spec) for spec in specs_with_modules]
 | 
			
		||||
 | 
			
		||||
    if not modules:
 | 
			
		||||
@@ -166,7 +178,7 @@ def rm(mtype, specs, args):
 | 
			
		||||
 | 
			
		||||
    # Ask for confirmation
 | 
			
		||||
    if not args.yes_to_all:
 | 
			
		||||
        tty.msg('You are about to remove {0} module files the following specs:\n'.format(mtype))
 | 
			
		||||
        tty.msg('You are about to remove {0} module files the following specs:\n'.format(mtype))  # NOQA: ignore=E501
 | 
			
		||||
        spack.cmd.display_specs(specs_with_modules, long=True)
 | 
			
		||||
        print('')
 | 
			
		||||
        spack.cmd.ask_for_confirmation('Do you want to proceed ? ')
 | 
			
		||||
@@ -185,7 +197,7 @@ def refresh(mtype, specs, args):
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    if not args.yes_to_all:
 | 
			
		||||
        tty.msg('You are about to regenerate {name} module files for the following specs:\n'.format(name=mtype))
 | 
			
		||||
        tty.msg('You are about to regenerate {name} module files for the following specs:\n'.format(name=mtype))  # NOQA: ignore=E501
 | 
			
		||||
        spack.cmd.display_specs(specs, long=True)
 | 
			
		||||
        print('')
 | 
			
		||||
        spack.cmd.ask_for_confirmation('Do you want to proceed ? ')
 | 
			
		||||
@@ -233,11 +245,11 @@ def module(parser, args):
 | 
			
		||||
    try:
 | 
			
		||||
        callbacks[args.subparser_name](module_type, args.specs, args)
 | 
			
		||||
    except MultipleMatches:
 | 
			
		||||
        message = 'the constraint \'{query}\' matches multiple packages, and this is not allowed in this context'
 | 
			
		||||
        message = 'the constraint \'{query}\' matches multiple packages, and this is not allowed in this context'  # NOQA: ignore=E501
 | 
			
		||||
        tty.error(message.format(query=constraint))
 | 
			
		||||
        for s in args.specs:
 | 
			
		||||
            sys.stderr.write(s.format(color=True) + '\n')
 | 
			
		||||
        raise SystemExit(1)
 | 
			
		||||
    except NoMatch:
 | 
			
		||||
        message = 'the constraint \'{query}\' match no package, and this is not allowed in this context'
 | 
			
		||||
        message = 'the constraint \'{query}\' match no package, and this is not allowed in this context'  # NOQA: ignore=E501
 | 
			
		||||
        tty.die(message.format(query=constraint))
 | 
			
		||||
 
 | 
			
		||||
@@ -42,7 +42,7 @@
 | 
			
		||||
display_args = {
 | 
			
		||||
    'long': True,
 | 
			
		||||
    'show_flags': True,
 | 
			
		||||
    'variants':True
 | 
			
		||||
    'variants': True
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -53,32 +53,37 @@ def setup_parser(subparser):
 | 
			
		||||
    subparser.add_argument(
 | 
			
		||||
        '-a', '--all', action='store_true', dest='all',
 | 
			
		||||
        help="USE CAREFULLY. Remove ALL installed packages that match each " +
 | 
			
		||||
             "supplied spec. i.e., if you say uninstall libelf, ALL versions of " +
 | 
			
		||||
             "libelf are uninstalled. This is both useful and dangerous, like rm -r.")
 | 
			
		||||
             "supplied spec. i.e., if you say uninstall libelf, ALL versions of " +  # NOQA: ignore=E501
 | 
			
		||||
             "libelf are uninstalled. This is both useful and dangerous, like rm -r.")  # NOQA: ignore=E501
 | 
			
		||||
    subparser.add_argument(
 | 
			
		||||
        '-d', '--dependents', action='store_true', dest='dependents',
 | 
			
		||||
        help='Also uninstall any packages that depend on the ones given via command line.'
 | 
			
		||||
        help='Also uninstall any packages that depend on the ones given via command line.'  # NOQA: ignore=E501
 | 
			
		||||
    )
 | 
			
		||||
    subparser.add_argument(
 | 
			
		||||
        '-y', '--yes-to-all', action='store_true', dest='yes_to_all',
 | 
			
		||||
        help='Assume "yes" is the answer to every confirmation asked to the user.'
 | 
			
		||||
        help='Assume "yes" is the answer to every confirmation asked to the user.'  # NOQA: ignore=E501
 | 
			
		||||
 | 
			
		||||
    )
 | 
			
		||||
    subparser.add_argument('packages', nargs=argparse.REMAINDER, help="specs of packages to uninstall")
 | 
			
		||||
    subparser.add_argument(
 | 
			
		||||
        'packages',
 | 
			
		||||
        nargs=argparse.REMAINDER,
 | 
			
		||||
        help="specs of packages to uninstall"
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def concretize_specs(specs, allow_multiple_matches=False, force=False):
 | 
			
		||||
    """
 | 
			
		||||
    Returns a list of specs matching the non necessarily concretized specs given from cli
 | 
			
		||||
    """Returns a list of specs matching the non necessarily
 | 
			
		||||
    concretized specs given from cli
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        specs: list of specs to be matched against installed packages
 | 
			
		||||
        allow_multiple_matches : boolean (if True multiple matches for each item in specs are admitted)
 | 
			
		||||
        allow_multiple_matches : if True multiple matches are admitted
 | 
			
		||||
 | 
			
		||||
    Return:
 | 
			
		||||
        list of specs
 | 
			
		||||
    """
 | 
			
		||||
    specs_from_cli = []  # List of specs that match expressions given via command line
 | 
			
		||||
    # List of specs that match expressions given via command line
 | 
			
		||||
    specs_from_cli = []
 | 
			
		||||
    has_errors = False
 | 
			
		||||
    for spec in specs:
 | 
			
		||||
        matching = spack.installed_db.query(spec)
 | 
			
		||||
@@ -104,8 +109,8 @@ def concretize_specs(specs, allow_multiple_matches=False, force=False):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def installed_dependents(specs):
 | 
			
		||||
    """
 | 
			
		||||
    Returns a dictionary that maps a spec with a list of its installed dependents
 | 
			
		||||
    """Returns a dictionary that maps a spec with a list of its
 | 
			
		||||
    installed dependents
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        specs: list of specs to be checked for dependents
 | 
			
		||||
@@ -135,7 +140,7 @@ def do_uninstall(specs, force):
 | 
			
		||||
        try:
 | 
			
		||||
            # should work if package is known to spack
 | 
			
		||||
            packages.append(item.package)
 | 
			
		||||
        except spack.repository.UnknownPackageError as e:
 | 
			
		||||
        except spack.repository.UnknownPackageError:
 | 
			
		||||
            # The package.py file has gone away -- but still
 | 
			
		||||
            # want to uninstall.
 | 
			
		||||
            spack.Package(item).do_uninstall(force=True)
 | 
			
		||||
@@ -157,14 +162,17 @@ def uninstall(parser, args):
 | 
			
		||||
    with spack.installed_db.write_transaction():
 | 
			
		||||
        specs = spack.cmd.parse_specs(args.packages)
 | 
			
		||||
        # Gets the list of installed specs that match the ones give via cli
 | 
			
		||||
        uninstall_list = concretize_specs(specs, args.all, args.force)  # takes care of '-a' is given in the cli
 | 
			
		||||
        dependent_list = installed_dependents(uninstall_list)  # takes care of '-d'
 | 
			
		||||
        # takes care of '-a' is given in the cli
 | 
			
		||||
        uninstall_list = concretize_specs(specs, args.all, args.force)
 | 
			
		||||
        dependent_list = installed_dependents(
 | 
			
		||||
            uninstall_list)  # takes care of '-d'
 | 
			
		||||
 | 
			
		||||
        # Process dependent_list and update uninstall_list
 | 
			
		||||
        has_error = False
 | 
			
		||||
        if dependent_list and not args.dependents and not args.force:
 | 
			
		||||
            for spec, lst in dependent_list.items():
 | 
			
		||||
                tty.error("Will not uninstall %s" % spec.format("$_$@$%@$#", color=True))
 | 
			
		||||
                tty.error("Will not uninstall %s" %
 | 
			
		||||
                          spec.format("$_$@$%@$#", color=True))
 | 
			
		||||
                print('')
 | 
			
		||||
                print("The following packages depend on it:")
 | 
			
		||||
                spack.cmd.display_specs(lst, **display_args)
 | 
			
		||||
@@ -176,7 +184,7 @@ def uninstall(parser, args):
 | 
			
		||||
            uninstall_list = list(set(uninstall_list))
 | 
			
		||||
 | 
			
		||||
        if has_error:
 | 
			
		||||
            tty.die('You can use spack uninstall --dependents to uninstall these dependencies as well')
 | 
			
		||||
            tty.die('You can use spack uninstall --dependents to uninstall these dependencies as well')  # NOQA: ignore=E501
 | 
			
		||||
 | 
			
		||||
        if not args.yes_to_all:
 | 
			
		||||
            tty.msg("The following packages will be uninstalled : ")
 | 
			
		||||
 
 | 
			
		||||
@@ -188,7 +188,8 @@ def parse_config_options(module_generator):
 | 
			
		||||
    #####
 | 
			
		||||
 | 
			
		||||
    # Automatic loading loads
 | 
			
		||||
    module_file_actions['hash_length'] = module_configuration.get('hash_length', 7)
 | 
			
		||||
    module_file_actions['hash_length'] = module_configuration.get(
 | 
			
		||||
        'hash_length', 7)
 | 
			
		||||
    module_file_actions['autoload'] = dependencies(
 | 
			
		||||
        module_generator.spec, module_file_actions.get('autoload', 'none'))
 | 
			
		||||
    # Prerequisites
 | 
			
		||||
@@ -238,6 +239,7 @@ class EnvModule(object):
 | 
			
		||||
    formats = {}
 | 
			
		||||
 | 
			
		||||
    class __metaclass__(type):
 | 
			
		||||
 | 
			
		||||
        def __init__(cls, name, bases, dict):
 | 
			
		||||
            type.__init__(cls, name, bases, dict)
 | 
			
		||||
            if cls.name != 'env_module' and cls.name in CONFIGURATION[
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,8 @@
 | 
			
		||||
from spack.test.tally_plugin import Tally
 | 
			
		||||
"""Names of tests to be included in Spack's test suite"""
 | 
			
		||||
 | 
			
		||||
test_names = ['architecture', 'versions', 'url_parse', 'url_substitution', 'packages', 'stage',
 | 
			
		||||
test_names = ['architecture', 'versions', 'url_parse', 'url_substitution',
 | 
			
		||||
              'packages', 'stage',
 | 
			
		||||
              'spec_syntax', 'spec_semantics', 'spec_dag', 'concretize',
 | 
			
		||||
              'multimethod', 'install', 'package_sanity', 'config',
 | 
			
		||||
              'directory_layout', 'pattern', 'python_version', 'git_fetch',
 | 
			
		||||
@@ -40,7 +41,8 @@
 | 
			
		||||
              'cc', 'link_tree', 'spec_yaml', 'optional_deps',
 | 
			
		||||
              'make_executable', 'configure_guess', 'lock', 'database',
 | 
			
		||||
              'namespace_trie', 'yaml', 'sbang', 'environment', 'cmd.find',
 | 
			
		||||
              'cmd.uninstall', 'cmd.test_install', 'cmd.test_compiler_cmd', 'cmd.module']
 | 
			
		||||
              'cmd.uninstall', 'cmd.test_install',
 | 
			
		||||
              'cmd.test_compiler_cmd', 'cmd.module']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def list_tests():
 | 
			
		||||
 
 | 
			
		||||
@@ -31,9 +31,10 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestModule(spack.test.mock_database.MockDatabase):
 | 
			
		||||
 | 
			
		||||
    def _get_module_files(self, args):
 | 
			
		||||
        return [
 | 
			
		||||
            modules.module_types[args.module_type](spec).file_name for spec in args.specs
 | 
			
		||||
            modules.module_types[args.module_type](spec).file_name for spec in args.specs  # NOQA: ignore=E501
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
    def test_module_common_operations(self):
 | 
			
		||||
 
 | 
			
		||||
@@ -28,42 +28,50 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def composite(interface=None, method_list=None, container=list):
 | 
			
		||||
    """
 | 
			
		||||
    Returns a class decorator that patches a class adding all the methods it needs to be a composite for a given
 | 
			
		||||
    interface.
 | 
			
		||||
    """Returns a class decorator that patches a class adding all the methods
 | 
			
		||||
    it needs to be a composite for a given interface.
 | 
			
		||||
 | 
			
		||||
    :param interface: class exposing the interface to which the composite object must conform. Only non-private and
 | 
			
		||||
    non-special methods will be taken into account
 | 
			
		||||
    :param interface: class exposing the interface to which the composite
 | 
			
		||||
    object must conform. Only non-private and non-special methods will be
 | 
			
		||||
    taken into account
 | 
			
		||||
 | 
			
		||||
    :param method_list: names of methods that should be part of the composite
 | 
			
		||||
 | 
			
		||||
    :param container: container for the composite object (default = list). Must fulfill the MutableSequence contract.
 | 
			
		||||
    The composite class will expose the container API to manage object composition
 | 
			
		||||
    :param container: container for the composite object (default = list).
 | 
			
		||||
    Must fulfill the MutableSequence contract. The composite class will expose
 | 
			
		||||
    the container API to manage object composition
 | 
			
		||||
 | 
			
		||||
    :return: class decorator
 | 
			
		||||
    """
 | 
			
		||||
    # Check if container fulfills the MutableSequence contract and raise an exception if it doesn't
 | 
			
		||||
    # The patched class returned by the decorator will inherit from the container class to expose the
 | 
			
		||||
    # interface needed to manage objects composition
 | 
			
		||||
    # Check if container fulfills the MutableSequence contract and raise an
 | 
			
		||||
    # exception if it doesn't. The patched class returned by the decorator will
 | 
			
		||||
    # inherit from the container class to expose the interface needed to manage
 | 
			
		||||
    # objects composition
 | 
			
		||||
    if not issubclass(container, collections.MutableSequence):
 | 
			
		||||
        raise TypeError("Container must fulfill the MutableSequence contract")
 | 
			
		||||
 | 
			
		||||
    # Check if at least one of the 'interface' or the 'method_list' arguments are defined
 | 
			
		||||
    # Check if at least one of the 'interface' or the 'method_list' arguments
 | 
			
		||||
    # are defined
 | 
			
		||||
    if interface is None and method_list is None:
 | 
			
		||||
        raise TypeError("Either 'interface' or 'method_list' must be defined on a call to composite")
 | 
			
		||||
        raise TypeError("Either 'interface' or 'method_list' must be defined on a call to composite")  # NOQA : ignore=E501
 | 
			
		||||
 | 
			
		||||
    def cls_decorator(cls):
 | 
			
		||||
        # Retrieve the base class of the composite. Inspect its methods and decide which ones will be overridden
 | 
			
		||||
        # Retrieve the base class of the composite. Inspect its methods and
 | 
			
		||||
        # decide which ones will be overridden
 | 
			
		||||
        def no_special_no_private(x):
 | 
			
		||||
            return inspect.ismethod(x) and not x.__name__.startswith('_')
 | 
			
		||||
 | 
			
		||||
        # Patch the behavior of each of the methods in the previous list. This is done associating an instance of the
 | 
			
		||||
        # descriptor below to any method that needs to be patched.
 | 
			
		||||
        # Patch the behavior of each of the methods in the previous list.
 | 
			
		||||
        # This is done associating an instance of the descriptor below to
 | 
			
		||||
        # any method that needs to be patched.
 | 
			
		||||
        class IterateOver(object):
 | 
			
		||||
            """Decorator used to patch methods in a composite.
 | 
			
		||||
 | 
			
		||||
            It iterates over all the items in the instance containing the
 | 
			
		||||
            associated attribute and calls for each of them an attribute
 | 
			
		||||
            with the same name
 | 
			
		||||
            """
 | 
			
		||||
            Decorator used to patch methods in a composite. It iterates over all the items in the instance containing the
 | 
			
		||||
            associated attribute and calls for each of them an attribute with the same name
 | 
			
		||||
            """
 | 
			
		||||
 | 
			
		||||
            def __init__(self, name, func=None):
 | 
			
		||||
                self.name = name
 | 
			
		||||
                self.func = func
 | 
			
		||||
@@ -72,8 +80,9 @@ def __get__(self, instance, owner):
 | 
			
		||||
                def getter(*args, **kwargs):
 | 
			
		||||
                    for item in instance:
 | 
			
		||||
                        getattr(item, self.name)(*args, **kwargs)
 | 
			
		||||
                # If we are using this descriptor to wrap a method from an interface, then we must conditionally
 | 
			
		||||
                # use the `functools.wraps` decorator to set the appropriate fields.
 | 
			
		||||
                # If we are using this descriptor to wrap a method from an
 | 
			
		||||
                # interface, then we must conditionally use the
 | 
			
		||||
                # `functools.wraps` decorator to set the appropriate fields
 | 
			
		||||
                if self.func is not None:
 | 
			
		||||
                    getter = functools.wraps(self.func)(getter)
 | 
			
		||||
                return getter
 | 
			
		||||
@@ -81,7 +90,8 @@ def getter(*args, **kwargs):
 | 
			
		||||
        dictionary_for_type_call = {}
 | 
			
		||||
        # Construct a dictionary with the methods explicitly passed as name
 | 
			
		||||
        if method_list is not None:
 | 
			
		||||
            # python@2.7: method_list_dict = {name: IterateOver(name) for name in method_list}
 | 
			
		||||
            # python@2.7: method_list_dict = {name: IterateOver(name) for name
 | 
			
		||||
            # in method_list}
 | 
			
		||||
            method_list_dict = {}
 | 
			
		||||
            for name in method_list:
 | 
			
		||||
                method_list_dict[name] = IterateOver(name)
 | 
			
		||||
@@ -89,28 +99,33 @@ def getter(*args, **kwargs):
 | 
			
		||||
        # Construct a dictionary with the methods inspected from the interface
 | 
			
		||||
        if interface is not None:
 | 
			
		||||
            ##########
 | 
			
		||||
            # python@2.7: interface_methods = {name: method for name, method in inspect.getmembers(interface, predicate=no_special_no_private)}
 | 
			
		||||
            # python@2.7: interface_methods = {name: method for name, method in
 | 
			
		||||
            # inspect.getmembers(interface, predicate=no_special_no_private)}
 | 
			
		||||
            interface_methods = {}
 | 
			
		||||
            for name, method in inspect.getmembers(interface, predicate=no_special_no_private):
 | 
			
		||||
            for name, method in inspect.getmembers(interface, predicate=no_special_no_private):  # NOQA: ignore=E501
 | 
			
		||||
                interface_methods[name] = method
 | 
			
		||||
            ##########
 | 
			
		||||
            # python@2.7: interface_methods_dict = {name: IterateOver(name, method) for name, method in interface_methods.iteritems()}
 | 
			
		||||
            # python@2.7: interface_methods_dict = {name: IterateOver(name,
 | 
			
		||||
            # method) for name, method in interface_methods.iteritems()}
 | 
			
		||||
            interface_methods_dict = {}
 | 
			
		||||
            for name, method in interface_methods.iteritems():
 | 
			
		||||
                interface_methods_dict[name] = IterateOver(name, method)
 | 
			
		||||
            ##########
 | 
			
		||||
            dictionary_for_type_call.update(interface_methods_dict)
 | 
			
		||||
        # Get the methods that are defined in the scope of the composite class and override any previous definition
 | 
			
		||||
        # Get the methods that are defined in the scope of the composite
 | 
			
		||||
        # class and override any previous definition
 | 
			
		||||
        ##########
 | 
			
		||||
        # python@2.7: cls_method = {name: method for name, method in inspect.getmembers(cls, predicate=inspect.ismethod)}
 | 
			
		||||
        # python@2.7: cls_method = {name: method for name, method in
 | 
			
		||||
        # inspect.getmembers(cls, predicate=inspect.ismethod)}
 | 
			
		||||
        cls_method = {}
 | 
			
		||||
        for name, method in inspect.getmembers(cls, predicate=inspect.ismethod):
 | 
			
		||||
        for name, method in inspect.getmembers(cls, predicate=inspect.ismethod):  # NOQA: ignore=E501
 | 
			
		||||
            cls_method[name] = method
 | 
			
		||||
        ##########
 | 
			
		||||
        dictionary_for_type_call.update(cls_method)
 | 
			
		||||
        # Generate the new class on the fly and return it
 | 
			
		||||
        # FIXME : inherit from interface if we start to use ABC classes?
 | 
			
		||||
        wrapper_class = type(cls.__name__, (cls, container), dictionary_for_type_call)
 | 
			
		||||
        wrapper_class = type(cls.__name__, (cls, container),
 | 
			
		||||
                             dictionary_for_type_call)
 | 
			
		||||
        return wrapper_class
 | 
			
		||||
 | 
			
		||||
    return cls_decorator
 | 
			
		||||
@@ -118,5 +133,6 @@ def getter(*args, **kwargs):
 | 
			
		||||
 | 
			
		||||
class Bunch(object):
 | 
			
		||||
    """Carries a bunch of named attributes (from Alex Martelli bunch)"""
 | 
			
		||||
 | 
			
		||||
    def __init__(self, **kwargs):
 | 
			
		||||
        self.__dict__.update(kwargs)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user