flake8-clean.

This commit is contained in:
Brett Viren 2016-05-16 10:08:59 -04:00
parent b3ede099e2
commit 77a34ebdf9

View File

@ -29,14 +29,17 @@
This set consists of: This set consists of:
- specs resolved from the package names given by the user (the seeds) - specs resolved from the package names given by the user (the seeds)
- all depenencies of the seeds unless user specifies `--no-depenencies` - all depenencies of the seeds unless user specifies `--no-depenencies`
- less any specs with names matching the regular expressions given by `--exclude`
- less any specs with names matching the regular expressions given by
`--exclude`
The `view` command provides a number of functions (the "actions"): The `view` command provides a number of functions (the "actions"):
- symlink :: a file system view which is a directory hierarchy that is - symlink :: a file system view which is a directory hierarchy that is
the union of the hierarchies of the installed packages in the DAG the union of the hierarchies of the installed packages in the DAG
where installed files are referenced via symlinks. where installed files are referenced via symlinks.
- hardlink :: like the symlink view but hardlinks are used. - hardlink :: like the symlink view but hardlinks are used.
@ -66,71 +69,70 @@
import os import os
import re import re
import sys import sys
import argparse
import spack import spack
import spack.cmd import spack.cmd
import llnl.util.tty as tty import llnl.util.tty as tty
description = "Produce a single-rooted directory view of a spec." description = "Produce a single-rooted directory view of a spec."
def setup_parser(sp): def setup_parser(sp):
setup_parser.parser = sp setup_parser.parser = sp
sp.add_argument('-v','--verbose', action='store_true', default=False, sp.add_argument(
help="Display verbose output.") '-v', '--verbose', action='store_true', default=False,
sp.add_argument('-e','--exclude', action='append', default=[], help="Display verbose output.")
help="Exclude packages with names matching the given regex pattern.") sp.add_argument(
sp.add_argument('-d', '--dependencies', choices=['true','false','yes','no'], '-e', '--exclude', action='append', default=[],
default='true', help="Exclude packages with names matching the given regex pattern.")
help="Follow dependencies.") sp.add_argument(
'-d', '--dependencies', choices=['true', 'false', 'yes', 'no'],
default='true',
help="Follow dependencies.")
ssp = sp.add_subparsers(metavar='ACTION', dest='action') ssp = sp.add_subparsers(metavar='ACTION', dest='action')
specs_opts = dict(metavar='spec', nargs='+', specs_opts = dict(metavar='spec', nargs='+',
help="Seed specs of the packages to view.") help="Seed specs of the packages to view.")
# The action parameterizes the command but in keeping with Spack # The action parameterizes the command but in keeping with Spack
# patterns we make it a subcommand. # patterns we make it a subcommand.
file_system_view_actions = [ file_system_view_actions = [
ssp.add_parser('symlink', aliases=['add','soft'], ssp.add_parser(
help='Add package files to a filesystem view via symbolic links.'), 'symlink', aliases=['add', 'soft'],
ssp.add_parser('hardlink', aliases=['hard'], help='Add package files to a filesystem view via symbolic links.'),
help='Add packages files to a filesystem via via hard links.'), ssp.add_parser(
ssp.add_parser('remove', aliases=['rm'], 'hardlink', aliases=['hard'],
help='Remove packages from a filesystem view.'), help='Add packages files to a filesystem via via hard links.'),
ssp.add_parser('statlink', aliases=['status','check'], ssp.add_parser(
help='Check status of packages in a filesystem view.') 'remove', aliases=['rm'],
help='Remove packages from a filesystem view.'),
ssp.add_parser(
'statlink', aliases=['status', 'check'],
help='Check status of packages in a filesystem view.')
] ]
# All these options and arguments are common to every action. # All these options and arguments are common to every action.
for act in file_system_view_actions: for act in file_system_view_actions:
act.add_argument('path', nargs=1, act.add_argument('path', nargs=1,
help="Path to file system view directory.") help="Path to file system view directory.")
act.add_argument('specs', **specs_opts) act.add_argument('specs', **specs_opts)
# The formatted print action. # The formatted print action.
act = ssp.add_parser('print', act = ssp.add_parser('print',
help="Print a string to stdout based on given format") help="Print a string to stdout based on given format")
act.add_argument('format', nargs=1, act.add_argument('format', nargs=1,
help="Format describing per-package printout.") help="Format describing per-package printout.")
act.add_argument('specs', **specs_opts) act.add_argument('specs', **specs_opts)
## Other VIEW ACTIONS might be added here.
## Some ideas are the following (and some are redundant with existing cmds)
## A JSON view that dumps a DAG to a JSON file
## A DOT view that dumps to a GraphViz file
## A SHELL INIT view that dumps bash/csh script setting up to use packages in the view
return return
### Util functions
def assuredir(path): def assuredir(path):
'Assure path exists as a directory' 'Assure path exists as a directory'
if not os.path.exists(path): if not os.path.exists(path):
os.makedirs(path) os.makedirs(path)
def relative_to(prefix, path): def relative_to(prefix, path):
'Return end of `path` relative to `prefix`' 'Return end of `path` relative to `prefix`'
assert 0 == path.find(prefix) assert 0 == path.find(prefix)
@ -139,31 +141,36 @@ def relative_to(prefix, path):
reldir = reldir[1:] reldir = reldir[1:]
return reldir return reldir
def transform_path(spec, path, prefix=None): def transform_path(spec, path, prefix=None):
'Return the a relative path corresponding to given path spec.prefix' 'Return the a relative path corresponding to given path spec.prefix'
if os.path.isabs(path): if os.path.isabs(path):
path = relative_to(spec.prefix, path) path = relative_to(spec.prefix, path)
subdirs = path.split(os.path.sep) subdirs = path.split(os.path.sep)
if subdirs[0] == '.spack': if subdirs[0] == '.spack':
lst = ['.spack',spec.name]+subdirs[1:] lst = ['.spack', spec.name] + subdirs[1:]
path = os.path.join(*lst) path = os.path.join(*lst)
if prefix: if prefix:
path = os.path.join(prefix, path) path = os.path.join(prefix, path)
return path return path
def purge_empty_directories(path): def purge_empty_directories(path):
'Ascend up from the leaves accessible from `path` and remove empty directories.' '''Ascend up from the leaves accessible from `path`
and remove empty directories.'''
for dirpath, subdirs, files in os.walk(path, topdown=False): for dirpath, subdirs, files in os.walk(path, topdown=False):
for sd in subdirs: for sd in subdirs:
sdp = os.path.join(dirpath,sd) sdp = os.path.join(dirpath, sd)
try: try:
os.rmdir(sdp) os.rmdir(sdp)
except OSError: except OSError:
pass pass
def filter_exclude(specs, exclude): def filter_exclude(specs, exclude):
'Filter specs given sequence of exclude regex' 'Filter specs given sequence of exclude regex'
to_exclude = [re.compile(e) for e in exclude] to_exclude = [re.compile(e) for e in exclude]
def exclude(spec): def exclude(spec):
for e in to_exclude: for e in to_exclude:
if e.match(spec.name): if e.match(spec.name):
@ -171,6 +178,7 @@ def exclude(spec):
return False return False
return [s for s in specs if not exclude(s)] return [s for s in specs if not exclude(s)]
def flatten(seeds, descend=True): def flatten(seeds, descend=True):
'Normalize and flattend seed specs and descend hiearchy' 'Normalize and flattend seed specs and descend hiearchy'
flat = set() flat = set()
@ -181,6 +189,7 @@ def flatten(seeds, descend=True):
flat.update(spec.normalized().traverse()) flat.update(spec.normalized().traverse())
return flat return flat
def spec2dict(spec): def spec2dict(spec):
'Convert info in a spec into a simple dictionary.' 'Convert info in a spec into a simple dictionary.'
@ -188,44 +197,45 @@ def spec2dict(spec):
# some things need processing or are properties. # some things need processing or are properties.
# #
pkg = spec.package pkg = spec.package
ret = dict(name = spec.name, inst_deps = ','.join([s.name for s in pkg.installed_dependents]),
spec = spec.short_spec, ret = dict(name=spec.name,
colorspec = spec.cshort_spec, # color spec=spec.short_spec,
root = spec.root, colorspec=spec.cshort_spec, # color
prefix = spec.prefix, root=spec.root,
version = spec.version, prefix=spec.prefix,
variants = spec.variants, version=spec.version,
namespace = spec.namespace, variants=spec.variants,
compiler = spec.compiler, namespace=spec.namespace,
architecture = spec.architecture, compiler=spec.compiler,
dependencies = ','.join(spec.dependencies.keys()), architecture=spec.architecture,
dependents = ','.join(spec.dependents.keys()), dependencies=','.join(spec.dependencies.keys()),
external = spec.external or "False", dependents=','.join(spec.dependents.keys()),
hash = spec.dag_hash(), external=spec.external or "False",
hash=spec.dag_hash(),
# package related: # package related:
url = pkg.url, url=pkg.url,
stage = pkg.stage.path, stage=pkg.stage.path,
installed = pkg.installed, installed=pkg.installed,
installed_dependents = ','.join([s.name for s in pkg.installed_dependents]), installed_dependents=inst_deps,
build_log = pkg.build_log_path, build_log=pkg.build_log_path,
rpath = ':'.join(pkg.rpath), rpath=':'.join(pkg.rpath),
# ... # ...
) )
return ret return ret
### Action-specific helpers
def check_one(spec, path, verbose=False): def check_one(spec, path, verbose=False):
'Check status of view in path against spec' 'Check status of view in path against spec'
dotspack = os.path.join(path, '.spack', spec.name) dotspack = os.path.join(path, '.spack', spec.name)
if os.path.exists(os.path.join(dotspack)): if os.path.exists(os.path.join(dotspack)):
tty.info('Package in view: "%s"'%spec.name) tty.info('Package in view: "%s"' % spec.name)
return return
tty.info('Package not in view: "%s"'%spec.name) tty.info('Package not in view: "%s"' % spec.name)
return return
def remove_one(spec, path, verbose=False): def remove_one(spec, path, verbose=False):
'Remove any files found in `spec` from `path` and purge empty directories.' 'Remove any files found in `spec` from `path` and purge empty directories.'
@ -235,12 +245,12 @@ def remove_one(spec, path, verbose=False):
dotspack = transform_path(spec, '.spack', path) dotspack = transform_path(spec, '.spack', path)
if not os.path.exists(dotspack): if not os.path.exists(dotspack):
if verbose: if verbose:
tty.info('Skipping nonexistent package: "%s"'%spec.name) tty.info('Skipping nonexistent package: "%s"' % spec.name)
return return
if verbose: if verbose:
tty.info('Removing package: "%s"'%spec.name) tty.info('Removing package: "%s"' % spec.name)
for dirpath,dirnames,filenames in os.walk(spec.prefix): for dirpath, dirnames, filenames in os.walk(spec.prefix):
if not filenames: if not filenames:
continue continue
targdir = transform_path(spec, dirpath, path) targdir = transform_path(spec, dirpath, path)
@ -250,17 +260,18 @@ def remove_one(spec, path, verbose=False):
continue continue
os.unlink(dst) os.unlink(dst)
def link_one(spec, path, link = os.symlink, verbose=False):
def link_one(spec, path, link=os.symlink, verbose=False):
'Link all files in `spec` into directory `path`.' 'Link all files in `spec` into directory `path`.'
dotspack = transform_path(spec, '.spack', path) dotspack = transform_path(spec, '.spack', path)
if os.path.exists(dotspack): if os.path.exists(dotspack):
tty.warn('Skipping existing package: "%s"'%spec.name) tty.warn('Skipping existing package: "%s"' % spec.name)
return return
if verbose: if verbose:
tty.info('Linking package: "%s"' % spec.name) tty.info('Linking package: "%s"' % spec.name)
for dirpath,dirnames,filenames in os.walk(spec.prefix): for dirpath, dirnames, filenames in os.walk(spec.prefix):
if not filenames: if not filenames:
continue # avoid explicitly making empty dirs continue # avoid explicitly making empty dirs
@ -275,12 +286,9 @@ def link_one(spec, path, link = os.symlink, verbose=False):
continue # silence these continue # silence these
tty.warn("Skipping existing file: %s" % dst) tty.warn("Skipping existing file: %s" % dst)
continue continue
link(src,dst) link(src, dst)
### The canonically named visitor_* functions and their alias maps.
### One for each action.
def visitor_symlink(specs, args): def visitor_symlink(specs, args):
'Symlink all files found in specs' 'Symlink all files found in specs'
path = args.path[0] path = args.path[0]
@ -290,6 +298,7 @@ def visitor_symlink(specs, args):
visitor_add = visitor_symlink visitor_add = visitor_symlink
visitor_soft = visitor_symlink visitor_soft = visitor_symlink
def visitor_hardlink(specs, args): def visitor_hardlink(specs, args):
'Hardlink all files found in specs' 'Hardlink all files found in specs'
path = args.path[0] path = args.path[0]
@ -298,6 +307,7 @@ def visitor_hardlink(specs, args):
link_one(spec, path, os.link, verbose=args.verbose) link_one(spec, path, os.link, verbose=args.verbose)
visitor_hard = visitor_hardlink visitor_hard = visitor_hardlink
def visitor_remove(specs, args): def visitor_remove(specs, args):
'Remove all files and directories found in specs from args.path' 'Remove all files and directories found in specs from args.path'
path = args.path[0] path = args.path[0]
@ -306,6 +316,7 @@ def visitor_remove(specs, args):
purge_empty_directories(path) purge_empty_directories(path)
visitor_rm = visitor_remove visitor_rm = visitor_remove
def visitor_statlink(specs, args): def visitor_statlink(specs, args):
'Give status of view in args.path relative to specs' 'Give status of view in args.path relative to specs'
path = args.path[0] path = args.path[0]
@ -314,6 +325,7 @@ def visitor_statlink(specs, args):
visitor_status = visitor_statlink visitor_status = visitor_statlink
visitor_check = visitor_statlink visitor_check = visitor_statlink
def visitor_print(specs, args): def visitor_print(specs, args):
'Print a string for each spec using args.format.' 'Print a string for each spec using args.format.'
fmt = args.format[0] fmt = args.format[0]
@ -325,25 +337,22 @@ def visitor_print(specs, args):
try: try:
text = t.substitute(kwds) text = t.substitute(kwds)
except KeyError: except KeyError:
tty.error("Format error, use keywords: %s" % (', '.join(kwds.keys()), )) tty.error("Format error, use keywords: %s" %
(', '.join(kwds.keys()), ))
raise raise
# argparser escapes these # argparser escapes these
text = text.replace(r'\n', '\n').replace(r'\t', '\t') text = text.replace(r'\n', '\n').replace(r'\t', '\t')
sys.stdout.write(text) sys.stdout.write(text)
# Finally, the actual "view" command. There should be no need to
# modify anything below when new actions are added.
def view(parser, args): def view(parser, args):
'Produce a view of a set of packages.' 'Produce a view of a set of packages.'
# Process common args # Process common args
seeds = [spack.cmd.disambiguate_spec(s) for s in args.specs] seeds = [spack.cmd.disambiguate_spec(s) for s in args.specs]
specs = flatten(seeds, args.dependencies.lower() in ['yes','true']) specs = flatten(seeds, args.dependencies.lower() in ['yes', 'true'])
specs = filter_exclude(specs, args.exclude) specs = filter_exclude(specs, args.exclude)
# Execute the visitation. # Execute the visitation.
try: try:
visitor = globals()['visitor_' + args.action] visitor = globals()['visitor_' + args.action]