From 5b5894afba1c81b286582f4dda8a8f1c94314db7 Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Thu, 3 Nov 2016 08:45:15 +0100 Subject: spack find: accepts anonymous specs as arguments fixes #2170 (#2188) --- lib/spack/spack/cmd/common/arguments.py | 20 +++++++---- lib/spack/spack/cmd/find.py | 59 +++++++++------------------------ lib/spack/spack/cmd/module.py | 8 ++--- lib/spack/spack/test/cmd/find.py | 2 -- lib/spack/spack/test/cmd/module.py | 2 +- 5 files changed, 33 insertions(+), 58 deletions(-) diff --git a/lib/spack/spack/cmd/common/arguments.py b/lib/spack/spack/cmd/common/arguments.py index ade6844813..d5bd4bb711 100644 --- a/lib/spack/spack/cmd/common/arguments.py +++ b/lib/spack/spack/cmd/common/arguments.py @@ -46,19 +46,25 @@ 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 + in a parser. It will read a constraint and will attach a function to the + arguments that accepts optional keyword arguments. + + To obtain the specs from a command the function must be called. """ - qualifiers = {} def __call__(self, parser, namespace, values, option_string=None): # Query specs from command line - d = self.qualifiers.get(namespace.subparser_name, {}) - specs = [s for s in spack.store.db.query(**d)] - values = ' '.join(values) + self.values = values + namespace.contraint = values + namespace.specs = self._specs + + def _specs(self, **kwargs): + specs = [s for s in spack.store.db.query(**kwargs)] + values = ' '.join(self.values) if values: specs = [x for x in specs if x.satisfies(values, strict=True)] - namespace.specs = specs + return specs + _arguments['constraint'] = Args( 'constraint', nargs='*', action=ConstraintAction, diff --git a/lib/spack/spack/cmd/find.py b/lib/spack/spack/cmd/find.py index 50e6112486..29bf263f51 100644 --- a/lib/spack/spack/cmd/find.py +++ b/lib/spack/spack/cmd/find.py @@ -22,16 +22,11 @@ # License along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ############################################################################## -import argparse import sys import llnl.util.tty as tty -import spack -import spack.spec -import spack.store -from llnl.util.lang import * -from llnl.util.tty.colify import * -from llnl.util.tty.color import * +import spack.cmd.common.arguments as arguments + from spack.cmd import display_specs description = "Find installed spack packages" @@ -43,6 +38,7 @@ def setup_parser(subparser): action='store_const', dest='mode', const='short', + default='short', help='Show only specs (default)') format_group.add_argument('-p', '--paths', action='store_const', @@ -68,12 +64,12 @@ def setup_parser(subparser): action='store_true', dest='show_flags', help='Show spec compiler flags.') - - subparser.add_argument( + implicit_explicit = subparser.add_mutually_exclusive_group() + implicit_explicit.add_argument( '-e', '--explicit', action='store_true', help='Show only specs that were installed explicitly') - subparser.add_argument( + implicit_explicit.add_argument( '-E', '--implicit', action='store_true', help='Show only specs that were installed as dependencies') @@ -100,17 +96,10 @@ def setup_parser(subparser): action='store_true', help='Show fully qualified package names.') - subparser.add_argument('query_specs', - nargs=argparse.REMAINDER, - help='optional specs to filter results') + arguments.add_common_arguments(subparser, ['constraint']) def query_arguments(args): - # Check arguments - if args.explicit and args.implicit: - tty.error('You can\'t pass -E and -e options simultaneously.') - raise SystemExit(1) - # Set up query arguments. installed, known = True, any if args.only_missing: @@ -129,35 +118,17 @@ def query_arguments(args): def find(parser, args): - # Filter out specs that don't exist. - query_specs = spack.cmd.parse_specs(args.query_specs) - query_specs, nonexisting = partition_list( - query_specs, lambda s: spack.repo.exists(s.name) or not s.name) - - if nonexisting: - msg = "No such package%s: " % ('s' if len(nonexisting) > 1 else '') - msg += ", ".join(s.name for s in nonexisting) - tty.msg(msg) - - if not query_specs: - return - q_args = query_arguments(args) - - # Get all the specs the user asked for + query_specs = args.specs(**q_args) + # Exit early if no package matches the constraint if not query_specs: - specs = set(spack.store.db.query(**q_args)) - else: - results = [set(spack.store.db.query(qs, **q_args)) - for qs in query_specs] - specs = set.union(*results) - - if not args.mode: - args.mode = 'short' - + msg = "No package matches the query: {0}".format(args.contraint) + tty.msg(msg) + return + # Display the result if sys.stdout.isatty(): - tty.msg("%d installed packages." % len(specs)) - display_specs(specs, + tty.msg("%d installed packages." % len(query_specs)) + display_specs(query_specs, mode=args.mode, long=args.long, very_long=args.very_long, diff --git a/lib/spack/spack/cmd/module.py b/lib/spack/spack/cmd/module.py index d7abe0fa87..31460b3124 100644 --- a/lib/spack/spack/cmd/module.py +++ b/lib/spack/spack/cmd/module.py @@ -244,17 +244,17 @@ def module(parser, args): 'known': True }, } - arguments.ConstraintAction.qualifiers.update(constraint_qualifiers) - + query_args = constraint_qualifiers.get(args.subparser_name, {}) + specs = args.specs(**query_args) module_type = args.module_type constraint = args.constraint try: - callbacks[args.subparser_name](module_type, args.specs, args) + callbacks[args.subparser_name](module_type, specs, args) except MultipleMatches: message = ('the constraint \'{query}\' matches multiple packages, ' 'and this is not allowed in this context') tty.error(message.format(query=constraint)) - for s in args.specs: + for s in specs: sys.stderr.write(s.format(color=True) + '\n') raise SystemExit(1) except NoMatch: diff --git a/lib/spack/spack/test/cmd/find.py b/lib/spack/spack/test/cmd/find.py index fa82db7733..4788da8ec6 100644 --- a/lib/spack/spack/test/cmd/find.py +++ b/lib/spack/spack/test/cmd/find.py @@ -52,5 +52,3 @@ class FindTest(unittest.TestCase): args.implicit = True q_args = query_arguments(args) self.assertEqual(q_args['explicit'], False) - args.explicit = True - self.assertRaises(SystemExit, query_arguments, args) diff --git a/lib/spack/spack/test/cmd/module.py b/lib/spack/spack/test/cmd/module.py index 3a0ce32e6c..39f9c5649f 100644 --- a/lib/spack/spack/test/cmd/module.py +++ b/lib/spack/spack/test/cmd/module.py @@ -34,7 +34,7 @@ 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] + for spec in args.specs()] def test_module_common_operations(self): parser = argparse.ArgumentParser() -- cgit v1.2.3-60-g2f50