Skip to content
Snippets Groups Projects
Commit 5b5894af authored by Massimiliano Culpo's avatar Massimiliano Culpo Committed by Todd Gamblin
Browse files

spack find: accepts anonymous specs as arguments fixes #2170 (#2188)

parent b706da11
No related branches found
No related tags found
No related merge requests found
......@@ -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,
......
......@@ -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,
......
......@@ -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:
......
......@@ -52,5 +52,3 @@ def test_query_arguments(self):
args.implicit = True
q_args = query_arguments(args)
self.assertEqual(q_args['explicit'], False)
args.explicit = True
self.assertRaises(SystemExit, query_arguments, args)
......@@ -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()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment