summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTodd Gamblin <tgamblin@llnl.gov>2016-11-04 11:47:57 -0700
committerGitHub <noreply@github.com>2016-11-04 11:47:57 -0700
commit2536029ea9e09707bb2a4c4a2b60a6a726ac8b9e (patch)
treec2840dd27e3ae4d015bd9ba7ea028b0ee08471d0 /lib
parent9a585e6c6a7208dc4cb2b4958e8c654f022d7ea3 (diff)
downloadspack-2536029ea9e09707bb2a4c4a2b60a6a726ac8b9e.tar.gz
spack-2536029ea9e09707bb2a4c4a2b60a6a726ac8b9e.tar.bz2
spack-2536029ea9e09707bb2a4c4a2b60a6a726ac8b9e.tar.xz
spack-2536029ea9e09707bb2a4c4a2b60a6a726ac8b9e.zip
Better spack spec (#2238)
* Add options for hashes, tree depth, and YAML to `spack spec`. - Can now display hashes with `spack spec`, like `spack find`. - Removed the old "ids" argument to `spack spec` (which printed numerical values)b - Can output YAML spec from `spack spec` with `-y` - Can control depth of DAG traversal with --cover=[nodes|edges|paths] - Can print install status (installed, missing, not installed) with -I * Don't use YAML aliases in specs. - Force Spack's YAML dumper to ignore aliases. - aliases cause non-canonical YAML to be used in DAG hash, and result in redundant hashes. - add a test to ensure this behavior stays
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/cmd/common/arguments.py8
-rw-r--r--lib/spack/spack/cmd/find.py10
-rw-r--r--lib/spack/spack/cmd/spec.py39
-rw-r--r--lib/spack/spack/spec.py32
-rw-r--r--lib/spack/spack/test/spack_yaml.py16
-rw-r--r--lib/spack/spack/util/spack_yaml.py5
6 files changed, 85 insertions, 25 deletions
diff --git a/lib/spack/spack/cmd/common/arguments.py b/lib/spack/spack/cmd/common/arguments.py
index d5bd4bb711..1470ea035d 100644
--- a/lib/spack/spack/cmd/common/arguments.py
+++ b/lib/spack/spack/cmd/common/arguments.py
@@ -89,3 +89,11 @@ _arguments['clean'] = Args(
_arguments['dirty'] = Args(
'--dirty', action='store_true', dest='dirty',
help='Do NOT clean environment before installing.')
+
+_arguments['long'] = Args(
+ '-l', '--long', action='store_true',
+ help='Show dependency hashes as well as versions.')
+
+_arguments['very_long'] = Args(
+ '-L', '--very-long', action='store_true',
+ help='Show full dependency hashes as well as versions.')
diff --git a/lib/spack/spack/cmd/find.py b/lib/spack/spack/cmd/find.py
index 29bf263f51..27949ef5db 100644
--- a/lib/spack/spack/cmd/find.py
+++ b/lib/spack/spack/cmd/find.py
@@ -52,14 +52,8 @@ def setup_parser(subparser):
const='deps',
help='Show full dependency DAG of installed packages')
- subparser.add_argument('-l', '--long',
- action='store_true',
- dest='long',
- help='Show dependency hashes as well as versions.')
- subparser.add_argument('-L', '--very-long',
- action='store_true',
- dest='very_long',
- help='Show dependency hashes as well as versions.')
+ arguments.add_common_arguments(subparser, ['long', 'very_long'])
+
subparser.add_argument('-f', '--show-flags',
action='store_true',
dest='show_flags',
diff --git a/lib/spack/spack/cmd/spec.py b/lib/spack/spack/cmd/spec.py
index 6e6d1c1277..0a6fb330ac 100644
--- a/lib/spack/spack/cmd/spec.py
+++ b/lib/spack/spack/cmd/spec.py
@@ -23,36 +23,57 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
import argparse
-import spack.cmd
import spack
+import spack.cmd
+import spack.cmd.common.arguments as arguments
description = "print out abstract and concrete versions of a spec."
def setup_parser(subparser):
- subparser.add_argument('-i', '--ids', action='store_true',
- help="show numerical ids for dependencies.")
+ arguments.add_common_arguments(subparser, ['long', 'very_long'])
+ subparser.add_argument(
+ '-y', '--yaml', action='store_true', default=False,
+ help='Print concrete spec as YAML.')
+ subparser.add_argument(
+ '-c', '--cover', action='store',
+ default='nodes', choices=['nodes', 'edges', 'paths'],
+ help='How extensively to traverse the DAG. (default: nodes).')
+ subparser.add_argument(
+ '-I', '--install-status', action='store_true', default=False,
+ help='Show install status of packages. Packages can be: '
+ 'installed [+], missing and needed by an installed package [-], '
+ 'or not installed (no annotation).')
subparser.add_argument(
'specs', nargs=argparse.REMAINDER, help="specs of packages")
def spec(parser, args):
- kwargs = {'ids': args.ids,
- 'indent': 2,
- 'color': True}
+ kwargs = {'color': True,
+ 'cover': args.cover,
+ 'install_status': args.install_status,
+ 'hashes': args.long or args.very_long,
+ 'hashlen': None if args.very_long else 7}
for spec in spack.cmd.parse_specs(args.specs):
+ # With -y, just print YAML to output.
+ if args.yaml:
+ spec.concretize()
+ print spec.to_yaml()
+ continue
+
+ # Print some diagnostic info by default.
print "Input spec"
- print "------------------------------"
+ print "--------------------------------"
print spec.tree(**kwargs)
print "Normalized"
- print "------------------------------"
+ print "--------------------------------"
spec.normalize()
print spec.tree(**kwargs)
print "Concretized"
- print "------------------------------"
+ print "--------------------------------"
spec.concretize()
print spec.tree(**kwargs)
diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py
index cbcb2199f6..f830b73fa0 100644
--- a/lib/spack/spack/spec.py
+++ b/lib/spack/spack/spec.py
@@ -2396,12 +2396,24 @@ class Spec(object):
def __str__(self):
return self.format() + self.dep_string()
+ def _install_status(self):
+ """Helper for tree to print DB install status."""
+ if not self.concrete:
+ return None
+ try:
+ record = spack.store.db.get_record(self)
+ return record.installed
+ except KeyError:
+ return None
+
def tree(self, **kwargs):
"""Prints out this spec and its dependencies, tree-formatted
with indentation."""
color = kwargs.pop('color', False)
depth = kwargs.pop('depth', False)
- showid = kwargs.pop('ids', False)
+ hashes = kwargs.pop('hashes', True)
+ hlen = kwargs.pop('hashlen', None)
+ install_status = kwargs.pop('install_status', True)
cover = kwargs.pop('cover', 'nodes')
indent = kwargs.pop('indent', 0)
fmt = kwargs.pop('format', '$_$@$%@+$+$=')
@@ -2410,8 +2422,6 @@ class Spec(object):
check_kwargs(kwargs, self.tree)
out = ""
- cur_id = 0
- ids = {}
for d, node in self.traverse(
order='pre', cover=cover, depth=True, deptypes=deptypes):
if prefix is not None:
@@ -2419,11 +2429,17 @@ class Spec(object):
out += " " * indent
if depth:
out += "%-4d" % d
- if not id(node) in ids:
- cur_id += 1
- ids[id(node)] = cur_id
- if showid:
- out += "%-4d" % ids[id(node)]
+ if install_status:
+ status = node._install_status()
+ if status is None:
+ out += " " # Package isn't installed
+ elif status:
+ out += colorize("@g{[+]} ", color=color) # installed
+ else:
+ out += colorize("@r{[-]} ", color=color) # missing
+
+ if hashes:
+ out += colorize('@K{%s} ', color=color) % node.dag_hash(hlen)
out += (" " * d)
if d > 0:
out += "^"
diff --git a/lib/spack/spack/test/spack_yaml.py b/lib/spack/spack/test/spack_yaml.py
index 30ed1672e2..fbbb7b8e60 100644
--- a/lib/spack/spack/test/spack_yaml.py
+++ b/lib/spack/spack/test/spack_yaml.py
@@ -90,3 +90,19 @@ class SpackYamlTest(unittest.TestCase):
check(self.data['config_file']['some_list'][2], 8, 8)
check(self.data['config_file']['another_list'], 10, 10)
check(self.data['config_file']['some_key'], 11, 11)
+
+ def test_yaml_aliases(self):
+ aliased_list_1 = ['foo']
+ aliased_list_2 = []
+ dict_with_aliases = {
+ 'a': aliased_list_1,
+ 'b': aliased_list_1,
+ 'c': aliased_list_1,
+ 'd': aliased_list_2,
+ 'e': aliased_list_2,
+ 'f': aliased_list_2,
+ }
+ string = syaml.dump(dict_with_aliases)
+
+ # ensure no YAML aliases appear in syaml dumps.
+ self.assertFalse('*id' in string)
diff --git a/lib/spack/spack/util/spack_yaml.py b/lib/spack/spack/util/spack_yaml.py
index 674c79bca1..c27db52066 100644
--- a/lib/spack/spack/util/spack_yaml.py
+++ b/lib/spack/spack/util/spack_yaml.py
@@ -202,6 +202,11 @@ class OrderedLineDumper(Dumper):
node.flow_style = best_style
return node
+ def ignore_aliases(self, _data):
+ """Make the dumper NEVER print YAML aliases."""
+ return True
+
+
# Make our special objects look like normal YAML ones.
OrderedLineDumper.add_representer(syaml_dict, OrderedLineDumper.represent_dict)
OrderedLineDumper.add_representer(syaml_list, OrderedLineDumper.represent_list)