summaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authorTodd Gamblin <tgamblin@llnl.gov>2017-05-08 13:18:29 -0700
committerGitHub <noreply@github.com>2017-05-08 13:18:29 -0700
commitff3b5d88e4229516e9655a9a75f818453613e8e4 (patch)
tree56889884b1a68d740f1ddd702125c87e47a64493 /bin
parent7923579a424d8d9280717760cea1742cdb594d07 (diff)
downloadspack-ff3b5d88e4229516e9655a9a75f818453613e8e4.tar.gz
spack-ff3b5d88e4229516e9655a9a75f818453613e8e4.tar.bz2
spack-ff3b5d88e4229516e9655a9a75f818453613e8e4.tar.xz
spack-ff3b5d88e4229516e9655a9a75f818453613e8e4.zip
rework spack help (#3033)
- Full help is now only generated lazily, when needed. - Executing specific commands doesn't require loading all of them. - All commands are only loaded if we need them for help. - There is now short and long help: - short help (spack help) shows only basic spack options - long help (spack help -a) shows all spack options - Both divide help on commands into high-level sections - Commands now specify attributes from which help is auto-generated: - description: used in help to describe the command. - section: help section - level: short or long - Clean up command descriptions - Add a `spack docs` command to open full documentation in the browser. - move `spack doc` command to `spack pydoc` for clarity - Add a `spack --spec` command to show documentation on the spec syntax.
Diffstat (limited to 'bin')
-rwxr-xr-xbin/spack222
1 files changed, 21 insertions, 201 deletions
diff --git a/bin/spack b/bin/spack
index 5ab805fe54..496c705042 100755
--- a/bin/spack
+++ b/bin/spack
@@ -1,5 +1,4 @@
#!/usr/bin/env python
-# flake8: noqa
##############################################################################
# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
# Produced at the Lawrence Livermore National Laboratory.
@@ -26,34 +25,32 @@
##############################################################################
from __future__ import print_function
+import os
import sys
+
if sys.version_info[:2] < (2, 6):
v_info = sys.version_info[:3]
sys.exit("Spack requires Python 2.6 or higher."
"This is Python %d.%d.%d." % v_info)
-import os
-import inspect
-
# Find spack's location and its prefix.
-SPACK_FILE = os.path.realpath(os.path.expanduser(__file__))
-os.environ["SPACK_FILE"] = SPACK_FILE
-SPACK_PREFIX = os.path.dirname(os.path.dirname(SPACK_FILE))
+spack_file = os.path.realpath(os.path.expanduser(__file__))
+spack_prefix = os.path.dirname(os.path.dirname(spack_file))
# Allow spack libs to be imported in our scripts
-SPACK_LIB_PATH = os.path.join(SPACK_PREFIX, "lib", "spack")
-sys.path.insert(0, SPACK_LIB_PATH)
+spack_lib_path = os.path.join(spack_prefix, "lib", "spack")
+sys.path.insert(0, spack_lib_path)
# Add external libs
-SPACK_EXTERNAL_LIBS = os.path.join(SPACK_LIB_PATH, "external")
-sys.path.insert(0, SPACK_EXTERNAL_LIBS)
+spack_external_libs = os.path.join(spack_lib_path, "external")
+sys.path.insert(0, spack_external_libs)
# Handle vendoring of YAML specially, as it has two versions.
if sys.version_info[0] == 2:
- SPACK_YAML_LIBS = os.path.join(SPACK_EXTERNAL_LIBS, "yaml/lib")
+ spack_yaml_libs = os.path.join(spack_external_libs, "yaml/lib")
else:
- SPACK_YAML_LIBS = os.path.join(SPACK_EXTERNAL_LIBS, "yaml/lib3")
-sys.path.insert(0, SPACK_YAML_LIBS)
+ spack_yaml_libs = os.path.join(spack_external_libs, "yaml/lib3")
+sys.path.insert(0, spack_yaml_libs)
# Quick and dirty check to clean orphaned .pyc files left over from
# previous revisions. These files were present in earlier versions of
@@ -61,13 +58,13 @@ sys.path.insert(0, SPACK_YAML_LIBS)
# imports. If we leave them, Spack will fail in mysterious ways.
# TODO: more elegant solution for orphaned pyc files.
orphaned_pyc_files = [
- os.path.join(SPACK_EXTERNAL_LIBS, 'functools.pyc'),
- os.path.join(SPACK_EXTERNAL_LIBS, 'ordereddict.pyc'),
- os.path.join(SPACK_LIB_PATH, 'spack', 'platforms', 'cray_xc.pyc'),
- os.path.join(SPACK_LIB_PATH, 'spack', 'cmd', 'package-list.pyc'),
- os.path.join(SPACK_LIB_PATH, 'spack', 'cmd', 'test-install.pyc'),
- os.path.join(SPACK_LIB_PATH, 'spack', 'cmd', 'url-parse.pyc'),
- os.path.join(SPACK_LIB_PATH, 'spack', 'test', 'yaml.pyc')
+ os.path.join(spack_external_libs, 'functools.pyc'),
+ os.path.join(spack_external_libs, 'ordereddict.pyc'),
+ os.path.join(spack_lib_path, 'spack', 'platforms', 'cray_xc.pyc'),
+ os.path.join(spack_lib_path, 'spack', 'cmd', 'package-list.pyc'),
+ os.path.join(spack_lib_path, 'spack', 'cmd', 'test-install.pyc'),
+ os.path.join(spack_lib_path, 'spack', 'cmd', 'url-parse.pyc'),
+ os.path.join(spack_lib_path, 'spack', 'test', 'yaml.pyc')
]
for pyc_file in orphaned_pyc_files:
@@ -79,183 +76,6 @@ for pyc_file in orphaned_pyc_files:
print("WARNING: Spack may fail mysteriously. "
"Couldn't remove orphaned .pyc file: %s" % pyc_file)
-# If there is no working directory, use the spack prefix.
-try:
- working_dir = os.getcwd()
-except OSError:
- os.chdir(SPACK_PREFIX)
- working_dir = SPACK_PREFIX
-
-# clean up the scope and start using spack package instead.
-del SPACK_FILE, SPACK_PREFIX, SPACK_LIB_PATH
-import llnl.util.tty as tty
-from llnl.util.tty.color import *
-import spack
-from spack.error import SpackError
-import argparse
-import pstats
-
-# Get the allowed names of statistics for cProfile, and make a list of
-# groups of 7 names to wrap them nicely.
-stat_names = pstats.Stats.sort_arg_dict_default
-stat_lines = list(zip(*(iter(stat_names),)*7))
-
-# Command parsing
-parser = argparse.ArgumentParser(
- formatter_class=argparse.RawTextHelpFormatter,
- description="Spack: the Supercomputing PACKage Manager." + colorize("""
-
-spec expressions:
- PACKAGE [CONSTRAINTS]
-
- CONSTRAINTS:
- @c{@version}
- @g{%compiler @compiler_version}
- @B{+variant}
- @r{-variant} or @r{~variant}
- @m{=architecture}
- [^DEPENDENCY [CONSTRAINTS] ...]"""))
-
-parser.add_argument('-d', '--debug', action='store_true',
- help="write out debug logs during compile")
-parser.add_argument('-D', '--pdb', action='store_true',
- help="run spack under the pdb debugger")
-parser.add_argument('-k', '--insecure', action='store_true',
- help="do not check ssl certificates when downloading")
-parser.add_argument('-m', '--mock', action='store_true',
- help="use mock packages instead of real ones")
-parser.add_argument('-p', '--profile', action='store_true',
- help="profile execution using cProfile")
-parser.add_argument('-P', '--sorted-profile', default=None, metavar="STAT",
- help="profile and sort by one or more of:\n[%s]" %
- ',\n '.join([', '.join(line) for line in stat_lines]))
-parser.add_argument('--lines', default=20, action='store',
- help="lines of profile output: default 20; 'all' for all")
-parser.add_argument('-v', '--verbose', action='store_true',
- help="print additional output during builds")
-parser.add_argument('-s', '--stacktrace', action='store_true',
- help="add stacktrace info to all printed statements")
-parser.add_argument('-V', '--version', action='version',
- version="%s" % spack.spack_version)
-
-# each command module implements a parser() function, to which we pass its
-# subparser for setup.
-subparsers = parser.add_subparsers(metavar='SUBCOMMAND', dest="command")
-
-
-import spack.cmd
-for cmd in spack.cmd.commands:
- module = spack.cmd.get_module(cmd)
- cmd_name = cmd.replace('_', '-')
- subparser = subparsers.add_parser(cmd_name, help=module.description)
- module.setup_parser(subparser)
-
-
-def _main(args, unknown_args):
- # Set up environment based on args.
- tty.set_verbose(args.verbose)
- tty.set_debug(args.debug)
- tty.set_stacktrace(args.stacktrace)
- spack.debug = args.debug
-
- if spack.debug:
- import spack.util.debug as debug
- debug.register_interrupt_handler()
-
- # Run any available pre-run hooks
- spack.hooks.pre_run()
-
- spack.spack_working_dir = working_dir
- if args.mock:
- from spack.repository import RepoPath
- spack.repo.swap(RepoPath(spack.mock_packages_path))
-
- # If the user asked for it, don't check ssl certs.
- if args.insecure:
- tty.warn("You asked for --insecure. Will NOT check SSL certificates.")
- spack.insecure = True
-
- # Try to load the particular command asked for and run it
- command = spack.cmd.get_command(args.command.replace('-', '_'))
-
- # Allow commands to inject an optional argument and get unknown args
- # if they want to handle them.
- info = dict(inspect.getmembers(command))
- varnames = info['__code__'].co_varnames
- argcount = info['__code__'].co_argcount
-
- # Actually execute the command
- try:
- if argcount == 3 and varnames[2] == 'unknown_args':
- return_val = command(parser, args, unknown_args)
- else:
- if unknown_args:
- tty.die('unrecognized arguments: %s' % ' '.join(unknown_args))
- return_val = command(parser, args)
- except SpackError as e:
- e.die()
- except Exception as e:
- tty.die(str(e))
- except KeyboardInterrupt:
- sys.stderr.write('\n')
- tty.die("Keyboard interrupt.")
-
- # Allow commands to return values if they want to exit with some other code.
- if return_val is None:
- sys.exit(0)
- elif isinstance(return_val, int):
- sys.exit(return_val)
- else:
- tty.die("Bad return value from command %s: %s"
- % (args.command, return_val))
-
-
-def main(args):
- # Just print help and exit if run with no arguments at all
- if len(args) == 1:
- parser.print_help()
- sys.exit(1)
-
- # actually parse the args.
- args, unknown = parser.parse_known_args()
-
- if args.profile or args.sorted_profile:
- import cProfile
-
- try:
- nlines = int(args.lines)
- except ValueError:
- if args.lines != 'all':
- tty.die('Invalid number for --lines: %s' % args.lines)
- nlines = -1
-
- # allow comma-separated list of fields
- sortby = ['time']
- if args.sorted_profile:
- sortby = args.sorted_profile.split(',')
- for stat in sortby:
- if stat not in stat_names:
- tty.die("Invalid sort field: %s" % stat)
-
- try:
- # make a profiler and run the code.
- pr = cProfile.Profile()
- pr.enable()
- _main(args, unknown)
- finally:
- pr.disable()
-
- # print out profile stats.
- stats = pstats.Stats(pr)
- stats.sort_stats(*sortby)
- stats.print_stats(nlines)
-
- elif args.pdb:
- import pdb
- pdb.runctx('_main(args, unknown)', globals(), locals())
- else:
- _main(args, unknown)
-
-
-if __name__ == '__main__':
- main(sys.argv)
+# Once we've set up the system path, run the spack main method
+import spack.main # noqa
+sys.exit(spack.main.main())