diff options
author | Todd Gamblin <tgamblin@llnl.gov> | 2016-11-04 11:47:57 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-11-04 11:47:57 -0700 |
commit | 2536029ea9e09707bb2a4c4a2b60a6a726ac8b9e (patch) | |
tree | c2840dd27e3ae4d015bd9ba7ea028b0ee08471d0 /lib | |
parent | 9a585e6c6a7208dc4cb2b4958e8c654f022d7ea3 (diff) | |
download | spack-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.py | 8 | ||||
-rw-r--r-- | lib/spack/spack/cmd/find.py | 10 | ||||
-rw-r--r-- | lib/spack/spack/cmd/spec.py | 39 | ||||
-rw-r--r-- | lib/spack/spack/spec.py | 32 | ||||
-rw-r--r-- | lib/spack/spack/test/spack_yaml.py | 16 | ||||
-rw-r--r-- | lib/spack/spack/util/spack_yaml.py | 5 |
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) |