Make Spack core PEP8 compliant.

This commit is contained in:
Todd Gamblin 2016-08-09 13:23:53 -07:00
parent 8061deb883
commit bf1072c902
150 changed files with 1436 additions and 1160 deletions

View file

@ -19,5 +19,5 @@
# - F999: name name be undefined or undefined from star imports. # - F999: name name be undefined or undefined from star imports.
# #
[flake8] [flake8]
ignore = E221,E241,E731,F403,F821,F999,F405 ignore = E129,E221,E241,E272,E731,F403,F821,F999,F405
max-line-length = 79 max-line-length = 79

View file

@ -1,4 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python
# flake8: noqa
############################################################################## ##############################################################################
# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC. # Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
# Produced at the Lawrence Livermore National Laboratory. # Produced at the Lawrence Livermore National Laboratory.
@ -24,9 +25,10 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import sys import sys
if not sys.version_info[:2] >= (2,6): if not sys.version_info[:2] >= (2, 6):
v_info = sys.version_info[:3] v_info = sys.version_info[:3]
sys.exit("Spack requires Python 2.6 or higher. This is Python %d.%d.%d." % v_info) sys.exit("Spack requires Python 2.6 or higher. "
"This is Python %d.%d.%d." % v_info)
import os import os
@ -62,7 +64,8 @@ for pyc_file in orphaned_pyc_files:
try: try:
os.remove(pyc_file) os.remove(pyc_file)
except OSError as e: except OSError as e:
print "WARNING: Spack may fail mysteriously. Couldn't remove orphaned .pyc file: %s" % pyc_file 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. # If there is no working directory, use the spack prefix.
try: try:
@ -128,6 +131,7 @@ if len(sys.argv) == 1:
# actually parse the args. # actually parse the args.
args = parser.parse_args() args = parser.parse_args()
def main(): def main():
# Set up environment based on args. # Set up environment based on args.
tty.set_verbose(args.verbose) tty.set_verbose(args.verbose)
@ -148,7 +152,7 @@ def main():
# If the user asked for it, don't check ssl certs. # If the user asked for it, don't check ssl certs.
if args.insecure: if args.insecure:
tty.warn("You asked for --insecure, which does not check SSL certificates.") tty.warn("You asked for --insecure. Will NOT check SSL certificates.")
spack.curl.add_default_arg('-k') spack.curl.add_default_arg('-k')
# Try to load the particular command asked for and run it # Try to load the particular command asked for and run it
@ -167,7 +171,8 @@ def main():
elif isinstance(return_val, int): elif isinstance(return_val, int):
sys.exit(return_val) sys.exit(return_val)
else: else:
tty.die("Bad return value from command %s: %s" % (args.command, return_val)) tty.die("Bad return value from command %s: %s"
% (args.command, return_val))
if args.profile: if args.profile:
import cProfile import cProfile

View file

@ -106,6 +106,7 @@ def groupid_to_group(x):
class FileFilter(object): class FileFilter(object):
"""Convenience class for calling filter_file a lot.""" """Convenience class for calling filter_file a lot."""
def __init__(self, *filenames): def __init__(self, *filenames):
self.filenames = filenames self.filenames = filenames
@ -355,7 +356,8 @@ def traverse_tree(source_root, dest_root, rel_path='', **kwargs):
# When follow_nonexisting isn't set, don't descend into dirs # When follow_nonexisting isn't set, don't descend into dirs
# in source that do not exist in dest # in source that do not exist in dest
if follow_nonexisting or os.path.exists(dest_child): if follow_nonexisting or os.path.exists(dest_child):
tuples = traverse_tree(source_root, dest_root, rel_child, **kwargs) # NOQA: ignore=E501 tuples = traverse_tree(
source_root, dest_root, rel_child, **kwargs)
for t in tuples: for t in tuples:
yield t yield t
@ -422,14 +424,20 @@ def fix_darwin_install_name(path):
libs = glob.glob(join_path(path, "*.dylib")) libs = glob.glob(join_path(path, "*.dylib"))
for lib in libs: for lib in libs:
# fix install name first: # fix install name first:
subprocess.Popen(["install_name_tool", "-id", lib, lib], stdout=subprocess.PIPE).communicate()[0] # NOQA: ignore=E501 subprocess.Popen(
long_deps = subprocess.Popen(["otool", "-L", lib], stdout=subprocess.PIPE).communicate()[0].split('\n') # NOQA: ignore=E501 ["install_name_tool", "-id", lib, lib],
stdout=subprocess.PIPE).communicate()[0]
long_deps = subprocess.Popen(
["otool", "-L", lib],
stdout=subprocess.PIPE).communicate()[0].split('\n')
deps = [dep.partition(' ')[0][1::] for dep in long_deps[2:-1]] deps = [dep.partition(' ')[0][1::] for dep in long_deps[2:-1]]
# fix all dependencies: # fix all dependencies:
for dep in deps: for dep in deps:
for loc in libs: for loc in libs:
if dep == os.path.basename(loc): if dep == os.path.basename(loc):
subprocess.Popen(["install_name_tool", "-change", dep, loc, lib], stdout=subprocess.PIPE).communicate()[0] # NOQA: ignore=E501 subprocess.Popen(
["install_name_tool", "-change", dep, loc, lib],
stdout=subprocess.PIPE).communicate()[0]
break break

View file

@ -24,7 +24,6 @@
############################################################################## ##############################################################################
import os import os
import re import re
import sys
import functools import functools
import collections import collections
import inspect import inspect
@ -39,14 +38,15 @@ def index_by(objects, *funcs):
Values are used as keys. For example, suppose you have four Values are used as keys. For example, suppose you have four
objects with attributes that look like this: objects with attributes that look like this:
a = Spec(name="boost", compiler="gcc", arch="bgqos_0") a = Spec(name="boost", compiler="gcc", arch="bgqos_0")
b = Spec(name="mrnet", compiler="intel", arch="chaos_5_x86_64_ib") b = Spec(name="mrnet", compiler="intel", arch="chaos_5_x86_64_ib")
c = Spec(name="libelf", compiler="xlc", arch="bgqos_0") c = Spec(name="libelf", compiler="xlc", arch="bgqos_0")
d = Spec(name="libdwarf", compiler="intel", arch="chaos_5_x86_64_ib") d = Spec(name="libdwarf", compiler="intel", arch="chaos_5_x86_64_ib")
list_of_specs = [a,b,c,d] list_of_specs = [a,b,c,d]
index1 = index_by(list_of_specs, lambda s: s.arch, lambda s: s.compiler) index1 = index_by(list_of_specs, lambda s: s.arch,
index2 = index_by(list_of_specs, lambda s: s.compiler) lambda s: s.compiler)
index2 = index_by(list_of_specs, lambda s: s.compiler)
``index1'' now has two levels of dicts, with lists at the ``index1'' now has two levels of dicts, with lists at the
leaves, like this: leaves, like this:
@ -137,7 +137,7 @@ def get_calling_module_name():
finally: finally:
del stack del stack
if not '__module__' in caller_locals: if '__module__' not in caller_locals:
raise RuntimeError("Must invoke get_calling_module_name() " raise RuntimeError("Must invoke get_calling_module_name() "
"from inside a class definition!") "from inside a class definition!")
@ -173,11 +173,11 @@ def has_method(cls, name):
class memoized(object): class memoized(object):
"""Decorator that caches the results of a function, storing them """Decorator that caches the results of a function, storing them
in an attribute of that function.""" in an attribute of that function."""
def __init__(self, func): def __init__(self, func):
self.func = func self.func = func
self.cache = {} self.cache = {}
def __call__(self, *args): def __call__(self, *args):
if not isinstance(args, collections.Hashable): if not isinstance(args, collections.Hashable):
# Not hashable, so just call the function. # Not hashable, so just call the function.
@ -187,12 +187,10 @@ def __call__(self, *args):
self.cache[args] = self.func(*args) self.cache[args] = self.func(*args)
return self.cache[args] return self.cache[args]
def __get__(self, obj, objtype): def __get__(self, obj, objtype):
"""Support instance methods.""" """Support instance methods."""
return functools.partial(self.__call__, obj) return functools.partial(self.__call__, obj)
def clear(self): def clear(self):
"""Expunge cache so that self.func will be called again.""" """Expunge cache so that self.func will be called again."""
self.cache.clear() self.cache.clear()
@ -237,13 +235,21 @@ def setter(name, value):
if not has_method(cls, '_cmp_key'): if not has_method(cls, '_cmp_key'):
raise TypeError("'%s' doesn't define _cmp_key()." % cls.__name__) raise TypeError("'%s' doesn't define _cmp_key()." % cls.__name__)
setter('__eq__', lambda s,o: (s is o) or (o is not None and s._cmp_key() == o._cmp_key())) setter('__eq__',
setter('__lt__', lambda s,o: o is not None and s._cmp_key() < o._cmp_key()) lambda s, o:
setter('__le__', lambda s,o: o is not None and s._cmp_key() <= o._cmp_key()) (s is o) or (o is not None and s._cmp_key() == o._cmp_key()))
setter('__lt__',
lambda s, o: o is not None and s._cmp_key() < o._cmp_key())
setter('__le__',
lambda s, o: o is not None and s._cmp_key() <= o._cmp_key())
setter('__ne__', lambda s,o: (s is not o) and (o is None or s._cmp_key() != o._cmp_key())) setter('__ne__',
setter('__gt__', lambda s,o: o is None or s._cmp_key() > o._cmp_key()) lambda s, o:
setter('__ge__', lambda s,o: o is None or s._cmp_key() >= o._cmp_key()) (s is not o) and (o is None or s._cmp_key() != o._cmp_key()))
setter('__gt__',
lambda s, o: o is None or s._cmp_key() > o._cmp_key())
setter('__ge__',
lambda s, o: o is None or s._cmp_key() >= o._cmp_key())
setter('__hash__', lambda self: hash(self._cmp_key())) setter('__hash__', lambda self: hash(self._cmp_key()))
@ -254,10 +260,10 @@ def setter(name, value):
class HashableMap(dict): class HashableMap(dict):
"""This is a hashable, comparable dictionary. Hash is performed on """This is a hashable, comparable dictionary. Hash is performed on
a tuple of the values in the dictionary.""" a tuple of the values in the dictionary."""
def _cmp_key(self): def _cmp_key(self):
return tuple(sorted(self.values())) return tuple(sorted(self.values()))
def copy(self): def copy(self):
"""Type-agnostic clone method. Preserves subclass type.""" """Type-agnostic clone method. Preserves subclass type."""
# Construct a new dict of my type # Construct a new dict of my type
@ -336,24 +342,39 @@ def match(string):
return match return match
def DictWrapper(dictionary): def DictWrapper(dictionary):
"""Returns a class that wraps a dictionary and enables it to be used """Returns a class that wraps a dictionary and enables it to be used
like an object.""" like an object."""
class wrapper(object): class wrapper(object):
def __getattr__(self, name): return dictionary[name]
def __setattr__(self, name, value): dictionary[name] = value
def setdefault(self, *args): return dictionary.setdefault(*args)
def get(self, *args): return dictionary.get(*args)
def keys(self): return dictionary.keys()
def values(self): return dictionary.values()
def items(self): return dictionary.items()
def __iter__(self): return iter(dictionary)
def __getattr__(self, name):
return dictionary[name]
def __setattr__(self, name, value):
dictionary[name] = value
def setdefault(self, *args):
return dictionary.setdefault(*args)
def get(self, *args):
return dictionary.get(*args)
def keys(self):
return dictionary.keys()
def values(self):
return dictionary.values()
def items(self):
return dictionary.items()
def __iter__(self):
return iter(dictionary)
return wrapper() return wrapper()
class RequiredAttributeError(ValueError): class RequiredAttributeError(ValueError):
def __init__(self, message): def __init__(self, message):
super(RequiredAttributeError, self).__init__(message) super(RequiredAttributeError, self).__init__(message)

View file

@ -23,12 +23,13 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
"""LinkTree class for setting up trees of symbolic links.""" """LinkTree class for setting up trees of symbolic links."""
__all__ = ['LinkTree']
import os import os
import shutil import shutil
from llnl.util.filesystem import * from llnl.util.filesystem import *
__all__ = ['LinkTree']
empty_file_name = '.spack-empty' empty_file_name = '.spack-empty'
@ -43,13 +44,13 @@ class LinkTree(object):
modified. modified.
""" """
def __init__(self, source_root): def __init__(self, source_root):
if not os.path.exists(source_root): if not os.path.exists(source_root):
raise IOError("No such file or directory: '%s'", source_root) raise IOError("No such file or directory: '%s'", source_root)
self._root = source_root self._root = source_root
def find_conflict(self, dest_root, **kwargs): def find_conflict(self, dest_root, **kwargs):
"""Returns the first file in dest that conflicts with src""" """Returns the first file in dest that conflicts with src"""
kwargs['follow_nonexisting'] = False kwargs['follow_nonexisting'] = False
@ -61,9 +62,9 @@ def find_conflict(self, dest_root, **kwargs):
return dest return dest
return None return None
def merge(self, dest_root, **kwargs): def merge(self, dest_root, **kwargs):
"""Link all files in src into dest, creating directories if necessary.""" """Link all files in src into dest, creating directories
if necessary."""
kwargs['order'] = 'pre' kwargs['order'] = 'pre'
for src, dest in traverse_tree(self._root, dest_root, **kwargs): for src, dest in traverse_tree(self._root, dest_root, **kwargs):
if os.path.isdir(src): if os.path.isdir(src):
@ -83,7 +84,6 @@ def merge(self, dest_root, **kwargs):
assert(not os.path.exists(dest)) assert(not os.path.exists(dest))
os.symlink(src, dest) os.symlink(src, dest)
def unmerge(self, dest_root, **kwargs): def unmerge(self, dest_root, **kwargs):
"""Unlink all files in dest that exist in src. """Unlink all files in dest that exist in src.

View file

@ -47,6 +47,7 @@ class Lock(object):
and recent NFS versions. and recent NFS versions.
""" """
def __init__(self, file_path): def __init__(self, file_path):
self._file_path = file_path self._file_path = file_path
self._fd = None self._fd = None
@ -225,6 +226,7 @@ def __exit__(self, type, value, traceback):
class ReadTransaction(LockTransaction): class ReadTransaction(LockTransaction):
def _enter(self): def _enter(self):
return self._lock.acquire_read(self._timeout) return self._lock.acquire_read(self._timeout)
@ -233,6 +235,7 @@ def _exit(self):
class WriteTransaction(LockTransaction): class WriteTransaction(LockTransaction):
def _enter(self): def _enter(self):
return self._lock.acquire_write(self._timeout) return self._lock.acquire_write(self._timeout)

View file

@ -36,6 +36,7 @@
_verbose = False _verbose = False
indent = " " indent = " "
def is_verbose(): def is_verbose():
return _verbose return _verbose
@ -148,7 +149,8 @@ def get_yes_or_no(prompt, **kwargs):
elif default_value is False: elif default_value is False:
prompt += ' [y/N] ' prompt += ' [y/N] '
else: else:
raise ValueError("default for get_yes_no() must be True, False, or None.") raise ValueError(
"default for get_yes_no() must be True, False, or None.")
result = None result = None
while result is None: while result is None:
@ -174,8 +176,9 @@ def hline(label=None, **kwargs):
char = kwargs.pop('char', '-') char = kwargs.pop('char', '-')
max_width = kwargs.pop('max_width', 64) max_width = kwargs.pop('max_width', 64)
if kwargs: if kwargs:
raise TypeError("'%s' is an invalid keyword argument for this function." raise TypeError(
% next(kwargs.iterkeys())) "'%s' is an invalid keyword argument for this function."
% next(kwargs.iterkeys()))
rows, cols = terminal_size() rows, cols = terminal_size()
if not cols: if not cols:
@ -200,7 +203,8 @@ def terminal_size():
"""Gets the dimensions of the console: (rows, cols).""" """Gets the dimensions of the console: (rows, cols)."""
def ioctl_GWINSZ(fd): def ioctl_GWINSZ(fd):
try: try:
rc = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234')) rc = struct.unpack('hh', fcntl.ioctl(
fd, termios.TIOCGWINSZ, '1234'))
except: except:
return return
return rc return rc

View file

@ -27,15 +27,14 @@
""" """
import os import os
import sys import sys
import fcntl
import termios
import struct
from StringIO import StringIO from StringIO import StringIO
from llnl.util.tty import terminal_size from llnl.util.tty import terminal_size
from llnl.util.tty.color import clen, cextra from llnl.util.tty.color import clen, cextra
class ColumnConfig: class ColumnConfig:
def __init__(self, cols): def __init__(self, cols):
self.cols = cols self.cols = cols
self.line_length = 0 self.line_length = 0
@ -43,7 +42,8 @@ def __init__(self, cols):
self.widths = [0] * cols # does not include ansi colors self.widths = [0] * cols # does not include ansi colors
def __repr__(self): def __repr__(self):
attrs = [(a,getattr(self, a)) for a in dir(self) if not a.startswith("__")] attrs = [(a, getattr(self, a))
for a in dir(self) if not a.startswith("__")]
return "<Config: %s>" % ", ".join("%s: %r" % a for a in attrs) return "<Config: %s>" % ", ".join("%s: %r" % a for a in attrs)
@ -68,7 +68,7 @@ def config_variable_cols(elts, console_width, padding, cols=0):
max_cols = min(len(elts), max_cols) max_cols = min(len(elts), max_cols)
# Range of column counts to try. If forced, use the supplied value. # Range of column counts to try. If forced, use the supplied value.
col_range = [cols] if cols else xrange(1, max_cols+1) col_range = [cols] if cols else xrange(1, max_cols + 1)
# Determine the most columns possible for the console width. # Determine the most columns possible for the console width.
configs = [ColumnConfig(c) for c in col_range] configs = [ColumnConfig(c) for c in col_range]
@ -106,7 +106,6 @@ def config_uniform_cols(elts, console_width, padding, cols=0):
# 'clen' ignores length of ansi color sequences. # 'clen' ignores length of ansi color sequences.
max_len = max(clen(e) for e in elts) + padding max_len = max(clen(e) for e in elts) + padding
max_clen = max(len(e) for e in elts) + padding
if cols == 0: if cols == 0:
cols = max(1, console_width / max_len) cols = max(1, console_width / max_len)
cols = min(len(elts), cols) cols = min(len(elts), cols)
@ -130,17 +129,19 @@ def colify(elts, **options):
output=<stream> A file object to write to. Default is sys.stdout. output=<stream> A file object to write to. Default is sys.stdout.
indent=<int> Optionally indent all columns by some number of spaces. indent=<int> Optionally indent all columns by some number of spaces.
padding=<int> Spaces between columns. Default is 2. padding=<int> Spaces between columns. Default is 2.
width=<int> Width of the output. Default is 80 if tty is not detected. width=<int> Width of the output. Default is 80 if tty not detected.
cols=<int> Force number of columns. Default is to size to terminal, cols=<int> Force number of columns. Default is to size to terminal,
or single-column if no tty or single-column if no tty
tty=<bool> Whether to attempt to write to a tty. Default is to tty=<bool> Whether to attempt to write to a tty. Default is to
autodetect a tty. Set to False to force single-column output. autodetect a tty. Set to False to force
single-column output.
method=<string> Method to use to fit columns. Options are variable or uniform. method=<string> Method to use to fit columns. Options are variable or
Variable-width columns are tighter, uniform columns are all the uniform. Variable-width columns are tighter, uniform
same width and fit less data on the screen. columns are all the same width and fit less data on
the screen.
""" """
# Get keyword arguments or set defaults # Get keyword arguments or set defaults
cols = options.pop("cols", 0) cols = options.pop("cols", 0)
@ -152,8 +153,9 @@ def colify(elts, **options):
console_cols = options.pop("width", None) console_cols = options.pop("width", None)
if options: if options:
raise TypeError("'%s' is an invalid keyword argument for this function." raise TypeError(
% next(options.iterkeys())) "'%s' is an invalid keyword argument for this function."
% next(options.iterkeys()))
# elts needs to be an array of strings so we can count the elements # elts needs to be an array of strings so we can count the elements
elts = [str(elt) for elt in elts] elts = [str(elt) for elt in elts]
@ -167,7 +169,8 @@ def colify(elts, **options):
r, c = env_size.split('x') r, c = env_size.split('x')
console_rows, console_cols = int(r), int(c) console_rows, console_cols = int(r), int(c)
tty = True tty = True
except: pass except:
pass
# Use only one column if not a tty. # Use only one column if not a tty.
if not tty: if not tty:
@ -228,6 +231,7 @@ def colify_table(table, **options):
raise ValueError("Table is empty in colify_table!") raise ValueError("Table is empty in colify_table!")
columns = len(table[0]) columns = len(table[0])
def transpose(): def transpose():
for i in xrange(columns): for i in xrange(columns):
for row in table: for row in table:

View file

@ -75,25 +75,27 @@
import re import re
import sys import sys
class ColorParseError(Exception): class ColorParseError(Exception):
"""Raised when a color format fails to parse.""" """Raised when a color format fails to parse."""
def __init__(self, message): def __init__(self, message):
super(ColorParseError, self).__init__(message) super(ColorParseError, self).__init__(message)
# Text styles for ansi codes # Text styles for ansi codes
styles = {'*' : '1', # bold styles = {'*': '1', # bold
'_' : '4', # underline '_': '4', # underline
None : '0' } # plain None: '0'} # plain
# Dim and bright ansi colors # Dim and bright ansi colors
colors = {'k' : 30, 'K' : 90, # black colors = {'k': 30, 'K': 90, # black
'r' : 31, 'R' : 91, # red 'r': 31, 'R': 91, # red
'g' : 32, 'G' : 92, # green 'g': 32, 'G': 92, # green
'y' : 33, 'Y' : 93, # yellow 'y': 33, 'Y': 93, # yellow
'b' : 34, 'B' : 94, # blue 'b': 34, 'B': 94, # blue
'm' : 35, 'M' : 95, # magenta 'm': 35, 'M': 95, # magenta
'c' : 36, 'C' : 96, # cyan 'c': 36, 'C': 96, # cyan
'w' : 37, 'W' : 97 } # white 'w': 37, 'W': 97} # white
# Regex to be used for color formatting # Regex to be used for color formatting
color_re = r'@(?:@|\.|([*_])?([a-zA-Z])?(?:{((?:[^}]|}})*)})?)' color_re = r'@(?:@|\.|([*_])?([a-zA-Z])?(?:{((?:[^}]|}})*)})?)'
@ -104,6 +106,7 @@ def __init__(self, message):
class match_to_ansi(object): class match_to_ansi(object):
def __init__(self, color=True): def __init__(self, color=True):
self.color = color self.color = color
@ -179,12 +182,14 @@ def cprint(string, stream=sys.stdout, color=None):
"""Same as cwrite, but writes a trailing newline to the stream.""" """Same as cwrite, but writes a trailing newline to the stream."""
cwrite(string + "\n", stream, color) cwrite(string + "\n", stream, color)
def cescape(string): def cescape(string):
"""Replace all @ with @@ in the string provided.""" """Replace all @ with @@ in the string provided."""
return str(string).replace('@', '@@') return str(string).replace('@', '@@')
class ColorStream(object): class ColorStream(object):
def __init__(self, stream, color=None): def __init__(self, stream, color=None):
self._stream = stream self._stream = stream
self._color = color self._color = color
@ -196,7 +201,7 @@ def write(self, string, **kwargs):
color = self._color color = self._color
if self._color is None: if self._color is None:
if raw: if raw:
color=True color = True
else: else:
color = self._stream.isatty() or _force_color color = self._stream.isatty() or _force_color
raw_write(colorize(string, color=color)) raw_write(colorize(string, color=color))

View file

@ -36,6 +36,7 @@
# Use this to strip escape sequences # Use this to strip escape sequences
_escape = re.compile(r'\x1b[^m]*m|\x1b\[?1034h') _escape = re.compile(r'\x1b[^m]*m|\x1b\[?1034h')
def _strip(line): def _strip(line):
"""Strip color and control characters from a line.""" """Strip color and control characters from a line."""
return _escape.sub('', line) return _escape.sub('', line)
@ -58,10 +59,10 @@ class keyboard_input(object):
When the with block completes, this will restore settings before When the with block completes, this will restore settings before
canonical and echo were disabled. canonical and echo were disabled.
""" """
def __init__(self, stream): def __init__(self, stream):
self.stream = stream self.stream = stream
def __enter__(self): def __enter__(self):
self.old_cfg = None self.old_cfg = None
@ -86,10 +87,9 @@ def __enter__(self):
# Apply new settings for terminal # Apply new settings for terminal
termios.tcsetattr(fd, termios.TCSADRAIN, self.new_cfg) termios.tcsetattr(fd, termios.TCSADRAIN, self.new_cfg)
except Exception, e: except Exception:
pass # Some OS's do not support termios, so ignore. pass # Some OS's do not support termios, so ignore.
def __exit__(self, exc_type, exception, traceback): def __exit__(self, exc_type, exception, traceback):
# If termios was avaialble, restore old settings after the # If termios was avaialble, restore old settings after the
# with block # with block
@ -114,6 +114,7 @@ class log_output(object):
Closes the provided stream when done with the block. Closes the provided stream when done with the block.
If echo is True, also prints the output to stdout. If echo is True, also prints the output to stdout.
""" """
def __init__(self, stream, echo=False, force_color=False, debug=False): def __init__(self, stream, echo=False, force_color=False, debug=False):
self.stream = stream self.stream = stream
@ -122,7 +123,7 @@ def __init__(self, stream, echo=False, force_color=False, debug=False):
self.force_color = force_color self.force_color = force_color
self.debug = debug self.debug = debug
# Default is to try file-descriptor reassignment unless the system # Default is to try file-descriptor reassignment unless the system
# out/err streams do not have an associated file descriptor # out/err streams do not have an associated file descriptor
self.directAssignment = False self.directAssignment = False
@ -130,7 +131,6 @@ def trace(self, frame, event, arg):
"""Jumps to __exit__ on the child process.""" """Jumps to __exit__ on the child process."""
raise _SkipWithBlock() raise _SkipWithBlock()
def __enter__(self): def __enter__(self):
"""Redirect output from the with block to a file. """Redirect output from the with block to a file.
@ -154,7 +154,8 @@ def __enter__(self):
with self.stream as log_file: with self.stream as log_file:
with keyboard_input(sys.stdin): with keyboard_input(sys.stdin):
while True: while True:
rlist, w, x = select.select([read_file, sys.stdin], [], []) rlist, w, x = select.select(
[read_file, sys.stdin], [], [])
if not rlist: if not rlist:
break break
@ -211,7 +212,6 @@ def __enter__(self):
if self.debug: if self.debug:
tty._debug = True tty._debug = True
def __exit__(self, exc_type, exception, traceback): def __exit__(self, exc_type, exception, traceback):
"""Exits on child, handles skipping the with block on parent.""" """Exits on child, handles skipping the with block on parent."""
# Child should just exit here. # Child should just exit here.
@ -235,7 +235,7 @@ def __exit__(self, exc_type, exception, traceback):
sys.stderr = self._stderr sys.stderr = self._stderr
else: else:
os.dup2(self._stdout, sys.stdout.fileno()) os.dup2(self._stdout, sys.stdout.fileno())
os.dup2(self._stderr, sys.stderr.fileno()) os.dup2(self._stderr, sys.stderr.fileno())
return False return False

View file

@ -30,15 +30,15 @@
from spack.util.executable import Executable, ProcessError from spack.util.executable import Executable, ProcessError
from llnl.util.lang import memoized from llnl.util.lang import memoized
class ABI(object): class ABI(object):
"""This class provides methods to test ABI compatibility between specs. """This class provides methods to test ABI compatibility between specs.
The current implementation is rather rough and could be improved.""" The current implementation is rather rough and could be improved."""
def architecture_compatible(self, parent, child): def architecture_compatible(self, parent, child):
"""Returns true iff the parent and child specs have ABI compatible targets.""" """Return true if parent and child have ABI compatible targets."""
return not parent.architecture or not child.architecture \ return not parent.architecture or not child.architecture or \
or parent.architecture == child.architecture parent.architecture == child.architecture
@memoized @memoized
def _gcc_get_libstdcxx_version(self, version): def _gcc_get_libstdcxx_version(self, version):
@ -61,8 +61,9 @@ def _gcc_get_libstdcxx_version(self, version):
else: else:
return None return None
try: try:
output = rungcc("--print-file-name=%s" % libname, return_output=True) output = rungcc("--print-file-name=%s" % libname,
except ProcessError, e: return_output=True)
except ProcessError:
return None return None
if not output: if not output:
return None return None
@ -71,7 +72,6 @@ def _gcc_get_libstdcxx_version(self, version):
return None return None
return os.path.basename(libpath) return os.path.basename(libpath)
@memoized @memoized
def _gcc_compiler_compare(self, pversion, cversion): def _gcc_compiler_compare(self, pversion, cversion):
"""Returns true iff the gcc version pversion and cversion """Returns true iff the gcc version pversion and cversion
@ -82,7 +82,6 @@ def _gcc_compiler_compare(self, pversion, cversion):
return False return False
return plib == clib return plib == clib
def _intel_compiler_compare(self, pversion, cversion): def _intel_compiler_compare(self, pversion, cversion):
"""Returns true iff the intel version pversion and cversion """Returns true iff the intel version pversion and cversion
are ABI compatible""" are ABI compatible"""
@ -92,9 +91,8 @@ def _intel_compiler_compare(self, pversion, cversion):
return False return False
return pversion.version[:2] == cversion.version[:2] return pversion.version[:2] == cversion.version[:2]
def compiler_compatible(self, parent, child, **kwargs): def compiler_compatible(self, parent, child, **kwargs):
"""Returns true iff the compilers for parent and child specs are ABI compatible""" """Return true if compilers for parent and child are ABI compatible."""
if not parent.compiler or not child.compiler: if not parent.compiler or not child.compiler:
return True return True
@ -109,8 +107,8 @@ def compiler_compatible(self, parent, child, **kwargs):
# TODO: into compiler classes? # TODO: into compiler classes?
for pversion in parent.compiler.versions: for pversion in parent.compiler.versions:
for cversion in child.compiler.versions: for cversion in child.compiler.versions:
# For a few compilers use specialized comparisons. Otherwise # For a few compilers use specialized comparisons.
# match on version match. # Otherwise match on version match.
if pversion.satisfies(cversion): if pversion.satisfies(cversion):
return True return True
elif (parent.compiler.name == "gcc" and elif (parent.compiler.name == "gcc" and
@ -121,9 +119,8 @@ def compiler_compatible(self, parent, child, **kwargs):
return True return True
return False return False
def compatible(self, parent, child, **kwargs): def compatible(self, parent, child, **kwargs):
"""Returns true iff a parent and child spec are ABI compatible""" """Returns true iff a parent and child spec are ABI compatible"""
loosematch = kwargs.get('loose', False) loosematch = kwargs.get('loose', False)
return self.architecture_compatible(parent, child) and \ return self.architecture_compatible(parent, child) and \
self.compiler_compatible(parent, child, loose=loosematch) self.compiler_compatible(parent, child, loose=loosematch)

View file

@ -91,6 +91,7 @@
class NoPlatformError(serr.SpackError): class NoPlatformError(serr.SpackError):
def __init__(self): def __init__(self):
super(NoPlatformError, self).__init__( super(NoPlatformError, self).__init__(
"Could not determine a platform for this machine.") "Could not determine a platform for this machine.")

View file

@ -240,4 +240,4 @@ def fmt(s):
else: else:
raise ValueError( raise ValueError(
"Invalid mode for display_specs: %s. Must be one of (paths," "Invalid mode for display_specs: %s. Must be one of (paths,"
"deps, short)." % mode) # NOQA: ignore=E501 "deps, short)." % mode)

View file

@ -29,12 +29,14 @@
description = "Activate a package extension." description = "Activate a package extension."
def setup_parser(subparser): def setup_parser(subparser):
subparser.add_argument( subparser.add_argument(
'-f', '--force', action='store_true', '-f', '--force', action='store_true',
help="Activate without first activating dependencies.") help="Activate without first activating dependencies.")
subparser.add_argument( subparser.add_argument(
'spec', nargs=argparse.REMAINDER, help="spec of package extension to activate.") 'spec', nargs=argparse.REMAINDER,
help="spec of package extension to activate.")
def activate(parser, args): def activate(parser, args):

View file

@ -22,10 +22,10 @@
# License along with this program; if not, write to the Free Software # License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import spack
import spack.architecture as architecture import spack.architecture as architecture
description = "Print the architecture for this machine" description = "Print the architecture for this machine"
def arch(parser, args): def arch(parser, args):
print architecture.sys_type() print architecture.sys_type()

View file

@ -25,7 +25,8 @@
import spack.cmd.location import spack.cmd.location
import spack.modules import spack.modules
description="cd to spack directories in the shell." description = "cd to spack directories in the shell."
def setup_parser(subparser): def setup_parser(subparser):
"""This is for decoration -- spack cd is used through spack's """This is for decoration -- spack cd is used through spack's

View file

@ -31,6 +31,7 @@
description = "Remove build stage and source tarball for packages." description = "Remove build stage and source tarball for packages."
def setup_parser(subparser): def setup_parser(subparser):
subparser.add_argument('packages', nargs=argparse.REMAINDER, subparser.add_argument('packages', nargs=argparse.REMAINDER,
help="specs of packages to clean") help="specs of packages to clean")

View file

@ -35,7 +35,7 @@
def add_common_arguments(parser, list_of_arguments): def add_common_arguments(parser, list_of_arguments):
for argument in list_of_arguments: for argument in list_of_arguments:
if argument not in _arguments: if argument not in _arguments:
message = 'Trying to add the non existing argument "{0}" to a command' # NOQA: ignore=E501 message = 'Trying to add non existing argument "{0}" to a command'
raise KeyError(message.format(argument)) raise KeyError(message.format(argument))
x = _arguments[argument] x = _arguments[argument]
parser.add_argument(*x.flags, **x.kwargs) parser.add_argument(*x.flags, **x.kwargs)
@ -82,7 +82,7 @@ def __call__(self, parser, namespace, values, option_string=None):
kwargs={ kwargs={
'action': 'store_true', 'action': 'store_true',
'dest': 'yes_to_all', 'dest': 'yes_to_all',
'help': 'Assume "yes" is the answer to every confirmation asked to the user.' # NOQA: ignore=E501 'help': 'Assume "yes" is the answer to every confirmation request.'
}) })
_arguments['yes_to_all'] = parms _arguments['yes_to_all'] = parms

View file

@ -37,6 +37,7 @@
description = "Manage compilers" description = "Manage compilers"
def setup_parser(subparser): def setup_parser(subparser):
sp = subparser.add_subparsers( sp = subparser.add_subparsers(
metavar='SUBCOMMAND', dest='compiler_command') metavar='SUBCOMMAND', dest='compiler_command')
@ -44,48 +45,58 @@ def setup_parser(subparser):
scopes = spack.config.config_scopes scopes = spack.config.config_scopes
# Find # Find
find_parser = sp.add_parser('find', aliases=['add'], help='Search the system for compilers to add to the Spack configuration.') find_parser = sp.add_parser(
'find', aliases=['add'],
help='Search the system for compilers to add to Spack configuration.')
find_parser.add_argument('add_paths', nargs=argparse.REMAINDER) find_parser.add_argument('add_paths', nargs=argparse.REMAINDER)
find_parser.add_argument('--scope', choices=scopes, default=spack.cmd.default_modify_scope, find_parser.add_argument(
help="Configuration scope to modify.") '--scope', choices=scopes, default=spack.cmd.default_modify_scope,
help="Configuration scope to modify.")
# Remove # Remove
remove_parser = sp.add_parser('remove', aliases=['rm'], help='Remove compiler by spec.') remove_parser = sp.add_parser(
'remove', aliases=['rm'], help='Remove compiler by spec.')
remove_parser.add_argument( remove_parser.add_argument(
'-a', '--all', action='store_true', help='Remove ALL compilers that match spec.') '-a', '--all', action='store_true',
help='Remove ALL compilers that match spec.')
remove_parser.add_argument('compiler_spec') remove_parser.add_argument('compiler_spec')
remove_parser.add_argument('--scope', choices=scopes, default=spack.cmd.default_modify_scope, remove_parser.add_argument(
help="Configuration scope to modify.") '--scope', choices=scopes, default=spack.cmd.default_modify_scope,
help="Configuration scope to modify.")
# List # List
list_parser = sp.add_parser('list', help='list available compilers') list_parser = sp.add_parser('list', help='list available compilers')
list_parser.add_argument('--scope', choices=scopes, default=spack.cmd.default_list_scope, list_parser.add_argument(
help="Configuration scope to read from.") '--scope', choices=scopes, default=spack.cmd.default_list_scope,
help="Configuration scope to read from.")
# Info # Info
info_parser = sp.add_parser('info', help='Show compiler paths.') info_parser = sp.add_parser('info', help='Show compiler paths.')
info_parser.add_argument('compiler_spec') info_parser.add_argument('compiler_spec')
info_parser.add_argument('--scope', choices=scopes, default=spack.cmd.default_list_scope, info_parser.add_argument(
help="Configuration scope to read from.") '--scope', choices=scopes, default=spack.cmd.default_list_scope,
help="Configuration scope to read from.")
def compiler_find(args): def compiler_find(args):
"""Search either $PATH or a list of paths OR MODULES for compilers and add them """Search either $PATH or a list of paths OR MODULES for compilers and
to Spack's configuration.""" add them to Spack's configuration.
"""
paths = args.add_paths paths = args.add_paths
if not paths: if not paths:
paths = get_path('PATH') paths = get_path('PATH')
# Don't initialize compilers config via compilers.get_compiler_config. # Don't initialize compilers config via compilers.get_compiler_config.
# Just let compiler_find do the # Just let compiler_find do the
# entire process and return an empty config from all_compilers # entire process and return an empty config from all_compilers
# Default for any other process is init_config=True # Default for any other process is init_config=True
compilers = [c for c in spack.compilers.find_compilers(*paths) compilers = [c for c in spack.compilers.find_compilers(*paths)
if c.spec not in spack.compilers.all_compilers( if c.spec not in spack.compilers.all_compilers(
scope=args.scope, init_config=False)] scope=args.scope, init_config=False)]
if compilers: if compilers:
spack.compilers.add_compilers_to_config(compilers, scope=args.scope, spack.compilers.add_compilers_to_config(compilers, scope=args.scope,
init_config=False) init_config=False)
n = len(compilers) n = len(compilers)
s = 's' if n > 1 else '' s = 's' if n > 1 else ''
filename = spack.config.get_config_filename(args.scope, 'compilers') filename = spack.config.get_config_filename(args.scope, 'compilers')
@ -103,11 +114,12 @@ def compiler_remove(args):
elif not args.all and len(compilers) > 1: elif not args.all and len(compilers) > 1:
tty.error("Multiple compilers match spec %s. Choose one:" % cspec) tty.error("Multiple compilers match spec %s. Choose one:" % cspec)
colify(reversed(sorted([c.spec for c in compilers])), indent=4) colify(reversed(sorted([c.spec for c in compilers])), indent=4)
tty.msg("Or, you can use `spack compiler remove -a` to remove all of them.") tty.msg("Or, use `spack compiler remove -a` to remove all of them.")
sys.exit(1) sys.exit(1)
for compiler in compilers: for compiler in compilers:
spack.compilers.remove_compiler_from_config(compiler.spec, scope=args.scope) spack.compilers.remove_compiler_from_config(
compiler.spec, scope=args.scope)
tty.msg("Removed compiler %s" % compiler.spec) tty.msg("Removed compiler %s" % compiler.spec)
@ -133,7 +145,8 @@ def compiler_list(args):
tty.msg("Available compilers") tty.msg("Available compilers")
index = index_by(spack.compilers.all_compilers(scope=args.scope), 'name') index = index_by(spack.compilers.all_compilers(scope=args.scope), 'name')
for i, (name, compilers) in enumerate(index.items()): for i, (name, compilers) in enumerate(index.items()):
if i >= 1: print if i >= 1:
print
cname = "%s{%s}" % (spack.spec.compiler_color, name) cname = "%s{%s}" % (spack.spec.compiler_color, name)
tty.hline(colorize(cname), char='-') tty.hline(colorize(cname), char='-')
@ -141,10 +154,10 @@ def compiler_list(args):
def compiler(parser, args): def compiler(parser, args):
action = {'add' : compiler_find, action = {'add': compiler_find,
'find' : compiler_find, 'find': compiler_find,
'remove' : compiler_remove, 'remove': compiler_remove,
'rm' : compiler_remove, 'rm': compiler_remove,
'info' : compiler_info, 'info': compiler_info,
'list' : compiler_list } 'list': compiler_list}
action[args.compiler_command](args) action[args.compiler_command](args)

View file

@ -22,18 +22,16 @@
# License along with this program; if not, write to the Free Software # License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import llnl.util.tty as tty
from llnl.util.tty.colify import colify
from llnl.util.lang import index_by
import spack import spack
from spack.cmd.compiler import compiler_list from spack.cmd.compiler import compiler_list
description = "List available compilers. Same as 'spack compiler list'." description = "List available compilers. Same as 'spack compiler list'."
def setup_parser(subparser): def setup_parser(subparser):
subparser.add_argument('--scope', choices=spack.config.config_scopes, subparser.add_argument('--scope', choices=spack.config.config_scopes,
help="Configuration scope to read/modify.") help="Configuration scope to read/modify.")
def compilers(parser, args): def compilers(parser, args):
compiler_list(args) compiler_list(args)

View file

@ -22,15 +22,11 @@
# License along with this program; if not, write to the Free Software # License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import sys
import argparse
import llnl.util.tty as tty
import spack.config import spack.config
description = "Get and set configuration options." description = "Get and set configuration options."
def setup_parser(subparser): def setup_parser(subparser):
# User can only choose one # User can only choose one
scope_group = subparser.add_mutually_exclusive_group() scope_group = subparser.add_mutually_exclusive_group()
@ -64,6 +60,6 @@ def config_edit(args):
def config(parser, args): def config(parser, args):
action = { 'get' : config_get, action = {'get': config_get,
'edit' : config_edit } 'edit': config_edit}
action[args.config_command](args) action[args.config_command](args)

View file

@ -217,6 +217,7 @@ def setup_parser(subparser):
class BuildSystemGuesser(object): class BuildSystemGuesser(object):
def __call__(self, stage, url): def __call__(self, stage, url):
"""Try to guess the type of build system used by a project based on """Try to guess the type of build system used by a project based on
the contents of its archive or the URL it was downloaded from.""" the contents of its archive or the URL it was downloaded from."""

View file

@ -31,6 +31,7 @@
description = "Deactivate a package extension." description = "Deactivate a package extension."
def setup_parser(subparser): def setup_parser(subparser):
subparser.add_argument( subparser.add_argument(
'-f', '--force', action='store_true', '-f', '--force', action='store_true',
@ -40,7 +41,8 @@ def setup_parser(subparser):
help="Deactivate all extensions of an extendable package, or " help="Deactivate all extensions of an extendable package, or "
"deactivate an extension AND its dependencies.") "deactivate an extension AND its dependencies.")
subparser.add_argument( subparser.add_argument(
'spec', nargs=argparse.REMAINDER, help="spec of package extension to deactivate.") 'spec', nargs=argparse.REMAINDER,
help="spec of package extension to deactivate.")
def deactivate(parser, args): def deactivate(parser, args):
@ -65,7 +67,8 @@ def deactivate(parser, args):
if not args.force and not spec.package.activated: if not args.force and not spec.package.activated:
tty.die("%s is not activated." % pkg.spec.short_spec) tty.die("%s is not activated." % pkg.spec.short_spec)
tty.msg("Deactivating %s and all dependencies." % pkg.spec.short_spec) tty.msg("Deactivating %s and all dependencies." %
pkg.spec.short_spec)
topo_order = topological_sort(spec) topo_order = topological_sort(spec)
index = spec.index() index = spec.index()
@ -79,7 +82,9 @@ def deactivate(parser, args):
epkg.do_deactivate(force=args.force) epkg.do_deactivate(force=args.force)
else: else:
tty.die("spack deactivate --all requires an extendable package or an extension.") tty.die(
"spack deactivate --all requires an extendable package "
"or an extension.")
else: else:
if not pkg.is_extension: if not pkg.is_extension:

View file

@ -31,9 +31,11 @@
description = "Show installed packages that depend on another." description = "Show installed packages that depend on another."
def setup_parser(subparser): def setup_parser(subparser):
subparser.add_argument( subparser.add_argument(
'spec', nargs=argparse.REMAINDER, help="specs to list dependencies of.") 'spec', nargs=argparse.REMAINDER,
help="specs to list dependencies of.")
def dependents(parser, args): def dependents(parser, args):
@ -42,5 +44,6 @@ def dependents(parser, args):
tty.die("spack dependents takes only one spec.") tty.die("spack dependents takes only one spec.")
fmt = '$_$@$%@$+$=$#' fmt = '$_$@$%@$+$=$#'
deps = [d.format(fmt, color=True) for d in specs[0].package.installed_dependents] deps = [d.format(fmt, color=True)
for d in specs[0].package.installed_dependents]
tty.msg("Dependents of %s" % specs[0].format(fmt, color=True), *deps) tty.msg("Dependents of %s" % specs[0].format(fmt, color=True), *deps)

View file

@ -35,6 +35,7 @@
description = "Do-It-Yourself: build from an existing source directory." description = "Do-It-Yourself: build from an existing source directory."
def setup_parser(subparser): def setup_parser(subparser):
subparser.add_argument( subparser.add_argument(
'-i', '--ignore-dependencies', action='store_true', dest='ignore_deps', '-i', '--ignore-dependencies', action='store_true', dest='ignore_deps',
@ -76,14 +77,17 @@ def diy(self, args):
return return
if not spec.versions.concrete: if not spec.versions.concrete:
tty.die("spack diy spec must have a single, concrete version. Did you forget a package version number?") tty.die(
"spack diy spec must have a single, concrete version. "
"Did you forget a package version number?")
spec.concretize() spec.concretize()
package = spack.repo.get(spec) package = spack.repo.get(spec)
if package.installed: if package.installed:
tty.error("Already installed in %s" % package.prefix) tty.error("Already installed in %s" % package.prefix)
tty.msg("Uninstall or try adding a version suffix for this DIY build.") tty.msg("Uninstall or try adding a version suffix for this "
"DIY build.")
sys.exit(1) sys.exit(1)
# Forces the build to run out of the current directory. # Forces the build to run out of the current directory.

View file

@ -25,6 +25,7 @@
description = "Run pydoc from within spack." description = "Run pydoc from within spack."
def setup_parser(subparser): def setup_parser(subparser):
subparser.add_argument('entity', help="Run pydoc help on entity") subparser.add_argument('entity', help="Run pydoc help on entity")

View file

@ -68,7 +68,7 @@ def edit_package(name, repo_path, namespace, force=False):
if os.path.exists(path): if os.path.exists(path):
if not os.path.isfile(path): if not os.path.isfile(path):
tty.die("Something's wrong. '%s' is not a file!" % path) tty.die("Something's wrong. '%s' is not a file!" % path)
if not os.access(path, os.R_OK|os.W_OK): if not os.access(path, os.R_OK | os.W_OK):
tty.die("Insufficient permissions on '%s'!" % path) tty.die("Insufficient permissions on '%s'!" % path)
elif not force: elif not force:
tty.die("No package '%s'. Use spack create, or supply -f/--force " tty.die("No package '%s'. Use spack create, or supply -f/--force "
@ -93,19 +93,23 @@ def setup_parser(subparser):
# Various filetypes you can edit directly from the cmd line. # Various filetypes you can edit directly from the cmd line.
excl_args.add_argument( excl_args.add_argument(
'-c', '--command', dest='path', action='store_const', '-c', '--command', dest='path', action='store_const',
const=spack.cmd.command_path, help="Edit the command with the supplied name.") const=spack.cmd.command_path,
help="Edit the command with the supplied name.")
excl_args.add_argument( excl_args.add_argument(
'-t', '--test', dest='path', action='store_const', '-t', '--test', dest='path', action='store_const',
const=spack.test_path, help="Edit the test with the supplied name.") const=spack.test_path, help="Edit the test with the supplied name.")
excl_args.add_argument( excl_args.add_argument(
'-m', '--module', dest='path', action='store_const', '-m', '--module', dest='path', action='store_const',
const=spack.module_path, help="Edit the main spack module with the supplied name.") const=spack.module_path,
help="Edit the main spack module with the supplied name.")
# Options for editing packages # Options for editing packages
excl_args.add_argument( excl_args.add_argument(
'-r', '--repo', default=None, help="Path to repo to edit package in.") '-r', '--repo', default=None,
help="Path to repo to edit package in.")
excl_args.add_argument( excl_args.add_argument(
'-N', '--namespace', default=None, help="Namespace of package to edit.") '-N', '--namespace', default=None,
help="Namespace of package to edit.")
subparser.add_argument( subparser.add_argument(
'name', nargs='?', default=None, help="name of package to edit") 'name', nargs='?', default=None, help="name of package to edit")

View file

@ -28,11 +28,13 @@
import spack.cmd import spack.cmd
import spack.build_environment as build_env import spack.build_environment as build_env
description = "Run a command with the environment for a particular spec's install." description = "Run a command with the install environment for a spec."
def setup_parser(subparser): def setup_parser(subparser):
subparser.add_argument( subparser.add_argument(
'spec', nargs=argparse.REMAINDER, help="specs of package environment to emulate.") 'spec', nargs=argparse.REMAINDER,
help="specs of package environment to emulate.")
def env(parser, args): def env(parser, args):
@ -47,7 +49,7 @@ def env(parser, args):
if sep in args.spec: if sep in args.spec:
s = args.spec.index(sep) s = args.spec.index(sep)
spec = args.spec[:s] spec = args.spec[:s]
cmd = args.spec[s+1:] cmd = args.spec[s + 1:]
else: else:
spec = args.spec[0] spec = args.spec[0]
cmd = args.spec[1:] cmd = args.spec[1:]

View file

@ -22,7 +22,6 @@
# License along with this program; if not, write to the Free Software # License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import sys
import argparse import argparse
import llnl.util.tty as tty import llnl.util.tty as tty
@ -34,6 +33,7 @@
description = "List extensions for package." description = "List extensions for package."
def setup_parser(subparser): def setup_parser(subparser):
format_group = subparser.add_mutually_exclusive_group() format_group = subparser.add_mutually_exclusive_group()
format_group.add_argument( format_group.add_argument(
@ -47,7 +47,8 @@ def setup_parser(subparser):
help='Show full dependency DAG of extensions') help='Show full dependency DAG of extensions')
subparser.add_argument( subparser.add_argument(
'spec', nargs=argparse.REMAINDER, help='Spec of package to list extensions for') 'spec', nargs=argparse.REMAINDER,
help='Spec of package to list extensions for')
def extensions(parser, args): def extensions(parser, args):
@ -85,7 +86,8 @@ def extensions(parser, args):
# #
# List specs of installed extensions. # List specs of installed extensions.
# #
installed = [s.spec for s in spack.installed_db.installed_extensions_for(spec)] installed = [
s.spec for s in spack.installed_db.installed_extensions_for(spec)]
print print
if not installed: if not installed:
tty.msg("None installed.") tty.msg("None installed.")
@ -102,4 +104,5 @@ def extensions(parser, args):
tty.msg("None activated.") tty.msg("None activated.")
return return
tty.msg("%d currently activated:" % len(activated)) tty.msg("%d currently activated:" % len(activated))
spack.cmd.find.display_specs(activated.values(), mode=args.mode, long=args.long) spack.cmd.find.display_specs(
activated.values(), mode=args.mode, long=args.long)

View file

@ -29,16 +29,21 @@
description = "Fetch archives for packages" description = "Fetch archives for packages"
def setup_parser(subparser): def setup_parser(subparser):
subparser.add_argument( subparser.add_argument(
'-n', '--no-checksum', action='store_true', dest='no_checksum', '-n', '--no-checksum', action='store_true', dest='no_checksum',
help="Do not check packages against checksum") help="Do not check packages against checksum")
subparser.add_argument( subparser.add_argument(
'-m', '--missing', action='store_true', help="Also fetch all missing dependencies") '-m', '--missing', action='store_true',
help="Also fetch all missing dependencies")
subparser.add_argument( subparser.add_argument(
'-D', '--dependencies', action='store_true', help="Also fetch all dependencies") '-D', '--dependencies', action='store_true',
help="Also fetch all dependencies")
subparser.add_argument( subparser.add_argument(
'packages', nargs=argparse.REMAINDER, help="specs of packages to fetch") 'packages', nargs=argparse.REMAINDER,
help="specs of packages to fetch")
def fetch(parser, args): def fetch(parser, args):
if not args.packages: if not args.packages:
@ -50,7 +55,6 @@ def fetch(parser, args):
specs = spack.cmd.parse_specs(args.packages, concretize=True) specs = spack.cmd.parse_specs(args.packages, concretize=True)
for spec in specs: for spec in specs:
if args.missing or args.dependencies: if args.missing or args.dependencies:
to_fetch = set()
for s in spec.traverse(deptype_query=spack.alldeps): for s in spec.traverse(deptype_query=spack.alldeps):
package = spack.repo.get(s) package = spack.repo.get(s)
if args.missing and package.installed: if args.missing and package.installed:

View file

@ -30,6 +30,7 @@
description = "Generate graphs of package dependency relationships." description = "Generate graphs of package dependency relationships."
def setup_parser(subparser): def setup_parser(subparser):
setup_parser.parser = subparser setup_parser.parser = subparser
@ -42,10 +43,12 @@ def setup_parser(subparser):
help="Generate graph in dot format and print to stdout.") help="Generate graph in dot format and print to stdout.")
subparser.add_argument( subparser.add_argument(
'--concretize', action='store_true', help="Concretize specs before graphing.") '--concretize', action='store_true',
help="Concretize specs before graphing.")
subparser.add_argument( subparser.add_argument(
'specs', nargs=argparse.REMAINDER, help="specs of packages to graph.") 'specs', nargs=argparse.REMAINDER,
help="specs of packages to graph.")
def graph(parser, args): def graph(parser, args):
@ -56,11 +59,11 @@ def graph(parser, args):
setup_parser.parser.print_help() setup_parser.parser.print_help()
return 1 return 1
if args.dot: # Dot graph only if asked for. if args.dot: # Dot graph only if asked for.
graph_dot(*specs) graph_dot(*specs)
elif specs: # ascii is default: user doesn't need to provide it explicitly elif specs: # ascii is default: user doesn't need to provide it explicitly
graph_ascii(specs[0], debug=spack.debug) graph_ascii(specs[0], debug=spack.debug)
for spec in specs[1:]: for spec in specs[1:]:
print # extra line bt/w independent graphs print # extra line bt/w independent graphs
graph_ascii(spec, debug=spack.debug) graph_ascii(spec, debug=spack.debug)

View file

@ -22,14 +22,14 @@
# License along with this program; if not, write to the Free Software # License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import sys
description = "Get help on spack and its commands" description = "Get help on spack and its commands"
def setup_parser(subparser): def setup_parser(subparser):
subparser.add_argument('help_command', nargs='?', default=None, subparser.add_argument('help_command', nargs='?', default=None,
help='command to get help on') help='command to get help on')
def help(parser, args): def help(parser, args):
if args.help_command: if args.help_command:
parser.parse_args([args.help_command, '-h']) parser.parse_args([args.help_command, '-h'])

View file

@ -31,6 +31,7 @@
description = "Build and install packages" description = "Build and install packages"
def setup_parser(subparser): def setup_parser(subparser):
subparser.add_argument( subparser.add_argument(
'-i', '--ignore-dependencies', action='store_true', dest='ignore_deps', '-i', '--ignore-dependencies', action='store_true', dest='ignore_deps',
@ -52,18 +53,18 @@ def setup_parser(subparser):
help="Display verbose build output while installing.") help="Display verbose build output while installing.")
subparser.add_argument( subparser.add_argument(
'--fake', action='store_true', dest='fake', '--fake', action='store_true', dest='fake',
help="Fake install. Just remove the prefix and touch a fake file in it.") help="Fake install. Just remove prefix and create a fake file.")
subparser.add_argument( subparser.add_argument(
'--dirty', action='store_true', dest='dirty', '--dirty', action='store_true', dest='dirty',
help="Install a package *without* cleaning the environment.") help="Install a package *without* cleaning the environment.")
subparser.add_argument( subparser.add_argument(
'packages', nargs=argparse.REMAINDER, help="specs of packages to install") 'packages', nargs=argparse.REMAINDER,
help="specs of packages to install")
subparser.add_argument( subparser.add_argument(
'--run-tests', action='store_true', dest='run_tests', '--run-tests', action='store_true', dest='run_tests',
help="Run tests during installation of a package.") help="Run tests during installation of a package.")
def install(parser, args): def install(parser, args):
if not args.packages: if not args.packages:
tty.die("install requires at least one package argument") tty.die("install requires at least one package argument")

View file

@ -25,13 +25,16 @@
import argparse import argparse
import spack.modules import spack.modules
description ="Add package to environment using modules." description = "Add package to environment using modules."
def setup_parser(subparser): def setup_parser(subparser):
"""Parser is only constructed so that this prints a nice help """Parser is only constructed so that this prints a nice help
message with -h. """ message with -h. """
subparser.add_argument( subparser.add_argument(
'spec', nargs=argparse.REMAINDER, help="Spec of package to load with modules. (If -, read specs from STDIN)") 'spec', nargs=argparse.REMAINDER,
help="Spec of package to load with modules. "
"(If -, read specs from STDIN)")
def load(parser, args): def load(parser, args):

View file

@ -22,8 +22,6 @@
# License along with this program; if not, write to the Free Software # License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import os
import sys
import argparse import argparse
import llnl.util.tty as tty import llnl.util.tty as tty
@ -32,16 +30,19 @@
import spack import spack
import spack.cmd import spack.cmd
description="Print out locations of various directories used by Spack" description = "Print out locations of various directories used by Spack"
def setup_parser(subparser): def setup_parser(subparser):
global directories global directories
directories = subparser.add_mutually_exclusive_group() directories = subparser.add_mutually_exclusive_group()
directories.add_argument( directories.add_argument(
'-m', '--module-dir', action='store_true', help="Spack python module directory.") '-m', '--module-dir', action='store_true',
help="Spack python module directory.")
directories.add_argument( directories.add_argument(
'-r', '--spack-root', action='store_true', help="Spack installation root.") '-r', '--spack-root', action='store_true',
help="Spack installation root.")
directories.add_argument( directories.add_argument(
'-i', '--install-dir', action='store_true', '-i', '--install-dir', action='store_true',
@ -53,15 +54,19 @@ def setup_parser(subparser):
'-P', '--packages', action='store_true', '-P', '--packages', action='store_true',
help="Top-level packages directory for Spack.") help="Top-level packages directory for Spack.")
directories.add_argument( directories.add_argument(
'-s', '--stage-dir', action='store_true', help="Stage directory for a spec.") '-s', '--stage-dir', action='store_true',
help="Stage directory for a spec.")
directories.add_argument( directories.add_argument(
'-S', '--stages', action='store_true', help="Top level Stage directory.") '-S', '--stages', action='store_true',
help="Top level Stage directory.")
directories.add_argument( directories.add_argument(
'-b', '--build-dir', action='store_true', '-b', '--build-dir', action='store_true',
help="Checked out or expanded source directory for a spec (requires it to be staged first).") help="Checked out or expanded source directory for a spec "
"(requires it to be staged first).")
subparser.add_argument( subparser.add_argument(
'spec', nargs=argparse.REMAINDER, help="spec of package to fetch directory for.") 'spec', nargs=argparse.REMAINDER,
help="spec of package to fetch directory for.")
def location(parser, args): def location(parser, args):
@ -104,9 +109,9 @@ def location(parser, args):
if args.stage_dir: if args.stage_dir:
print pkg.stage.path print pkg.stage.path
else: # args.build_dir is the default. else: # args.build_dir is the default.
if not pkg.stage.source_path: if not pkg.stage.source_path:
tty.die("Build directory does not exist yet. Run this to create it:", tty.die("Build directory does not exist yet. "
"Run this to create it:",
"spack stage " + " ".join(args.spec)) "spack stage " + " ".join(args.spec))
print pkg.stage.source_path print pkg.stage.source_path

View file

@ -23,7 +23,6 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import os import os
import sys
from datetime import datetime from datetime import datetime
import argparse import argparse
@ -40,6 +39,7 @@
description = "Manage mirrors." description = "Manage mirrors."
def setup_parser(subparser): def setup_parser(subparser):
subparser.add_argument( subparser.add_argument(
'-n', '--no-checksum', action='store_true', dest='no_checksum', '-n', '--no-checksum', action='store_true', dest='no_checksum',
@ -61,8 +61,9 @@ def setup_parser(subparser):
'-D', '--dependencies', action='store_true', '-D', '--dependencies', action='store_true',
help="Also fetch all dependencies") help="Also fetch all dependencies")
create_parser.add_argument( create_parser.add_argument(
'-o', '--one-version-per-spec', action='store_const', const=1, default=0, '-o', '--one-version-per-spec', action='store_const',
help="Only fetch one 'preferred' version per spec, not all known versions.") const=1, default=0,
help="Only fetch one 'preferred' version per spec, not all known.")
scopes = spack.config.config_scopes scopes = spack.config.config_scopes
@ -70,7 +71,7 @@ def setup_parser(subparser):
add_parser = sp.add_parser('add', help=mirror_add.__doc__) add_parser = sp.add_parser('add', help=mirror_add.__doc__)
add_parser.add_argument('name', help="Mnemonic name for mirror.") add_parser.add_argument('name', help="Mnemonic name for mirror.")
add_parser.add_argument( add_parser.add_argument(
'url', help="URL of mirror directory created by 'spack mirror create'.") 'url', help="URL of mirror directory from 'spack mirror create'.")
add_parser.add_argument( add_parser.add_argument(
'--scope', choices=scopes, default=spack.cmd.default_modify_scope, '--scope', choices=scopes, default=spack.cmd.default_modify_scope,
help="Configuration scope to modify.") help="Configuration scope to modify.")
@ -107,7 +108,7 @@ def mirror_add(args):
tty.die("Mirror with url %s already exists." % url) tty.die("Mirror with url %s already exists." % url)
# should only be one item per mirror dict. # should only be one item per mirror dict.
items = [(n,u) for n,u in mirrors.items()] items = [(n, u) for n, u in mirrors.items()]
items.insert(0, (args.name, url)) items.insert(0, (args.name, url))
mirrors = syaml_dict(items) mirrors = syaml_dict(items)
spack.config.update_config('mirrors', mirrors, scope=args.scope) spack.config.update_config('mirrors', mirrors, scope=args.scope)
@ -121,7 +122,7 @@ def mirror_remove(args):
if not mirrors: if not mirrors:
mirrors = syaml_dict() mirrors = syaml_dict()
if not name in mirrors: if name not in mirrors:
tty.die("No mirror with name %s" % name) tty.die("No mirror with name %s" % name)
old_value = mirrors.pop(name) old_value = mirrors.pop(name)
@ -152,7 +153,7 @@ def _read_specs_from_file(filename):
s.package s.package
specs.append(s) specs.append(s)
except SpackError, e: except SpackError, e:
tty.die("Parse error in %s, line %d:" % (args.file, i+1), tty.die("Parse error in %s, line %d:" % (args.file, i + 1),
">>> " + string, str(e)) ">>> " + string, str(e))
return specs return specs
@ -214,10 +215,10 @@ def mirror_create(args):
def mirror(parser, args): def mirror(parser, args):
action = { 'create' : mirror_create, action = {'create': mirror_create,
'add' : mirror_add, 'add': mirror_add,
'remove' : mirror_remove, 'remove': mirror_remove,
'rm' : mirror_remove, 'rm': mirror_remove,
'list' : mirror_list } 'list': mirror_list}
action[args.mirror_command](args) action[args.mirror_command](args)

View file

@ -118,7 +118,8 @@ def loads(mtype, specs, args):
seen_add = seen.add seen_add = seen.add
for spec in specs_from_user_constraint: for spec in specs_from_user_constraint:
specs.extend( specs.extend(
[item for item in spec.traverse(order='post', cover='nodes') if not (item in seen or seen_add(item))] # NOQA: ignore=E501 [item for item in spec.traverse(order='post', cover='nodes')
if not (item in seen or seen_add(item))]
) )
module_cls = module_types[mtype] module_cls = module_types[mtype]
@ -178,7 +179,9 @@ def rm(mtype, specs, args):
# Ask for confirmation # Ask for confirmation
if not args.yes_to_all: if not args.yes_to_all:
tty.msg('You are about to remove {0} module files the following specs:\n'.format(mtype)) # NOQA: ignore=E501 tty.msg(
'You are about to remove {0} module files the following specs:\n'
.format(mtype))
spack.cmd.display_specs(specs_with_modules, long=True) spack.cmd.display_specs(specs_with_modules, long=True)
print('') print('')
spack.cmd.ask_for_confirmation('Do you want to proceed ? ') spack.cmd.ask_for_confirmation('Do you want to proceed ? ')
@ -197,7 +200,9 @@ def refresh(mtype, specs, args):
return return
if not args.yes_to_all: if not args.yes_to_all:
tty.msg('You are about to regenerate {name} module files for the following specs:\n'.format(name=mtype)) # NOQA: ignore=E501 tty.msg(
'You are about to regenerate {name} module files for:\n'
.format(name=mtype))
spack.cmd.display_specs(specs, long=True) spack.cmd.display_specs(specs, long=True)
print('') print('')
spack.cmd.ask_for_confirmation('Do you want to proceed ? ') spack.cmd.ask_for_confirmation('Do you want to proceed ? ')
@ -245,11 +250,13 @@ def module(parser, args):
try: try:
callbacks[args.subparser_name](module_type, args.specs, args) callbacks[args.subparser_name](module_type, args.specs, args)
except MultipleMatches: except MultipleMatches:
message = 'the constraint \'{query}\' matches multiple packages, and this is not allowed in this context' # NOQA: ignore=E501 message = ('the constraint \'{query}\' matches multiple packages, '
'and this is not allowed in this context')
tty.error(message.format(query=constraint)) tty.error(message.format(query=constraint))
for s in args.specs: for s in args.specs:
sys.stderr.write(s.format(color=True) + '\n') sys.stderr.write(s.format(color=True) + '\n')
raise SystemExit(1) raise SystemExit(1)
except NoMatch: except NoMatch:
message = 'the constraint \'{query}\' match no package, and this is not allowed in this context' # NOQA: ignore=E501 message = ('the constraint \'{query}\' match no package, '
'and this is not allowed in this context')
tty.die(message.format(query=constraint)) tty.die(message.format(query=constraint))

View file

@ -32,7 +32,7 @@
def github_url(pkg): def github_url(pkg):
"""Link to a package file on github.""" """Link to a package file on github."""
url = "https://github.com/llnl/spack/blob/master/var/spack/packages/%s/package.py" # NOQA: ignore=E501 url = "https://github.com/llnl/spack/blob/master/var/spack/packages/%s/package.py"
return (url % pkg.name) return (url % pkg.name)

View file

@ -29,14 +29,16 @@
import spack import spack
description="Patch expanded archive sources in preparation for install" description = "Patch expanded archive sources in preparation for install"
def setup_parser(subparser): def setup_parser(subparser):
subparser.add_argument( subparser.add_argument(
'-n', '--no-checksum', action='store_true', dest='no_checksum', '-n', '--no-checksum', action='store_true', dest='no_checksum',
help="Do not check downloaded packages against checksum") help="Do not check downloaded packages against checksum")
subparser.add_argument( subparser.add_argument(
'packages', nargs=argparse.REMAINDER, help="specs of packages to stage") 'packages', nargs=argparse.REMAINDER,
help="specs of packages to stage")
def patch(parser, args): def patch(parser, args):

View file

@ -33,6 +33,7 @@
description = "Query packages associated with particular git revisions." description = "Query packages associated with particular git revisions."
def setup_parser(subparser): def setup_parser(subparser):
sp = subparser.add_subparsers( sp = subparser.add_subparsers(
metavar='SUBCOMMAND', dest='pkg_command') metavar='SUBCOMMAND', dest='pkg_command')
@ -46,22 +47,28 @@ def setup_parser(subparser):
help="Revision to list packages for.") help="Revision to list packages for.")
diff_parser = sp.add_parser('diff', help=pkg_diff.__doc__) diff_parser = sp.add_parser('diff', help=pkg_diff.__doc__)
diff_parser.add_argument('rev1', nargs='?', default='HEAD^', diff_parser.add_argument(
help="Revision to compare against.") 'rev1', nargs='?', default='HEAD^',
diff_parser.add_argument('rev2', nargs='?', default='HEAD', help="Revision to compare against.")
help="Revision to compare to rev1 (default is HEAD).") diff_parser.add_argument(
'rev2', nargs='?', default='HEAD',
help="Revision to compare to rev1 (default is HEAD).")
add_parser = sp.add_parser('added', help=pkg_added.__doc__) add_parser = sp.add_parser('added', help=pkg_added.__doc__)
add_parser.add_argument('rev1', nargs='?', default='HEAD^', add_parser.add_argument(
help="Revision to compare against.") 'rev1', nargs='?', default='HEAD^',
add_parser.add_argument('rev2', nargs='?', default='HEAD', help="Revision to compare against.")
help="Revision to compare to rev1 (default is HEAD).") add_parser.add_argument(
'rev2', nargs='?', default='HEAD',
help="Revision to compare to rev1 (default is HEAD).")
rm_parser = sp.add_parser('removed', help=pkg_removed.__doc__) rm_parser = sp.add_parser('removed', help=pkg_removed.__doc__)
rm_parser.add_argument('rev1', nargs='?', default='HEAD^', rm_parser.add_argument(
help="Revision to compare against.") 'rev1', nargs='?', default='HEAD^',
rm_parser.add_argument('rev2', nargs='?', default='HEAD', help="Revision to compare against.")
help="Revision to compare to rev1 (default is HEAD).") rm_parser.add_argument(
'rev2', nargs='?', default='HEAD',
help="Revision to compare to rev1 (default is HEAD).")
def get_git(): def get_git():
@ -88,7 +95,8 @@ def pkg_add(args):
for pkg_name in args.packages: for pkg_name in args.packages:
filename = spack.repo.filename_for_package_name(pkg_name) filename = spack.repo.filename_for_package_name(pkg_name)
if not os.path.isfile(filename): if not os.path.isfile(filename):
tty.die("No such package: %s. Path does not exist:" % pkg_name, filename) tty.die("No such package: %s. Path does not exist:" %
pkg_name, filename)
git = get_git() git = get_git()
git('-C', spack.packages_path, 'add', filename) git('-C', spack.packages_path, 'add', filename)
@ -112,7 +120,8 @@ def pkg_diff(args):
if u1: if u1:
print "%s:" % args.rev1 print "%s:" % args.rev1
colify(sorted(u1), indent=4) colify(sorted(u1), indent=4)
if u1: print if u1:
print
if u2: if u2:
print "%s:" % args.rev2 print "%s:" % args.rev2
@ -122,19 +131,21 @@ def pkg_diff(args):
def pkg_removed(args): def pkg_removed(args):
"""Show packages removed since a commit.""" """Show packages removed since a commit."""
u1, u2 = diff_packages(args.rev1, args.rev2) u1, u2 = diff_packages(args.rev1, args.rev2)
if u1: colify(sorted(u1)) if u1:
colify(sorted(u1))
def pkg_added(args): def pkg_added(args):
"""Show packages added since a commit.""" """Show packages added since a commit."""
u1, u2 = diff_packages(args.rev1, args.rev2) u1, u2 = diff_packages(args.rev1, args.rev2)
if u2: colify(sorted(u2)) if u2:
colify(sorted(u2))
def pkg(parser, args): def pkg(parser, args):
action = { 'add' : pkg_add, action = {'add': pkg_add,
'diff' : pkg_diff, 'diff': pkg_diff,
'list' : pkg_list, 'list': pkg_list,
'removed' : pkg_removed, 'removed': pkg_removed,
'added' : pkg_added } 'added': pkg_added}
action[args.pkg_command](args) action[args.pkg_command](args)

View file

@ -22,7 +22,6 @@
# License along with this program; if not, write to the Free Software # License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import os
import argparse import argparse
from llnl.util.tty.colify import colify from llnl.util.tty.colify import colify
@ -30,11 +29,13 @@
import spack import spack
import spack.cmd import spack.cmd
description ="List packages that provide a particular virtual package" description = "List packages that provide a particular virtual package"
def setup_parser(subparser): def setup_parser(subparser):
subparser.add_argument('vpkg_spec', metavar='VPACKAGE_SPEC', nargs=argparse.REMAINDER, subparser.add_argument(
help='Find packages that provide this virtual package') 'vpkg_spec', metavar='VPACKAGE_SPEC', nargs=argparse.REMAINDER,
help='Find packages that provide this virtual package')
def providers(parser, args): def providers(parser, args):

View file

@ -30,18 +30,22 @@
import spack import spack
def setup_parser(subparser): def setup_parser(subparser):
subparser.add_argument( subparser.add_argument(
'-c', dest='python_command', help='Command to execute.') '-c', dest='python_command', help='Command to execute.')
subparser.add_argument( subparser.add_argument(
'python_args', nargs=argparse.REMAINDER, help="File to run plus arguments.") 'python_args', nargs=argparse.REMAINDER,
help="File to run plus arguments.")
description = "Launch an interpreter as spack would launch a command" description = "Launch an interpreter as spack would launch a command"
def python(parser, args): def python(parser, args):
# Fake a main python shell by setting __name__ to __main__. # Fake a main python shell by setting __name__ to __main__.
console = code.InteractiveConsole({'__name__' : '__main__', console = code.InteractiveConsole({'__name__': '__main__',
'spack' : spack}) 'spack': spack})
if "PYTHONSTARTUP" in os.environ: if "PYTHONSTARTUP" in os.environ:
startup_file = os.environ["PYTHONSTARTUP"] startup_file = os.environ["PYTHONSTARTUP"]

View file

@ -22,10 +22,10 @@
# License along with this program; if not, write to the Free Software # License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import argparse
import spack import spack
description = "Rebuild Spack's package database." description = "Rebuild Spack's package database."
def reindex(parser, args): def reindex(parser, args):
spack.installed_db.reindex(spack.install_layout) spack.installed_db.reindex(spack.install_layout)

View file

@ -23,20 +23,16 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import os import os
import re
import shutil
import argparse
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.filesystem import join_path, mkdirp
import spack.spec import spack.spec
import spack.config import spack.config
from spack.util.environment import get_path
from spack.repository import * from spack.repository import *
description = "Manage package source repositories." description = "Manage package source repositories."
def setup_parser(subparser): def setup_parser(subparser):
sp = subparser.add_subparsers(metavar='SUBCOMMAND', dest='repo_command') sp = subparser.add_subparsers(metavar='SUBCOMMAND', dest='repo_command')
scopes = spack.config.config_scopes scopes = spack.config.config_scopes
@ -57,13 +53,15 @@ def setup_parser(subparser):
# Add # Add
add_parser = sp.add_parser('add', help=repo_add.__doc__) add_parser = sp.add_parser('add', help=repo_add.__doc__)
add_parser.add_argument('path', help="Path to a Spack package repository directory.") add_parser.add_argument(
'path', help="Path to a Spack package repository directory.")
add_parser.add_argument( add_parser.add_argument(
'--scope', choices=scopes, default=spack.cmd.default_modify_scope, '--scope', choices=scopes, default=spack.cmd.default_modify_scope,
help="Configuration scope to modify.") help="Configuration scope to modify.")
# Remove # Remove
remove_parser = sp.add_parser('remove', help=repo_remove.__doc__, aliases=['rm']) remove_parser = sp.add_parser(
'remove', help=repo_remove.__doc__, aliases=['rm'])
remove_parser.add_argument( remove_parser.add_argument(
'path_or_namespace', 'path_or_namespace',
help="Path or namespace of a Spack package repository.") help="Path or namespace of a Spack package repository.")
@ -100,7 +98,8 @@ def repo_add(args):
# If that succeeds, finally add it to the configuration. # If that succeeds, finally add it to the configuration.
repos = spack.config.get_config('repos', args.scope) repos = spack.config.get_config('repos', args.scope)
if not repos: repos = [] if not repos:
repos = []
if repo.root in repos or path in repos: if repo.root in repos or path in repos:
tty.die("Repository is already registered with Spack: %s" % path) tty.die("Repository is already registered with Spack: %s" % path)
@ -135,7 +134,7 @@ def repo_remove(args):
tty.msg("Removed repository %s with namespace '%s'." tty.msg("Removed repository %s with namespace '%s'."
% (repo.root, repo.namespace)) % (repo.root, repo.namespace))
return return
except RepoError as e: except RepoError:
continue continue
tty.die("No repository with path or namespace: %s" tty.die("No repository with path or namespace: %s"
@ -149,7 +148,7 @@ def repo_list(args):
for r in roots: for r in roots:
try: try:
repos.append(Repo(r)) repos.append(Repo(r))
except RepoError as e: except RepoError:
continue continue
msg = "%d package repositor" % len(repos) msg = "%d package repositor" % len(repos)
@ -166,9 +165,9 @@ def repo_list(args):
def repo(parser, args): def repo(parser, args):
action = { 'create' : repo_create, action = {'create': repo_create,
'list' : repo_list, 'list': repo_list,
'add' : repo_add, 'add': repo_add,
'remove' : repo_remove, 'remove': repo_remove,
'rm' : repo_remove} 'rm': repo_remove}
action[args.repo_command](args) action[args.repo_command](args)

View file

@ -31,6 +31,7 @@
description = "Revert checked out package source code." description = "Revert checked out package source code."
def setup_parser(subparser): def setup_parser(subparser):
subparser.add_argument('packages', nargs=argparse.REMAINDER, subparser.add_argument('packages', nargs=argparse.REMAINDER,
help="specs of packages to restage") help="specs of packages to restage")

View file

@ -35,6 +35,7 @@
description = "Create a configuration script and module, but don't build." description = "Create a configuration script and module, but don't build."
def setup_parser(subparser): def setup_parser(subparser):
subparser.add_argument( subparser.add_argument(
'-i', '--ignore-dependencies', action='store_true', dest='ignore_deps', '-i', '--ignore-dependencies', action='store_true', dest='ignore_deps',
@ -70,7 +71,9 @@ def setup(self, args):
return return
if not spec.versions.concrete: if not spec.versions.concrete:
tty.die("spack setup spec must have a single, concrete version. Did you forget a package version number?") tty.die(
"spack setup spec must have a single, concrete version. "
"Did you forget a package version number?")
spec.concretize() spec.concretize()
package = spack.repo.get(spec) package = spack.repo.get(spec)
@ -84,8 +87,8 @@ def setup(self, args):
spack.do_checksum = False spack.do_checksum = False
package.do_install( package.do_install(
keep_prefix=True, # Don't remove install directory, even if you think you should keep_prefix=True, # Don't remove install directory
ignore_deps=args.ignore_deps, ignore_deps=args.ignore_deps,
verbose=args.verbose, verbose=args.verbose,
keep_stage=True, # don't remove source dir for SETUP. keep_stage=True, # don't remove source dir for SETUP.
install_phases = set(['setup', 'provenance'])) install_phases=set(['setup', 'provenance']))

View file

@ -25,23 +25,22 @@
import argparse import argparse
import spack.cmd import spack.cmd
import llnl.util.tty as tty
import spack import spack
import spack.url as url
description = "print out abstract and concrete versions of a spec." description = "print out abstract and concrete versions of a spec."
def setup_parser(subparser): def setup_parser(subparser):
subparser.add_argument('-i', '--ids', action='store_true', subparser.add_argument('-i', '--ids', action='store_true',
help="show numerical ids for dependencies.") help="show numerical ids for dependencies.")
subparser.add_argument('specs', nargs=argparse.REMAINDER, help="specs of packages") subparser.add_argument(
'specs', nargs=argparse.REMAINDER, help="specs of packages")
def spec(parser, args): def spec(parser, args):
kwargs = { 'ids' : args.ids, kwargs = {'ids': args.ids,
'indent' : 2, 'indent': 2,
'color' : True } 'color': True}
for spec in spack.cmd.parse_specs(args.specs): for spec in spack.cmd.parse_specs(args.specs):
print "Input spec" print "Input spec"

View file

@ -22,14 +22,14 @@
# License along with this program; if not, write to the Free Software # License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import os
import argparse import argparse
import llnl.util.tty as tty import llnl.util.tty as tty
import spack import spack
import spack.cmd import spack.cmd
description="Expand downloaded archive in preparation for install" description = "Expand downloaded archive in preparation for install"
def setup_parser(subparser): def setup_parser(subparser):
subparser.add_argument( subparser.add_argument(

View file

@ -36,25 +36,25 @@
from spack.build_environment import InstallError from spack.build_environment import InstallError
from spack.fetch_strategy import FetchError from spack.fetch_strategy import FetchError
description = "Run package installation as a unit test, output formatted results." description = "Run package install as a unit test, output formatted results."
def setup_parser(subparser): def setup_parser(subparser):
subparser.add_argument('-j', subparser.add_argument(
'--jobs', '-j', '--jobs', action='store', type=int,
action='store', help="Explicitly set number of make jobs. Default is #cpus.")
type=int,
help="Explicitly set number of make jobs. Default is #cpus.")
subparser.add_argument('-n', subparser.add_argument(
'--no-checksum', '-n', '--no-checksum', action='store_true', dest='no_checksum',
action='store_true', help="Do not check packages against checksum")
dest='no_checksum',
help="Do not check packages against checksum")
subparser.add_argument('-o', '--output', action='store', help="test output goes in this file") subparser.add_argument(
'-o', '--output', action='store',
help="test output goes in this file")
subparser.add_argument('package', nargs=argparse.REMAINDER, help="spec of package to install") subparser.add_argument(
'package', nargs=argparse.REMAINDER,
help="spec of package to install")
class TestResult(object): class TestResult(object):
@ -65,6 +65,7 @@ class TestResult(object):
class TestSuite(object): class TestSuite(object):
def __init__(self, filename): def __init__(self, filename):
self.filename = filename self.filename = filename
self.root = ET.Element('testsuite') self.root = ET.Element('testsuite')
@ -75,14 +76,17 @@ def __enter__(self):
def append(self, item): def append(self, item):
if not isinstance(item, TestCase): if not isinstance(item, TestCase):
raise TypeError('only TestCase instances may be appended to a TestSuite instance') raise TypeError(
'only TestCase instances may be appended to TestSuite')
self.tests.append(item) # Append the item to the list of tests self.tests.append(item) # Append the item to the list of tests
def __exit__(self, exc_type, exc_val, exc_tb): def __exit__(self, exc_type, exc_val, exc_tb):
# Prepare the header for the entire test suite # Prepare the header for the entire test suite
number_of_errors = sum(x.result_type == TestResult.ERRORED for x in self.tests) number_of_errors = sum(
x.result_type == TestResult.ERRORED for x in self.tests)
self.root.set('errors', str(number_of_errors)) self.root.set('errors', str(number_of_errors))
number_of_failures = sum(x.result_type == TestResult.FAILED for x in self.tests) number_of_failures = sum(
x.result_type == TestResult.FAILED for x in self.tests)
self.root.set('failures', str(number_of_failures)) self.root.set('failures', str(number_of_failures))
self.root.set('tests', str(len(self.tests))) self.root.set('tests', str(len(self.tests)))
@ -112,7 +116,8 @@ def __init__(self, classname, name, time=None):
self.element.set('time', str(time)) self.element.set('time', str(time))
self.result_type = None self.result_type = None
def set_result(self, result_type, message=None, error_type=None, text=None): def set_result(self, result_type,
message=None, error_type=None, text=None):
self.result_type = result_type self.result_type = result_type
result = TestCase.results[self.result_type] result = TestCase.results[self.result_type]
if result is not None and result is not TestResult.PASSED: if result is not None and result is not TestResult.PASSED:
@ -155,13 +160,19 @@ def install_single_spec(spec, number_of_jobs):
# If it is already installed, skip the test # If it is already installed, skip the test
if spack.repo.get(spec).installed: if spack.repo.get(spec).installed:
testcase = TestCase(package.name, package.spec.short_spec, time=0.0) testcase = TestCase(package.name, package.spec.short_spec, time=0.0)
testcase.set_result(TestResult.SKIPPED, message='Skipped [already installed]', error_type='already_installed') testcase.set_result(
TestResult.SKIPPED,
message='Skipped [already installed]',
error_type='already_installed')
return testcase return testcase
# If it relies on dependencies that did not install, skip # If it relies on dependencies that did not install, skip
if failed_dependencies(spec): if failed_dependencies(spec):
testcase = TestCase(package.name, package.spec.short_spec, time=0.0) testcase = TestCase(package.name, package.spec.short_spec, time=0.0)
testcase.set_result(TestResult.SKIPPED, message='Skipped [failed dependencies]', error_type='dep_failed') testcase.set_result(
TestResult.SKIPPED,
message='Skipped [failed dependencies]',
error_type='dep_failed')
return testcase return testcase
# Otherwise try to install the spec # Otherwise try to install the spec
@ -177,26 +188,30 @@ def install_single_spec(spec, number_of_jobs):
testcase = TestCase(package.name, package.spec.short_spec, duration) testcase = TestCase(package.name, package.spec.short_spec, duration)
testcase.set_result(TestResult.PASSED) testcase.set_result(TestResult.PASSED)
except InstallError: except InstallError:
# An InstallError is considered a failure (the recipe didn't work correctly) # An InstallError is considered a failure (the recipe didn't work
# correctly)
duration = time.time() - start_time duration = time.time() - start_time
# Try to get the log # Try to get the log
lines = fetch_log(package.build_log_path) lines = fetch_log(package.build_log_path)
text = '\n'.join(lines) text = '\n'.join(lines)
testcase = TestCase(package.name, package.spec.short_spec, duration) testcase = TestCase(package.name, package.spec.short_spec, duration)
testcase.set_result(TestResult.FAILED, message='Installation failure', text=text) testcase.set_result(TestResult.FAILED,
message='Installation failure', text=text)
except FetchError: except FetchError:
# A FetchError is considered an error (we didn't even start building) # A FetchError is considered an error (we didn't even start building)
duration = time.time() - start_time duration = time.time() - start_time
testcase = TestCase(package.name, package.spec.short_spec, duration) testcase = TestCase(package.name, package.spec.short_spec, duration)
testcase.set_result(TestResult.ERRORED, message='Unable to fetch package') testcase.set_result(TestResult.ERRORED,
message='Unable to fetch package')
return testcase return testcase
def get_filename(args, top_spec): def get_filename(args, top_spec):
if not args.output: if not args.output:
fname = 'test-{x.name}-{x.version}-{hash}.xml'.format(x=top_spec, hash=top_spec.dag_hash()) fname = 'test-{x.name}-{x.version}-{hash}.xml'.format(
x=top_spec, hash=top_spec.dag_hash())
output_directory = join_path(os.getcwd(), 'test-output') output_directory = join_path(os.getcwd(), 'test-output')
if not os.path.exists(output_directory): if not os.path.exists(output_directory):
os.mkdir(output_directory) os.mkdir(output_directory)

View file

@ -52,6 +52,7 @@ def setup_parser(subparser):
class MockCache(object): class MockCache(object):
def store(self, copyCmd, relativeDst): def store(self, copyCmd, relativeDst):
pass pass
@ -60,6 +61,7 @@ def fetcher(self, targetPath, digest):
class MockCacheFetcher(object): class MockCacheFetcher(object):
def set_stage(self, stage): def set_stage(self, stage):
pass pass

View file

@ -50,25 +50,27 @@ def setup_parser(subparser):
subparser.add_argument( subparser.add_argument(
'-f', '--force', action='store_true', dest='force', '-f', '--force', action='store_true', dest='force',
help="Remove regardless of whether other packages depend on this one.") help="Remove regardless of whether other packages depend on this one.")
subparser.add_argument( subparser.add_argument(
'-a', '--all', action='store_true', dest='all', '-a', '--all', action='store_true', dest='all',
help="USE CAREFULLY. Remove ALL installed packages that match each " + help="USE CAREFULLY. Remove ALL installed packages that match each "
"supplied spec. i.e., if you say uninstall libelf, ALL versions of " + # NOQA: ignore=E501 "supplied spec. i.e., if you say uninstall libelf, ALL versions "
"libelf are uninstalled. This is both useful and dangerous, like rm -r.") # NOQA: ignore=E501 "of libelf are uninstalled. This is both useful and dangerous, "
"like rm -r.")
subparser.add_argument( subparser.add_argument(
'-d', '--dependents', action='store_true', dest='dependents', '-d', '--dependents', action='store_true', dest='dependents',
help='Also uninstall any packages that depend on the ones given via command line.' # NOQA: ignore=E501 help='Also uninstall any packages that depend on the ones given '
) 'via command line.')
subparser.add_argument( subparser.add_argument(
'-y', '--yes-to-all', action='store_true', dest='yes_to_all', '-y', '--yes-to-all', action='store_true', dest='yes_to_all',
help='Assume "yes" is the answer to every confirmation asked to the user.' # NOQA: ignore=E501 help='Assume "yes" is the answer to every confirmation requested')
)
subparser.add_argument( subparser.add_argument(
'packages', 'packages',
nargs=argparse.REMAINDER, nargs=argparse.REMAINDER,
help="specs of packages to uninstall" help="specs of packages to uninstall")
)
def concretize_specs(specs, allow_multiple_matches=False, force=False): def concretize_specs(specs, allow_multiple_matches=False, force=False):

View file

@ -25,13 +25,15 @@
import argparse import argparse
import spack.modules import spack.modules
description ="Remove package from environment using module." description = "Remove package from environment using module."
def setup_parser(subparser): def setup_parser(subparser):
"""Parser is only constructed so that this prints a nice help """Parser is only constructed so that this prints a nice help
message with -h. """ message with -h. """
subparser.add_argument( subparser.add_argument(
'spec', nargs=argparse.REMAINDER, help='Spec of package to unload with modules.') 'spec', nargs=argparse.REMAINDER,
help='Spec of package to unload with modules.')
def unload(parser, args): def unload(parser, args):

View file

@ -25,13 +25,15 @@
import argparse import argparse
import spack.modules import spack.modules
description ="Remove package from environment using dotkit." description = "Remove package from environment using dotkit."
def setup_parser(subparser): def setup_parser(subparser):
"""Parser is only constructed so that this prints a nice help """Parser is only constructed so that this prints a nice help
message with -h. """ message with -h. """
subparser.add_argument( subparser.add_argument(
'spec', nargs=argparse.REMAINDER, help='Spec of package to unuse with dotkit.') 'spec', nargs=argparse.REMAINDER,
help='Spec of package to unuse with dotkit.')
def unuse(parser, args): def unuse(parser, args):

View file

@ -22,28 +22,28 @@
# License along with this program; if not, write to the Free Software # License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import sys
import llnl.util.tty as tty import llnl.util.tty as tty
import spack import spack
import spack.url import spack.url
from spack.util.web import find_versions_of_archive from spack.util.web import find_versions_of_archive
description = "Show parsing of a URL, optionally spider web for other versions." description = "Show parsing of a URL, optionally spider web for versions."
def setup_parser(subparser): def setup_parser(subparser):
subparser.add_argument('url', help="url of a package archive") subparser.add_argument('url', help="url of a package archive")
subparser.add_argument( subparser.add_argument(
'-s', '--spider', action='store_true', help="Spider the source page for versions.") '-s', '--spider', action='store_true',
help="Spider the source page for versions.")
def print_name_and_version(url): def print_name_and_version(url):
name, ns, nl, ntup, ver, vs, vl, vtup = spack.url.substitution_offsets(url) name, ns, nl, ntup, ver, vs, vl, vtup = spack.url.substitution_offsets(url)
underlines = [" "] * max(ns+nl, vs+vl) underlines = [" "] * max(ns + nl, vs + vl)
for i in range(ns, ns+nl): for i in range(ns, ns + nl):
underlines[i] = '-' underlines[i] = '-'
for i in range(vs, vs+vl): for i in range(vs, vs + vl):
underlines[i] = '~' underlines[i] = '~'
print " %s" % url print " %s" % url

View file

@ -22,12 +22,12 @@
# License along with this program; if not, write to the Free Software # License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import sys
import spack import spack
import spack.url import spack.url
description = "Inspect urls used by packages in spack." description = "Inspect urls used by packages in spack."
def setup_parser(subparser): def setup_parser(subparser):
subparser.add_argument( subparser.add_argument(
'-c', '--color', action='store_true', '-c', '--color', action='store_true',
@ -53,6 +53,7 @@ def urls(parser, args):
for url in sorted(urls): for url in sorted(urls):
if args.color or args.extrapolation: if args.color or args.extrapolation:
print spack.url.color_url(url, subs=args.extrapolation, errors=True) print spack.url.color_url(
url, subs=args.extrapolation, errors=True)
else: else:
print url print url

View file

@ -25,13 +25,15 @@
import argparse import argparse
import spack.modules import spack.modules
description ="Add package to environment using dotkit." description = "Add package to environment using dotkit."
def setup_parser(subparser): def setup_parser(subparser):
"""Parser is only constructed so that this prints a nice help """Parser is only constructed so that this prints a nice help
message with -h. """ message with -h. """
subparser.add_argument( subparser.add_argument(
'spec', nargs=argparse.REMAINDER, help='Spec of package to use with dotkit.') 'spec', nargs=argparse.REMAINDER,
help='Spec of package to use with dotkit.')
def use(parser, args): def use(parser, args):

View file

@ -22,15 +22,16 @@
# License along with this program; if not, write to the Free Software # License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import os
from llnl.util.tty.colify import colify from llnl.util.tty.colify import colify
import llnl.util.tty as tty import llnl.util.tty as tty
import spack import spack
description ="List available versions of a package" description = "List available versions of a package"
def setup_parser(subparser): def setup_parser(subparser):
subparser.add_argument('package', metavar='PACKAGE', help='Package to list versions for') subparser.add_argument('package', metavar='PACKAGE',
help='Package to list versions for')
def versions(parser, args): def versions(parser, args):

View file

@ -25,10 +25,8 @@
import os import os
import re import re
import itertools import itertools
from datetime import datetime
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.lang import memoized
from llnl.util.filesystem import join_path from llnl.util.filesystem import join_path
import spack.error import spack.error
@ -37,10 +35,10 @@
from spack.util.multiproc import parmap from spack.util.multiproc import parmap
from spack.util.executable import * from spack.util.executable import *
from spack.util.environment import get_path from spack.util.environment import get_path
from spack.version import Version
__all__ = ['Compiler', 'get_compiler_version'] __all__ = ['Compiler', 'get_compiler_version']
def _verify_executables(*paths): def _verify_executables(*paths):
for path in paths: for path in paths:
if not os.path.isfile(path) and os.access(path, os.X_OK): if not os.path.isfile(path) and os.access(path, os.X_OK):
@ -49,8 +47,9 @@ def _verify_executables(*paths):
_version_cache = {} _version_cache = {}
def get_compiler_version(compiler_path, version_arg, regex='(.*)'): def get_compiler_version(compiler_path, version_arg, regex='(.*)'):
if not compiler_path in _version_cache: if compiler_path not in _version_cache:
compiler = Executable(compiler_path) compiler = Executable(compiler_path)
output = compiler(version_arg, output=str, error=str) output = compiler(version_arg, output=str, error=str)
@ -113,7 +112,7 @@ def fc_rpath_arg(self):
# Name of module used to switch versions of this compiler # Name of module used to switch versions of this compiler
PrgEnv_compiler = None PrgEnv_compiler = None
def __init__(self, cspec, operating_system, def __init__(self, cspec, operating_system,
paths, modules=[], alias=None, **kwargs): paths, modules=[], alias=None, **kwargs):
def check(exe): def check(exe):
if exe is None: if exe is None:
@ -130,11 +129,6 @@ def check(exe):
else: else:
self.fc = check(paths[3]) self.fc = check(paths[3])
#self.cc = check(cc)
#self.cxx = check(cxx)
#self.f77 = check(f77)
#self.fc = check(fc)
# Unfortunately have to make sure these params are accepted # Unfortunately have to make sure these params are accepted
# in the same order they are returned by sorted(flags) # in the same order they are returned by sorted(flags)
# in compilers/__init__.py # in compilers/__init__.py
@ -158,31 +152,30 @@ def version(self):
@property @property
def openmp_flag(self): def openmp_flag(self):
# If it is not overridden, assume it is not supported and warn the user # If it is not overridden, assume it is not supported and warn the user
tty.die("The compiler you have chosen does not currently support OpenMP.", tty.die(
"If you think it should, please edit the compiler subclass and", "The compiler you have chosen does not currently support OpenMP.",
"submit a pull request or issue.") "If you think it should, please edit the compiler subclass and",
"submit a pull request or issue.")
# This property should be overridden in the compiler subclass if # This property should be overridden in the compiler subclass if
# C++11 is supported by that compiler # C++11 is supported by that compiler
@property @property
def cxx11_flag(self): def cxx11_flag(self):
# If it is not overridden, assume it is not supported and warn the user # If it is not overridden, assume it is not supported and warn the user
tty.die("The compiler you have chosen does not currently support C++11.", tty.die(
"If you think it should, please edit the compiler subclass and", "The compiler you have chosen does not currently support C++11.",
"submit a pull request or issue.") "If you think it should, please edit the compiler subclass and",
"submit a pull request or issue.")
# This property should be overridden in the compiler subclass if # This property should be overridden in the compiler subclass if
# C++14 is supported by that compiler # C++14 is supported by that compiler
@property @property
def cxx14_flag(self): def cxx14_flag(self):
# If it is not overridden, assume it is not supported and warn the user # If it is not overridden, assume it is not supported and warn the user
tty.die("The compiler you have chosen does not currently support C++14.", tty.die(
"If you think it should, please edit the compiler subclass and", "The compiler you have chosen does not currently support C++14.",
"submit a pull request or issue.") "If you think it should, please edit the compiler subclass and",
"submit a pull request or issue.")
# #
# Compiler classes have methods for querying the version of # Compiler classes have methods for querying the version of
@ -191,7 +184,6 @@ def cxx14_flag(self):
# Compiler *instances* are just data objects, and can only be # Compiler *instances* are just data objects, and can only be
# constructed from an actual set of executables. # constructed from an actual set of executables.
# #
@classmethod @classmethod
def default_version(cls, cc): def default_version(cls, cc):
"""Override just this to override all compiler version functions.""" """Override just this to override all compiler version functions."""
@ -258,16 +250,19 @@ def check(key):
version = detect_version(full_path) version = detect_version(full_path)
return (version, prefix, suffix, full_path) return (version, prefix, suffix, full_path)
except ProcessError, e: except ProcessError, e:
tty.debug("Couldn't get version for compiler %s" % full_path, e) tty.debug(
"Couldn't get version for compiler %s" % full_path, e)
return None return None
except Exception, e: except Exception, e:
# Catching "Exception" here is fine because it just # Catching "Exception" here is fine because it just
# means something went wrong running a candidate executable. # means something went wrong running a candidate executable.
tty.debug("Error while executing candidate compiler %s" % full_path, tty.debug("Error while executing candidate compiler %s"
"%s: %s" %(e.__class__.__name__, e)) % full_path,
"%s: %s" % (e.__class__.__name__, e))
return None return None
successful = [key for key in parmap(check, checks) if key is not None] successful = [k for k in parmap(check, checks) if k is not None]
# The 'successful' list is ordered like the input paths. # The 'successful' list is ordered like the input paths.
# Reverse it here so that the dict creation (last insert wins) # Reverse it here so that the dict creation (last insert wins)
# does not spoil the intented precedence. # does not spoil the intented precedence.
@ -278,20 +273,23 @@ def __repr__(self):
"""Return a string representation of the compiler toolchain.""" """Return a string representation of the compiler toolchain."""
return self.__str__() return self.__str__()
def __str__(self): def __str__(self):
"""Return a string representation of the compiler toolchain.""" """Return a string representation of the compiler toolchain."""
return "%s(%s)" % ( return "%s(%s)" % (
self.name, '\n '.join((str(s) for s in (self.cc, self.cxx, self.f77, self.fc, self.modules, str(self.operating_system))))) self.name, '\n '.join((str(s) for s in (
self.cc, self.cxx, self.f77, self.fc, self.modules,
str(self.operating_system)))))
class CompilerAccessError(spack.error.SpackError): class CompilerAccessError(spack.error.SpackError):
def __init__(self, path): def __init__(self, path):
super(CompilerAccessError, self).__init__( super(CompilerAccessError, self).__init__(
"'%s' is not a valid compiler." % path) "'%s' is not a valid compiler." % path)
class InvalidCompilerError(spack.error.SpackError): class InvalidCompilerError(spack.error.SpackError):
def __init__(self): def __init__(self):
super(InvalidCompilerError, self).__init__( super(InvalidCompilerError, self).__init__(
"Compiler has no executables.") "Compiler has no executables.")

View file

@ -26,15 +26,9 @@
system and configuring Spack to use multiple compilers. system and configuring Spack to use multiple compilers.
""" """
import imp import imp
import os
import platform import platform
import copy
import hashlib
import base64
import yaml
import sys
from llnl.util.lang import memoized, list_modules from llnl.util.lang import list_modules
from llnl.util.filesystem import join_path from llnl.util.filesystem import join_path
import spack import spack
@ -43,11 +37,7 @@
import spack.config import spack.config
import spack.architecture import spack.architecture
from spack.util.multiproc import parmap
from spack.compiler import Compiler
from spack.util.executable import which
from spack.util.naming import mod_to_class from spack.util.naming import mod_to_class
from spack.util.environment import get_path
_imported_compilers_module = 'spack.compilers' _imported_compilers_module = 'spack.compilers'
_path_instance_vars = ['cc', 'cxx', 'f77', 'fc'] _path_instance_vars = ['cc', 'cxx', 'f77', 'fc']
@ -73,7 +63,8 @@ def _to_dict(compiler):
"""Return a dict version of compiler suitable to insert in YAML.""" """Return a dict version of compiler suitable to insert in YAML."""
d = {} d = {}
d['spec'] = str(compiler.spec) d['spec'] = str(compiler.spec)
d['paths'] = dict( (attr, getattr(compiler, attr, None)) for attr in _path_instance_vars ) d['paths'] = dict((attr, getattr(compiler, attr, None))
for attr in _path_instance_vars)
d['operating_system'] = str(compiler.operating_system) d['operating_system'] = str(compiler.operating_system)
d['modules'] = compiler.modules if compiler.modules else [] d['modules'] = compiler.modules if compiler.modules else []
@ -140,15 +131,19 @@ def remove_compiler_from_config(compiler_spec, scope=None):
- compiler_specs: a list of CompilerSpec objects. - compiler_specs: a list of CompilerSpec objects.
- scope: configuration scope to modify. - scope: configuration scope to modify.
""" """
# Need a better way for this
global _cache_config_file
compiler_config = get_compiler_config(scope) compiler_config = get_compiler_config(scope)
config_length = len(compiler_config) config_length = len(compiler_config)
filtered_compiler_config = [comp for comp in compiler_config filtered_compiler_config = [
if spack.spec.CompilerSpec(comp['compiler']['spec']) != compiler_spec] comp for comp in compiler_config
# Need a better way for this if spack.spec.CompilerSpec(comp['compiler']['spec']) != compiler_spec]
global _cache_config_file
_cache_config_file = filtered_compiler_config # Update the cache for changes # Update the cache for changes
if len(filtered_compiler_config) == config_length: # No items removed _cache_config_file = filtered_compiler_config
if len(filtered_compiler_config) == config_length: # No items removed
CompilerSpecInsufficientlySpecificError(compiler_spec) CompilerSpecInsufficientlySpecificError(compiler_spec)
spack.config.update_config('compilers', filtered_compiler_config, scope) spack.config.update_config('compilers', filtered_compiler_config, scope)
@ -158,7 +153,8 @@ def all_compilers_config(scope=None, init_config=True):
available to build with. These are instances of CompilerSpec. available to build with. These are instances of CompilerSpec.
""" """
# Get compilers for this architecture. # Get compilers for this architecture.
global _cache_config_file #Create a cache of the config file so we don't load all the time. # Create a cache of the config file so we don't load all the time.
global _cache_config_file
if not _cache_config_file: if not _cache_config_file:
_cache_config_file = get_compiler_config(scope, init_config) _cache_config_file = get_compiler_config(scope, init_config)
return _cache_config_file return _cache_config_file
@ -236,7 +232,8 @@ def get_compilers(cspec):
continue continue
items = items['compiler'] items = items['compiler']
if not ('paths' in items and all(n in items['paths'] for n in _path_instance_vars)): if not ('paths' in items and
all(n in items['paths'] for n in _path_instance_vars)):
raise InvalidCompilerConfigurationError(cspec) raise InvalidCompilerConfigurationError(cspec)
cls = class_for_compiler_name(cspec.name) cls = class_for_compiler_name(cspec.name)
@ -254,10 +251,10 @@ def get_compilers(cspec):
mods = [] mods = []
if 'operating_system' in items: if 'operating_system' in items:
operating_system = spack.architecture._operating_system_from_dict(items['operating_system'], platform) os = spack.architecture._operating_system_from_dict(
items['operating_system'], platform)
else: else:
operating_system = None os = None
alias = items['alias'] if 'alias' in items else None alias = items['alias'] if 'alias' in items else None
@ -266,7 +263,8 @@ def get_compilers(cspec):
if f in items: if f in items:
flags[f] = items[f] flags[f] = items[f]
compilers.append(cls(cspec, operating_system, compiler_paths, mods, alias, **flags)) compilers.append(
cls(cspec, os, compiler_paths, mods, alias, **flags))
return compilers return compilers
@ -275,7 +273,6 @@ def get_compilers(cspec):
for cspec in matches: for cspec in matches:
compilers.extend(get_compilers(cspec)) compilers.extend(get_compilers(cspec))
return compilers return compilers
# return [get_compilers(cspec) for cspec in matches]
@_auto_compiler_spec @_auto_compiler_spec
@ -285,8 +282,9 @@ def compiler_for_spec(compiler_spec, arch):
operating_system = arch.platform_os operating_system = arch.platform_os
assert(compiler_spec.concrete) assert(compiler_spec.concrete)
compilers = [c for c in compilers_for_spec(compiler_spec, platform=arch.platform) compilers = [
if c.operating_system == operating_system] c for c in compilers_for_spec(compiler_spec, platform=arch.platform)
if c.operating_system == operating_system]
if len(compilers) < 1: if len(compilers) < 1:
raise NoCompilerForSpecError(compiler_spec, operating_system) raise NoCompilerForSpecError(compiler_spec, operating_system)
if len(compilers) > 1: if len(compilers) > 1:
@ -321,11 +319,13 @@ def all_os_classes():
return classes return classes
def all_compiler_types(): def all_compiler_types():
return [class_for_compiler_name(c) for c in supported_compilers()] return [class_for_compiler_name(c) for c in supported_compilers()]
class InvalidCompilerConfigurationError(spack.error.SpackError): class InvalidCompilerConfigurationError(spack.error.SpackError):
def __init__(self, compiler_spec): def __init__(self, compiler_spec):
super(InvalidCompilerConfigurationError, self).__init__( super(InvalidCompilerConfigurationError, self).__init__(
"Invalid configuration for [compiler \"%s\"]: " % compiler_spec, "Invalid configuration for [compiler \"%s\"]: " % compiler_spec,
@ -335,14 +335,18 @@ def __init__(self, compiler_spec):
class NoCompilersError(spack.error.SpackError): class NoCompilersError(spack.error.SpackError):
def __init__(self): def __init__(self):
super(NoCompilersError, self).__init__("Spack could not find any compilers!") super(NoCompilersError, self).__init__(
"Spack could not find any compilers!")
class NoCompilerForSpecError(spack.error.SpackError): class NoCompilerForSpecError(spack.error.SpackError):
def __init__(self, compiler_spec, target): def __init__(self, compiler_spec, target):
super(NoCompilerForSpecError, self).__init__("No compilers for operating system %s satisfy spec %s" % ( super(NoCompilerForSpecError, self).__init__(
target, compiler_spec)) "No compilers for operating system %s satisfy spec %s"
% (target, compiler_spec))
class CompilerSpecInsufficientlySpecificError(spack.error.SpackError): class CompilerSpecInsufficientlySpecificError(spack.error.SpackError):
def __init__(self, compiler_spec): def __init__(self, compiler_spec):
super(CompilerSpecInsufficientlySpecificError, self).__init__("Multiple compilers satisfy spec %s", super(CompilerSpecInsufficientlySpecificError, self).__init__(
compiler_spec) "Multiple compilers satisfy spec %s" % compiler_spec)

View file

@ -29,6 +29,7 @@
import llnl.util.tty as tty import llnl.util.tty as tty
from spack.version import ver from spack.version import ver
class Clang(Compiler): class Clang(Compiler):
# Subclasses use possible names of C compiler # Subclasses use possible names of C compiler
cc_names = ['clang'] cc_names = ['clang']
@ -43,11 +44,12 @@ class Clang(Compiler):
fc_names = [] fc_names = []
# Named wrapper links within spack.build_env_path # Named wrapper links within spack.build_env_path
link_paths = { 'cc' : 'clang/clang', link_paths = {'cc': 'clang/clang',
'cxx' : 'clang/clang++', 'cxx': 'clang/clang++',
# Use default wrappers for fortran, in case provided in compilers.yaml # Use default wrappers for fortran, in case provided in
'f77' : 'f77', # compilers.yaml
'fc' : 'f90' } 'f77': 'f77',
'fc': 'f90'}
@property @property
def is_apple(self): def is_apple(self):

View file

@ -1,34 +1,33 @@
##############################################################################} ##############################################################################
# Copyright (c) 2013, Lawrence Livermore National Security, LLC. # Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
# Produced at the Lawrence Livermore National Laboratory. # Produced at the Lawrence Livermore National Laboratory.
# #
# This file is part of Spack. # This file is part of Spack.
# Written by Todd Gamblin, tgamblin@llnl.gov, All rights reserved. # Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
# LLNL-CODE-647188 # LLNL-CODE-647188
# #
# For details, see https://scalability-llnl.github.io/spack # For details, see https://github.com/llnl/spack
# Please also see the LICENSE file for our notice and the LGPL. # Please also see the LICENSE file for our notice and the LGPL.
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License (as published by # it under the terms of the GNU Lesser General Public License (as
# the Free Software Foundation) version 2.1 dated February 1999. # published by the Free Software Foundation) version 2.1, February 1999.
# #
# This program is distributed in the hope that it will be useful, but # This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF # WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
# conditions of the GNU General Public License for more details. # conditions of the GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public
# along with this program; if not, write to the Free Software Foundation, # License along with this program; if not, write to the Free Software
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import llnl.util.tty as tty
#from spack.build_environment import load_module
from spack.compiler import * from spack.compiler import *
#from spack.version import ver
class Craype(Compiler): class Craype(Compiler):
"""Cray programming environment compiler."""
# Subclasses use possible names of C compiler # Subclasses use possible names of C compiler
cc_names = ['cc'] cc_names = ['cc']
@ -47,12 +46,11 @@ class Craype(Compiler):
PrgEnv = 'PrgEnv-cray' PrgEnv = 'PrgEnv-cray'
PrgEnv_compiler = 'craype' PrgEnv_compiler = 'craype'
link_paths = { 'cc' : 'cc', link_paths = {'cc': 'cc',
'cxx' : 'c++', 'cxx': 'c++',
'f77' : 'f77', 'f77': 'f77',
'fc' : 'fc'} 'fc': 'fc'}
@classmethod @classmethod
def default_version(cls, comp): def default_version(cls, comp):
return get_compiler_version(comp, r'([Vv]ersion).*(\d+(\.\d+)+)') return get_compiler_version(comp, r'([Vv]ersion).*(\d+(\.\d+)+)')

View file

@ -26,6 +26,7 @@
from spack.compiler import * from spack.compiler import *
from spack.version import ver from spack.version import ver
class Gcc(Compiler): class Gcc(Compiler):
# Subclasses use possible names of C compiler # Subclasses use possible names of C compiler
cc_names = ['gcc'] cc_names = ['gcc']
@ -44,10 +45,10 @@ class Gcc(Compiler):
suffixes = [r'-mp-\d\.\d', r'-\d\.\d', r'-\d'] suffixes = [r'-mp-\d\.\d', r'-\d\.\d', r'-\d']
# Named wrapper links within spack.build_env_path # Named wrapper links within spack.build_env_path
link_paths = {'cc' : 'gcc/gcc', link_paths = {'cc': 'gcc/gcc',
'cxx' : 'gcc/g++', 'cxx': 'gcc/g++',
'f77' : 'gcc/gfortran', 'f77': 'gcc/gfortran',
'fc' : 'gcc/gfortran' } 'fc': 'gcc/gfortran'}
PrgEnv = 'PrgEnv-gnu' PrgEnv = 'PrgEnv-gnu'
PrgEnv_compiler = 'gcc' PrgEnv_compiler = 'gcc'
@ -79,7 +80,6 @@ def fc_version(cls, fc):
# older gfortran versions don't have simple dumpversion output. # older gfortran versions don't have simple dumpversion output.
r'(?:GNU Fortran \(GCC\))?(\d+\.\d+(?:\.\d+)?)') r'(?:GNU Fortran \(GCC\))?(\d+\.\d+(?:\.\d+)?)')
@classmethod @classmethod
def f77_version(cls, f77): def f77_version(cls, f77):
return cls.fc_version(f77) return cls.fc_version(f77)

View file

@ -26,6 +26,7 @@
import llnl.util.tty as tty import llnl.util.tty as tty
from spack.version import ver from spack.version import ver
class Intel(Compiler): class Intel(Compiler):
# Subclasses use possible names of C compiler # Subclasses use possible names of C compiler
cc_names = ['icc'] cc_names = ['icc']
@ -40,10 +41,10 @@ class Intel(Compiler):
fc_names = ['ifort'] fc_names = ['ifort']
# Named wrapper links within spack.build_env_path # Named wrapper links within spack.build_env_path
link_paths = { 'cc' : 'intel/icc', link_paths = {'cc': 'intel/icc',
'cxx' : 'intel/icpc', 'cxx': 'intel/icpc',
'f77' : 'intel/ifort', 'f77': 'intel/ifort',
'fc' : 'intel/ifort' } 'fc': 'intel/ifort'}
PrgEnv = 'PrgEnv-intel' PrgEnv = 'PrgEnv-intel'
PrgEnv_compiler = 'intel' PrgEnv_compiler = 'intel'
@ -64,7 +65,6 @@ def cxx11_flag(self):
else: else:
return "-std=c++11" return "-std=c++11"
@classmethod @classmethod
def default_version(cls, comp): def default_version(cls, comp):
"""The '--version' option seems to be the most consistent one """The '--version' option seems to be the most consistent one

View file

@ -23,7 +23,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
from spack.compiler import * from spack.compiler import *
import llnl.util.tty as tty
class Nag(Compiler): class Nag(Compiler):
# Subclasses use possible names of C compiler # Subclasses use possible names of C compiler
@ -39,11 +39,12 @@ class Nag(Compiler):
fc_names = ['nagfor'] fc_names = ['nagfor']
# Named wrapper links within spack.build_env_path # Named wrapper links within spack.build_env_path
link_paths = { # Use default wrappers for C and C++, in case provided in compilers.yaml # Use default wrappers for C and C++, in case provided in compilers.yaml
'cc' : 'cc', link_paths = {
'cxx' : 'c++', 'cc': 'cc',
'f77' : 'nag/nagfor', 'cxx': 'c++',
'fc' : 'nag/nagfor' } 'f77': 'nag/nagfor',
'fc': 'nag/nagfor'}
@property @property
def openmp_flag(self): def openmp_flag(self):
@ -71,9 +72,8 @@ def default_version(self, comp):
"""The '-V' option works for nag compilers. """The '-V' option works for nag compilers.
Output looks like this:: Output looks like this::
NAG Fortran Compiler Release 6.0(Hibiya) Build 1037 NAG Fortran Compiler Release 6.0(Hibiya) Build 1037
Product NPL6A60NA for x86-64 Linux Product NPL6A60NA for x86-64 Linux
Copyright 1990-2015 The Numerical Algorithms Group Ltd., Oxford, U.K.
""" """
return get_compiler_version( return get_compiler_version(
comp, '-V', r'NAG Fortran Compiler Release ([0-9.]+)') comp, '-V', r'NAG Fortran Compiler Release ([0-9.]+)')

View file

@ -23,7 +23,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
from spack.compiler import * from spack.compiler import *
import llnl.util.tty as tty
class Pgi(Compiler): class Pgi(Compiler):
# Subclasses use possible names of C compiler # Subclasses use possible names of C compiler
@ -39,17 +39,14 @@ class Pgi(Compiler):
fc_names = ['pgfortran', 'pgf95', 'pgf90'] fc_names = ['pgfortran', 'pgf95', 'pgf90']
# Named wrapper links within spack.build_env_path # Named wrapper links within spack.build_env_path
link_paths = { 'cc' : 'pgi/pgcc', link_paths = {'cc': 'pgi/pgcc',
'cxx' : 'pgi/pgc++', 'cxx': 'pgi/pgc++',
'f77' : 'pgi/pgfortran', 'f77': 'pgi/pgfortran',
'fc' : 'pgi/pgfortran' } 'fc': 'pgi/pgfortran'}
PrgEnv = 'PrgEnv-pgi' PrgEnv = 'PrgEnv-pgi'
PrgEnv_compiler = 'pgi' PrgEnv_compiler = 'pgi'
@property @property
def openmp_flag(self): def openmp_flag(self):
return "-mp" return "-mp"

View file

@ -26,24 +26,26 @@
import llnl.util.tty as tty import llnl.util.tty as tty
from spack.version import ver from spack.version import ver
class Xl(Compiler): class Xl(Compiler):
# Subclasses use possible names of C compiler # Subclasses use possible names of C compiler
cc_names = ['xlc','xlc_r'] cc_names = ['xlc', 'xlc_r']
# Subclasses use possible names of C++ compiler # Subclasses use possible names of C++ compiler
cxx_names = ['xlC','xlC_r','xlc++','xlc++_r'] cxx_names = ['xlC', 'xlC_r', 'xlc++', 'xlc++_r']
# Subclasses use possible names of Fortran 77 compiler # Subclasses use possible names of Fortran 77 compiler
f77_names = ['xlf','xlf_r'] f77_names = ['xlf', 'xlf_r']
# Subclasses use possible names of Fortran 90 compiler # Subclasses use possible names of Fortran 90 compiler
fc_names = ['xlf90','xlf90_r','xlf95','xlf95_r','xlf2003','xlf2003_r','xlf2008','xlf2008_r'] fc_names = ['xlf90', 'xlf90_r', 'xlf95', 'xlf95_r',
'xlf2003', 'xlf2003_r', 'xlf2008', 'xlf2008_r']
# Named wrapper links within spack.build_env_path # Named wrapper links within spack.build_env_path
link_paths = { 'cc' : 'xl/xlc', link_paths = {'cc': 'xl/xlc',
'cxx' : 'xl/xlc++', 'cxx': 'xl/xlc++',
'f77' : 'xl/xlf', 'f77': 'xl/xlf',
'fc' : 'xl/xlf90' } 'fc': 'xl/xlf90'}
@property @property
def openmp_flag(self): def openmp_flag(self):
@ -56,7 +58,6 @@ def cxx11_flag(self):
else: else:
return "-qlanglvl=extended0x" return "-qlanglvl=extended0x"
@classmethod @classmethod
def default_version(cls, comp): def default_version(cls, comp):
"""The '-qversion' is the standard option fo XL compilers. """The '-qversion' is the standard option fo XL compilers.
@ -82,29 +83,28 @@ def default_version(cls, comp):
""" """
return get_compiler_version( return get_compiler_version(
comp, '-qversion',r'([0-9]?[0-9]\.[0-9])') comp, '-qversion', r'([0-9]?[0-9]\.[0-9])')
@classmethod @classmethod
def fc_version(cls, fc): def fc_version(cls, fc):
"""The fortran and C/C++ versions of the XL compiler are always two units apart. """The fortran and C/C++ versions of the XL compiler are always
By this we mean that the fortran release that goes with XL C/C++ 11.1 is 13.1. two units apart. By this we mean that the fortran release that
Having such a difference in version number is confusing spack quite a lot. goes with XL C/C++ 11.1 is 13.1. Having such a difference in
Most notably if you keep the versions as is the default xl compiler will only version number is confusing spack quite a lot. Most notably
have fortran and no C/C++. if you keep the versions as is the default xl compiler will
So we associate the Fortran compiler with the version associated to the C/C++ only have fortran and no C/C++. So we associate the Fortran
compiler. compiler with the version associated to the C/C++ compiler.
One last stumble. Version numbers over 10 have at least a .1 those under 10 One last stumble. Version numbers over 10 have at least a .1
a .0. There is no xlf 9.x or under currently available. BG/P and BG/L can those under 10 a .0. There is no xlf 9.x or under currently
such a compiler mix and possibly older version of AIX and linux on power. available. BG/P and BG/L can such a compiler mix and possibly
older version of AIX and linux on power.
""" """
fver = get_compiler_version(fc, '-qversion',r'([0-9]?[0-9]\.[0-9])') fver = get_compiler_version(fc, '-qversion', r'([0-9]?[0-9]\.[0-9])')
cver = float(fver) - 2 cver = float(fver) - 2
if cver < 10 : if cver < 10:
cver = cver - 0.1 cver = cver - 0.1
return str(cver) return str(cver)
@classmethod @classmethod
def f77_version(cls, f77): def f77_version(cls, f77):
return cls.fc_version(f77) return cls.fc_version(f77)

View file

@ -61,7 +61,9 @@ def _valid_virtuals_and_externals(self, spec):
if not providers: if not providers:
raise UnsatisfiableProviderSpecError(providers[0], spec) raise UnsatisfiableProviderSpecError(providers[0], spec)
spec_w_preferred_providers = find_spec( spec_w_preferred_providers = find_spec(
spec, lambda x: spack.pkgsort.spec_has_preferred_provider(x.name, spec.name)) # NOQA: ignore=E501 spec,
lambda x: spack.pkgsort.spec_has_preferred_provider(
x.name, spec.name))
if not spec_w_preferred_providers: if not spec_w_preferred_providers:
spec_w_preferred_providers = spec spec_w_preferred_providers = spec
provider_cmp = partial(spack.pkgsort.provider_compare, provider_cmp = partial(spack.pkgsort.provider_compare,
@ -495,7 +497,8 @@ class UnavailableCompilerVersionError(spack.error.SpackError):
def __init__(self, compiler_spec, operating_system): def __init__(self, compiler_spec, operating_system):
super(UnavailableCompilerVersionError, self).__init__( super(UnavailableCompilerVersionError, self).__init__(
"No available compiler version matches '%s' on operating_system %s" % (compiler_spec, operating_system), # NOQA: ignore=E501 "No available compiler version matches '%s' on operating_system %s"
% (compiler_spec, operating_system),
"Run 'spack compilers' to see available compiler Options.") "Run 'spack compilers' to see available compiler Options.")
@ -506,14 +509,15 @@ class NoValidVersionError(spack.error.SpackError):
def __init__(self, spec): def __init__(self, spec):
super(NoValidVersionError, self).__init__( super(NoValidVersionError, self).__init__(
"There are no valid versions for %s that match '%s'" % (spec.name, spec.versions)) # NOQA: ignore=E501 "There are no valid versions for %s that match '%s'"
% (spec.name, spec.versions))
class NoBuildError(spack.error.SpackError): class NoBuildError(spack.error.SpackError):
"""Raised when a package is configured with the buildable option False, but """Raised when a package is configured with the buildable option False, but
no satisfactory external versions can be found""" no satisfactory external versions can be found"""
def __init__(self, spec): def __init__(self, spec):
super(NoBuildError, self).__init__( msg = ("The spec '%s' is configured as not buildable, "
"The spec '%s' is configured as not buildable,and no matching external installs were found" % spec.name) # NOQA: ignore=E501 "and no matching external installs were found")
super(NoBuildError, self).__init__(msg % spec.name)

View file

@ -158,35 +158,35 @@
'required': ['cc', 'cxx', 'f77', 'fc'], 'required': ['cc', 'cxx', 'f77', 'fc'],
'additionalProperties': False, 'additionalProperties': False,
'properties': { 'properties': {
'cc': { 'anyOf': [ {'type' : 'string' }, 'cc': {'anyOf': [{'type': 'string'},
{'type' : 'null' }]}, {'type': 'null'}]},
'cxx': { 'anyOf': [ {'type' : 'string' }, 'cxx': {'anyOf': [{'type': 'string'},
{'type' : 'null' }]}, {'type': 'null'}]},
'f77': { 'anyOf': [ {'type' : 'string' }, 'f77': {'anyOf': [{'type': 'string'},
{'type' : 'null' }]}, {'type': 'null'}]},
'fc': { 'anyOf': [ {'type' : 'string' }, 'fc': {'anyOf': [{'type': 'string'},
{'type' : 'null' }]}, {'type': 'null'}]},
'cflags': { 'anyOf': [ {'type' : 'string' }, 'cflags': {'anyOf': [{'type': 'string'},
{'type' : 'null' }]}, {'type': 'null'}]},
'cxxflags': { 'anyOf': [ {'type' : 'string' }, 'cxxflags': {'anyOf': [{'type': 'string'},
{'type' : 'null' }]}, {'type': 'null'}]},
'fflags': { 'anyOf': [ {'type' : 'string' }, 'fflags': {'anyOf': [{'type': 'string'},
{'type' : 'null' }]}, {'type': 'null'}]},
'cppflags': { 'anyOf': [ {'type' : 'string' }, 'cppflags': {'anyOf': [{'type': 'string'},
{'type' : 'null' }]}, {'type': 'null'}]},
'ldflags': { 'anyOf': [ {'type' : 'string' }, 'ldflags': {'anyOf': [{'type': 'string'},
{'type' : 'null' }]}, {'type': 'null'}]},
'ldlibs': { 'anyOf': [ {'type' : 'string' }, 'ldlibs': {'anyOf': [{'type': 'string'},
{'type' : 'null' }]}}}, {'type': 'null'}]}}},
'spec': { 'type': 'string'}, 'spec': {'type': 'string'},
'operating_system': { 'type': 'string'}, 'operating_system': {'type': 'string'},
'alias': { 'anyOf': [ {'type' : 'string'}, 'alias': {'anyOf': [{'type': 'string'},
{'type' : 'null' }]}, {'type': 'null'}]},
'modules': { 'anyOf': [ {'type' : 'string'}, 'modules': {'anyOf': [{'type': 'string'},
{'type' : 'null' }, {'type': 'null'},
{'type': 'array'}, {'type': 'array'},
]} ]}
},},},},},}, }, }, }, }, }, },
'mirrors': { 'mirrors': {
'$schema': 'http://json-schema.org/schema#', '$schema': 'http://json-schema.org/schema#',
'title': 'Spack mirror configuration file schema', 'title': 'Spack mirror configuration file schema',
@ -199,7 +199,7 @@
'additionalProperties': False, 'additionalProperties': False,
'patternProperties': { 'patternProperties': {
r'\w[\w-]*': { r'\w[\w-]*': {
'type': 'string'},},},},}, 'type': 'string'}, }, }, }, },
'repos': { 'repos': {
'$schema': 'http://json-schema.org/schema#', '$schema': 'http://json-schema.org/schema#',
@ -211,7 +211,7 @@
'type': 'array', 'type': 'array',
'default': [], 'default': [],
'items': { 'items': {
'type': 'string'},},},}, 'type': 'string'}, }, }, },
'packages': { 'packages': {
'$schema': 'http://json-schema.org/schema#', '$schema': 'http://json-schema.org/schema#',
'title': 'Spack package configuration file schema', 'title': 'Spack package configuration file schema',
@ -223,48 +223,48 @@
'default': {}, 'default': {},
'additionalProperties': False, 'additionalProperties': False,
'patternProperties': { 'patternProperties': {
r'\w[\w-]*': { # package name r'\w[\w-]*': { # package name
'type': 'object', 'type': 'object',
'default': {}, 'default': {},
'additionalProperties': False, 'additionalProperties': False,
'properties': { 'properties': {
'version': { 'version': {
'type' : 'array', 'type': 'array',
'default' : [], 'default': [],
'items' : { 'anyOf' : [ { 'type' : 'string' }, 'items': {'anyOf': [{'type': 'string'},
{ 'type' : 'number'}]}}, #version strings {'type': 'number'}]}}, # version strings
'compiler': { 'compiler': {
'type' : 'array', 'type': 'array',
'default' : [], 'default': [],
'items' : { 'type' : 'string' } }, #compiler specs 'items': {'type': 'string'}}, # compiler specs
'buildable': { 'buildable': {
'type': 'boolean', 'type': 'boolean',
'default': True, 'default': True,
}, },
'modules': { 'modules': {
'type' : 'object', 'type': 'object',
'default' : {}, 'default': {},
}, },
'providers': { 'providers': {
'type': 'object', 'type': 'object',
'default': {}, 'default': {},
'additionalProperties': False, 'additionalProperties': False,
'patternProperties': { 'patternProperties': {
r'\w[\w-]*': { r'\w[\w-]*': {
'type' : 'array', 'type': 'array',
'default' : [], 'default': [],
'items' : { 'type' : 'string' },},},}, 'items': {'type': 'string'}, }, }, },
'paths': { 'paths': {
'type' : 'object', 'type': 'object',
'default' : {}, 'default': {},
}, },
'variants': { 'variants': {
'oneOf' : [ 'oneOf': [
{ 'type' : 'string' }, {'type': 'string'},
{ 'type' : 'array', {'type': 'array',
'items' : { 'type' : 'string' } }, 'items': {'type': 'string'}},
], }, ], },
},},},},},}, }, }, }, }, }, },
'targets': { 'targets': {
'$schema': 'http://json-schema.org/schema#', '$schema': 'http://json-schema.org/schema#',
@ -277,8 +277,8 @@
'default': {}, 'default': {},
'additionalProperties': False, 'additionalProperties': False,
'patternProperties': { 'patternProperties': {
r'\w[\w-]*': { # target name r'\w[\w-]*': { # target name
'type': 'string' ,},},},},}, 'type': 'string', }, }, }, }, },
'modules': { 'modules': {
'$schema': 'http://json-schema.org/schema#', '$schema': 'http://json-schema.org/schema#',
'title': 'Spack module file configuration file schema', 'title': 'Spack module file configuration file schema',
@ -389,13 +389,15 @@
}, },
'tcl': { 'tcl': {
'allOf': [ 'allOf': [
{'$ref': '#/definitions/module_type_configuration'}, # Base configuration # Base configuration
{'$ref': '#/definitions/module_type_configuration'},
{} # Specific tcl extensions {} # Specific tcl extensions
] ]
}, },
'dotkit': { 'dotkit': {
'allOf': [ 'allOf': [
{'$ref': '#/definitions/module_type_configuration'}, # Base configuration # Base configuration
{'$ref': '#/definitions/module_type_configuration'},
{} # Specific dotkit extensions {} # Specific dotkit extensions
] ]
}, },
@ -428,7 +430,8 @@ def extend_with_default(validator_class):
""" """
validate_properties = validator_class.VALIDATORS["properties"] validate_properties = validator_class.VALIDATORS["properties"]
validate_pattern_properties = validator_class.VALIDATORS["patternProperties"] validate_pattern_properties = validator_class.VALIDATORS[
"patternProperties"]
def set_defaults(validator, properties, instance, schema): def set_defaults(validator, properties, instance, schema):
for property, subschema in properties.iteritems(): for property, subschema in properties.iteritems():
@ -510,7 +513,8 @@ def write_section(self, section):
except jsonschema.ValidationError as e: except jsonschema.ValidationError as e:
raise ConfigSanityError(e, data) raise ConfigSanityError(e, data)
except (yaml.YAMLError, IOError) as e: except (yaml.YAMLError, IOError) as e:
raise ConfigFileError("Error writing to config file: '%s'" % str(e)) raise ConfigFileError(
"Error writing to config file: '%s'" % str(e))
def clear(self): def clear(self):
"""Empty cached config information.""" """Empty cached config information."""
@ -739,7 +743,8 @@ def spec_externals(spec):
path = get_path_from_module(module) path = get_path_from_module(module)
external_spec = spack.spec.Spec(external_spec, external=path, external_module=module) external_spec = spack.spec.Spec(
external_spec, external=path, external_module=module)
if external_spec.satisfies(spec): if external_spec.satisfies(spec):
external_specs.append(external_spec) external_specs.append(external_spec)
@ -773,6 +778,7 @@ def get_path(path, data):
class ConfigFormatError(ConfigError): class ConfigFormatError(ConfigError):
"""Raised when a configuration format does not match its schema.""" """Raised when a configuration format does not match its schema."""
def __init__(self, validation_error, data): def __init__(self, validation_error, data):
# Try to get line number from erroneous instance and its parent # Try to get line number from erroneous instance and its parent
instance_mark = getattr(validation_error.instance, '_start_mark', None) instance_mark = getattr(validation_error.instance, '_start_mark', None)

View file

@ -119,6 +119,7 @@ def from_dict(cls, spec, dictionary):
class Database(object): class Database(object):
def __init__(self, root, db_dir=None): def __init__(self, root, db_dir=None):
"""Create a Database for Spack installations under ``root``. """Create a Database for Spack installations under ``root``.
@ -600,6 +601,7 @@ def missing(self, spec):
class CorruptDatabaseError(SpackError): class CorruptDatabaseError(SpackError):
def __init__(self, path, msg=''): def __init__(self, path, msg=''):
super(CorruptDatabaseError, self).__init__( super(CorruptDatabaseError, self).__init__(
"Spack database is corrupt: %s. %s." % (path, msg), "Spack database is corrupt: %s. %s." % (path, msg),
@ -607,6 +609,7 @@ def __init__(self, path, msg=''):
class InvalidDatabaseVersionError(SpackError): class InvalidDatabaseVersionError(SpackError):
def __init__(self, expected, found): def __init__(self, expected, found):
super(InvalidDatabaseVersionError, self).__init__( super(InvalidDatabaseVersionError, self).__init__(
"Expected database version %s but found version %s." "Expected database version %s but found version %s."

View file

@ -349,9 +349,10 @@ def __init__(self, directive, package):
class UnknownDependencyTypeError(DirectiveError): class UnknownDependencyTypeError(DirectiveError):
"""This is raised when a dependency is of an unknown type.""" """This is raised when a dependency is of an unknown type."""
def __init__(self, directive, package, deptype): def __init__(self, directive, package, deptype):
super(UnknownDependencyTypeError, self).__init__( super(UnknownDependencyTypeError, self).__init__(
directive, directive,
"Package '%s' cannot depend on a package via %s." % "Package '%s' cannot depend on a package via %s."
(package, deptype)) % (package, deptype))
self.package = package self.package = package

View file

@ -22,16 +22,13 @@
# License along with this program; if not, write to the Free Software # License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import re
import os import os
import exceptions import exceptions
import hashlib
import shutil import shutil
import glob import glob
import tempfile import tempfile
import yaml import yaml
import llnl.util.tty as tty
from llnl.util.filesystem import join_path, mkdirp from llnl.util.filesystem import join_path, mkdirp
import spack import spack
@ -51,10 +48,10 @@ class DirectoryLayout(object):
install, and they can use this to customize the nesting structure of install, and they can use this to customize the nesting structure of
spack installs. spack installs.
""" """
def __init__(self, root): def __init__(self, root):
self.root = root self.root = root
@property @property
def hidden_file_paths(self): def hidden_file_paths(self):
"""Return a list of hidden files used by the directory layout. """Return a list of hidden files used by the directory layout.
@ -67,25 +64,21 @@ def hidden_file_paths(self):
""" """
raise NotImplementedError() raise NotImplementedError()
def all_specs(self): def all_specs(self):
"""To be implemented by subclasses to traverse all specs for which there is """To be implemented by subclasses to traverse all specs for which there is
a directory within the root. a directory within the root.
""" """
raise NotImplementedError() raise NotImplementedError()
def relative_path_for_spec(self, spec): def relative_path_for_spec(self, spec):
"""Implemented by subclasses to return a relative path from the install """Implemented by subclasses to return a relative path from the install
root to a unique location for the provided spec.""" root to a unique location for the provided spec."""
raise NotImplementedError() raise NotImplementedError()
def create_install_directory(self, spec): def create_install_directory(self, spec):
"""Creates the installation directory for a spec.""" """Creates the installation directory for a spec."""
raise NotImplementedError() raise NotImplementedError()
def check_installed(self, spec): def check_installed(self, spec):
"""Checks whether a spec is installed. """Checks whether a spec is installed.
@ -95,7 +88,6 @@ def check_installed(self, spec):
""" """
raise NotImplementedError() raise NotImplementedError()
def extension_map(self, spec): def extension_map(self, spec):
"""Get a dict of currently installed extension packages for a spec. """Get a dict of currently installed extension packages for a spec.
@ -104,7 +96,6 @@ def extension_map(self, spec):
""" """
raise NotImplementedError() raise NotImplementedError()
def check_extension_conflict(self, spec, ext_spec): def check_extension_conflict(self, spec, ext_spec):
"""Ensure that ext_spec can be activated in spec. """Ensure that ext_spec can be activated in spec.
@ -113,7 +104,6 @@ def check_extension_conflict(self, spec, ext_spec):
""" """
raise NotImplementedError() raise NotImplementedError()
def check_activated(self, spec, ext_spec): def check_activated(self, spec, ext_spec):
"""Ensure that ext_spec can be removed from spec. """Ensure that ext_spec can be removed from spec.
@ -121,26 +111,22 @@ def check_activated(self, spec, ext_spec):
""" """
raise NotImplementedError() raise NotImplementedError()
def add_extension(self, spec, ext_spec): def add_extension(self, spec, ext_spec):
"""Add to the list of currently installed extensions.""" """Add to the list of currently installed extensions."""
raise NotImplementedError() raise NotImplementedError()
def remove_extension(self, spec, ext_spec): def remove_extension(self, spec, ext_spec):
"""Remove from the list of currently installed extensions.""" """Remove from the list of currently installed extensions."""
raise NotImplementedError() raise NotImplementedError()
def path_for_spec(self, spec): def path_for_spec(self, spec):
"""Return an absolute path from the root to a directory for the spec.""" """Return absolute path from the root to a directory for the spec."""
_check_concrete(spec) _check_concrete(spec)
path = self.relative_path_for_spec(spec) path = self.relative_path_for_spec(spec)
assert(not path.startswith(self.root)) assert(not path.startswith(self.root))
return os.path.join(self.root, path) return os.path.join(self.root, path)
def remove_install_directory(self, spec): def remove_install_directory(self, spec):
"""Removes a prefix and any empty parent directories from the root. """Removes a prefix and any empty parent directories from the root.
Raised RemoveFailedError if something goes wrong. Raised RemoveFailedError if something goes wrong.
@ -177,6 +163,7 @@ class YamlDirectoryLayout(DirectoryLayout):
only enabled variants are included in the install path. only enabled variants are included in the install path.
Disabled variants are omitted. Disabled variants are omitted.
""" """
def __init__(self, root, **kwargs): def __init__(self, root, **kwargs):
super(YamlDirectoryLayout, self).__init__(root) super(YamlDirectoryLayout, self).__init__(root)
self.metadata_dir = kwargs.get('metadata_dir', '.spack') self.metadata_dir = kwargs.get('metadata_dir', '.spack')
@ -191,12 +178,10 @@ def __init__(self, root, **kwargs):
# Cache of already written/read extension maps. # Cache of already written/read extension maps.
self._extension_maps = {} self._extension_maps = {}
@property @property
def hidden_file_paths(self): def hidden_file_paths(self):
return (self.metadata_dir,) return (self.metadata_dir,)
def relative_path_for_spec(self, spec): def relative_path_for_spec(self, spec):
_check_concrete(spec) _check_concrete(spec)
@ -208,20 +193,19 @@ def relative_path_for_spec(self, spec):
spec.version, spec.version,
spec.dag_hash(self.hash_len)) spec.dag_hash(self.hash_len))
path = join_path(spec.architecture, path = join_path(
spec.architecture,
"%s-%s" % (spec.compiler.name, spec.compiler.version), "%s-%s" % (spec.compiler.name, spec.compiler.version),
dir_name) dir_name)
return path return path
def write_spec(self, spec, path): def write_spec(self, spec, path):
"""Write a spec out to a file.""" """Write a spec out to a file."""
_check_concrete(spec) _check_concrete(spec)
with open(path, 'w') as f: with open(path, 'w') as f:
spec.to_yaml(f) spec.to_yaml(f)
def read_spec(self, path): def read_spec(self, path):
"""Read the contents of a file and parse them as a spec""" """Read the contents of a file and parse them as a spec"""
try: try:
@ -237,32 +221,26 @@ def read_spec(self, path):
spec._mark_concrete() spec._mark_concrete()
return spec return spec
def spec_file_path(self, spec): def spec_file_path(self, spec):
"""Gets full path to spec file""" """Gets full path to spec file"""
_check_concrete(spec) _check_concrete(spec)
return join_path(self.metadata_path(spec), self.spec_file_name) return join_path(self.metadata_path(spec), self.spec_file_name)
def metadata_path(self, spec): def metadata_path(self, spec):
return join_path(self.path_for_spec(spec), self.metadata_dir) return join_path(self.path_for_spec(spec), self.metadata_dir)
def build_log_path(self, spec): def build_log_path(self, spec):
return join_path(self.path_for_spec(spec), self.metadata_dir, return join_path(self.path_for_spec(spec), self.metadata_dir,
self.build_log_name) self.build_log_name)
def build_env_path(self, spec): def build_env_path(self, spec):
return join_path(self.path_for_spec(spec), self.metadata_dir, return join_path(self.path_for_spec(spec), self.metadata_dir,
self.build_env_name) self.build_env_name)
def build_packages_path(self, spec): def build_packages_path(self, spec):
return join_path(self.path_for_spec(spec), self.metadata_dir, return join_path(self.path_for_spec(spec), self.metadata_dir,
self.packages_dir) self.packages_dir)
def create_install_directory(self, spec): def create_install_directory(self, spec):
_check_concrete(spec) _check_concrete(spec)
@ -273,7 +251,6 @@ def create_install_directory(self, spec):
mkdirp(self.metadata_path(spec)) mkdirp(self.metadata_path(spec))
self.write_spec(spec, self.spec_file_path(spec)) self.write_spec(spec, self.spec_file_path(spec))
def check_installed(self, spec): def check_installed(self, spec):
_check_concrete(spec) _check_concrete(spec)
path = self.path_for_spec(spec) path = self.path_for_spec(spec)
@ -284,7 +261,7 @@ def check_installed(self, spec):
if not os.path.isfile(spec_file_path): if not os.path.isfile(spec_file_path):
raise InconsistentInstallDirectoryError( raise InconsistentInstallDirectoryError(
'Inconsistent state: install prefix exists but contains no spec.yaml:', 'Install prefix exists but contains no spec.yaml:',
" " + path) " " + path)
installed_spec = self.read_spec(spec_file_path) installed_spec = self.read_spec(spec_file_path)
@ -297,7 +274,6 @@ def check_installed(self, spec):
raise InconsistentInstallDirectoryError( raise InconsistentInstallDirectoryError(
'Spec file in %s does not match hash!' % spec_file_path) 'Spec file in %s does not match hash!' % spec_file_path)
def all_specs(self): def all_specs(self):
if not os.path.isdir(self.root): if not os.path.isdir(self.root):
return [] return []
@ -307,20 +283,17 @@ def all_specs(self):
spec_files = glob.glob(pattern) spec_files = glob.glob(pattern)
return [self.read_spec(s) for s in spec_files] return [self.read_spec(s) for s in spec_files]
def specs_by_hash(self): def specs_by_hash(self):
by_hash = {} by_hash = {}
for spec in self.all_specs(): for spec in self.all_specs():
by_hash[spec.dag_hash()] = spec by_hash[spec.dag_hash()] = spec
return by_hash return by_hash
def extension_file_path(self, spec): def extension_file_path(self, spec):
"""Gets full path to an installed package's extension file""" """Gets full path to an installed package's extension file"""
_check_concrete(spec) _check_concrete(spec)
return join_path(self.metadata_path(spec), self.extension_file_name) return join_path(self.metadata_path(spec), self.extension_file_name)
def _write_extensions(self, spec, extensions): def _write_extensions(self, spec, extensions):
path = self.extension_file_path(spec) path = self.extension_file_path(spec)
@ -332,23 +305,22 @@ def _write_extensions(self, spec, extensions):
# write tmp file # write tmp file
with tmp: with tmp:
yaml.dump({ yaml.dump({
'extensions' : [ 'extensions': [
{ ext.name : { {ext.name: {
'hash' : ext.dag_hash(), 'hash': ext.dag_hash(),
'path' : str(ext.prefix) 'path': str(ext.prefix)
}} for ext in sorted(extensions.values())] }} for ext in sorted(extensions.values())]
}, tmp, default_flow_style=False) }, tmp, default_flow_style=False)
# Atomic update by moving tmpfile on top of old one. # Atomic update by moving tmpfile on top of old one.
os.rename(tmp.name, path) os.rename(tmp.name, path)
def _extension_map(self, spec): def _extension_map(self, spec):
"""Get a dict<name -> spec> for all extensions currently """Get a dict<name -> spec> for all extensions currently
installed for this package.""" installed for this package."""
_check_concrete(spec) _check_concrete(spec)
if not spec in self._extension_maps: if spec not in self._extension_maps:
path = self.extension_file_path(spec) path = self.extension_file_path(spec)
if not os.path.exists(path): if not os.path.exists(path):
self._extension_maps[spec] = {} self._extension_maps[spec] = {}
@ -363,14 +335,14 @@ def _extension_map(self, spec):
dag_hash = entry[name]['hash'] dag_hash = entry[name]['hash']
prefix = entry[name]['path'] prefix = entry[name]['path']
if not dag_hash in by_hash: if dag_hash not in by_hash:
raise InvalidExtensionSpecError( raise InvalidExtensionSpecError(
"Spec %s not found in %s" % (dag_hash, prefix)) "Spec %s not found in %s" % (dag_hash, prefix))
ext_spec = by_hash[dag_hash] ext_spec = by_hash[dag_hash]
if not prefix == ext_spec.prefix: if prefix != ext_spec.prefix:
raise InvalidExtensionSpecError( raise InvalidExtensionSpecError(
"Prefix %s does not match spec with hash %s: %s" "Prefix %s does not match spec hash %s: %s"
% (prefix, dag_hash, ext_spec)) % (prefix, dag_hash, ext_spec))
exts[ext_spec.name] = ext_spec exts[ext_spec.name] = ext_spec
@ -378,13 +350,11 @@ def _extension_map(self, spec):
return self._extension_maps[spec] return self._extension_maps[spec]
def extension_map(self, spec): def extension_map(self, spec):
"""Defensive copying version of _extension_map() for external API.""" """Defensive copying version of _extension_map() for external API."""
_check_concrete(spec) _check_concrete(spec)
return self._extension_map(spec).copy() return self._extension_map(spec).copy()
def check_extension_conflict(self, spec, ext_spec): def check_extension_conflict(self, spec, ext_spec):
exts = self._extension_map(spec) exts = self._extension_map(spec)
if ext_spec.name in exts: if ext_spec.name in exts:
@ -394,13 +364,11 @@ def check_extension_conflict(self, spec, ext_spec):
else: else:
raise ExtensionConflictError(spec, ext_spec, installed_spec) raise ExtensionConflictError(spec, ext_spec, installed_spec)
def check_activated(self, spec, ext_spec): def check_activated(self, spec, ext_spec):
exts = self._extension_map(spec) exts = self._extension_map(spec)
if (not ext_spec.name in exts) or (ext_spec != exts[ext_spec.name]): if (ext_spec.name not in exts) or (ext_spec != exts[ext_spec.name]):
raise NoSuchExtensionError(spec, ext_spec) raise NoSuchExtensionError(spec, ext_spec)
def add_extension(self, spec, ext_spec): def add_extension(self, spec, ext_spec):
_check_concrete(spec) _check_concrete(spec)
_check_concrete(ext_spec) _check_concrete(ext_spec)
@ -413,7 +381,6 @@ def add_extension(self, spec, ext_spec):
exts[ext_spec.name] = ext_spec exts[ext_spec.name] = ext_spec
self._write_extensions(spec, exts) self._write_extensions(spec, exts)
def remove_extension(self, spec, ext_spec): def remove_extension(self, spec, ext_spec):
_check_concrete(spec) _check_concrete(spec)
_check_concrete(ext_spec) _check_concrete(ext_spec)
@ -429,12 +396,14 @@ def remove_extension(self, spec, ext_spec):
class DirectoryLayoutError(SpackError): class DirectoryLayoutError(SpackError):
"""Superclass for directory layout errors.""" """Superclass for directory layout errors."""
def __init__(self, message, long_msg=None): def __init__(self, message, long_msg=None):
super(DirectoryLayoutError, self).__init__(message, long_msg) super(DirectoryLayoutError, self).__init__(message, long_msg)
class SpecHashCollisionError(DirectoryLayoutError): class SpecHashCollisionError(DirectoryLayoutError):
"""Raised when there is a hash collision in an install layout.""" """Raised when there is a hash collision in an install layout."""
def __init__(self, installed_spec, new_spec): def __init__(self, installed_spec, new_spec):
super(SpecHashCollisionError, self).__init__( super(SpecHashCollisionError, self).__init__(
'Specs %s and %s have the same SHA-1 prefix!' 'Specs %s and %s have the same SHA-1 prefix!'
@ -443,6 +412,7 @@ def __init__(self, installed_spec, new_spec):
class RemoveFailedError(DirectoryLayoutError): class RemoveFailedError(DirectoryLayoutError):
"""Raised when a DirectoryLayout cannot remove an install prefix.""" """Raised when a DirectoryLayout cannot remove an install prefix."""
def __init__(self, installed_spec, prefix, error): def __init__(self, installed_spec, prefix, error):
super(RemoveFailedError, self).__init__( super(RemoveFailedError, self).__init__(
'Could not remove prefix %s for %s : %s' 'Could not remove prefix %s for %s : %s'
@ -452,12 +422,15 @@ def __init__(self, installed_spec, prefix, error):
class InconsistentInstallDirectoryError(DirectoryLayoutError): class InconsistentInstallDirectoryError(DirectoryLayoutError):
"""Raised when a package seems to be installed to the wrong place.""" """Raised when a package seems to be installed to the wrong place."""
def __init__(self, message, long_msg=None): def __init__(self, message, long_msg=None):
super(InconsistentInstallDirectoryError, self).__init__(message, long_msg) super(InconsistentInstallDirectoryError, self).__init__(
message, long_msg)
class InstallDirectoryAlreadyExistsError(DirectoryLayoutError): class InstallDirectoryAlreadyExistsError(DirectoryLayoutError):
"""Raised when create_install_directory is called unnecessarily.""" """Raised when create_install_directory is called unnecessarily."""
def __init__(self, path): def __init__(self, path):
super(InstallDirectoryAlreadyExistsError, self).__init__( super(InstallDirectoryAlreadyExistsError, self).__init__(
"Install path %s already exists!") "Install path %s already exists!")
@ -473,22 +446,26 @@ class InvalidExtensionSpecError(DirectoryLayoutError):
class ExtensionAlreadyInstalledError(DirectoryLayoutError): class ExtensionAlreadyInstalledError(DirectoryLayoutError):
"""Raised when an extension is added to a package that already has it.""" """Raised when an extension is added to a package that already has it."""
def __init__(self, spec, ext_spec): def __init__(self, spec, ext_spec):
super(ExtensionAlreadyInstalledError, self).__init__( super(ExtensionAlreadyInstalledError, self).__init__(
"%s is already installed in %s" % (ext_spec.short_spec, spec.short_spec)) "%s is already installed in %s"
% (ext_spec.short_spec, spec.short_spec))
class ExtensionConflictError(DirectoryLayoutError): class ExtensionConflictError(DirectoryLayoutError):
"""Raised when an extension is added to a package that already has it.""" """Raised when an extension is added to a package that already has it."""
def __init__(self, spec, ext_spec, conflict): def __init__(self, spec, ext_spec, conflict):
super(ExtensionConflictError, self).__init__( super(ExtensionConflictError, self).__init__(
"%s cannot be installed in %s because it conflicts with %s"% ( "%s cannot be installed in %s because it conflicts with %s"
ext_spec.short_spec, spec.short_spec, conflict.short_spec)) % (ext_spec.short_spec, spec.short_spec, conflict.short_spec))
class NoSuchExtensionError(DirectoryLayoutError): class NoSuchExtensionError(DirectoryLayoutError):
"""Raised when an extension isn't there on deactivate.""" """Raised when an extension isn't there on deactivate."""
def __init__(self, spec, ext_spec): def __init__(self, spec, ext_spec):
super(NoSuchExtensionError, self).__init__( super(NoSuchExtensionError, self).__init__(
"%s cannot be removed from %s because it's not activated."% ( "%s cannot be removed from %s because it's not activated."
ext_spec.short_spec, spec.short_spec)) % (ext_spec.short_spec, spec.short_spec))

View file

@ -1,4 +1,4 @@
# ##############################################################################
# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC. # Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
# Produced at the Lawrence Livermore National Laboratory. # Produced at the Lawrence Livermore National Laboratory.
# #
@ -21,7 +21,7 @@
# You should have received a copy of the GNU Lesser General Public # You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the Free Software # License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# ##############################################################################
import collections import collections
import inspect import inspect
import json import json
@ -287,7 +287,10 @@ def from_sourcing_files(*args, **kwargs):
shell = '{shell}'.format(**info) shell = '{shell}'.format(**info)
shell_options = '{shell_options}'.format(**info) shell_options = '{shell_options}'.format(**info)
source_file = '{source_command} {file} {concatenate_on_success}' source_file = '{source_command} {file} {concatenate_on_success}'
dump_environment = 'python -c "import os, json; print json.dumps(dict(os.environ))"' # NOQA: ignore=E501
dump_cmd = "import os, json; print json.dumps(dict(os.environ))"
dump_environment = 'python -c "%s"' % dump_cmd
# Construct the command that will be executed # Construct the command that will be executed
command = [source_file.format(file=file, **info) for file in args] command = [source_file.format(file=file, **info) for file in args]
command.append(dump_environment) command.append(dump_environment)
@ -326,8 +329,10 @@ def from_sourcing_files(*args, **kwargs):
for x in unset_variables: for x in unset_variables:
env.unset(x) env.unset(x)
# Variables that have been modified # Variables that have been modified
common_variables = set(this_environment).intersection(set(after_source_env)) # NOQA: ignore=E501 common_variables = set(
modified_variables = [x for x in common_variables if this_environment[x] != after_source_env[x]] # NOQA: ignore=E501 this_environment).intersection(set(after_source_env))
modified_variables = [x for x in common_variables
if this_environment[x] != after_source_env[x]]
def return_separator_if_any(first_value, second_value): def return_separator_if_any(first_value, second_value):
separators = ':', ';' separators = ':', ';'
@ -405,7 +410,7 @@ def set_or_unset_not_first(variable, changes, errstream):
if indexes: if indexes:
good = '\t \t{context} at {filename}:{lineno}' good = '\t \t{context} at {filename}:{lineno}'
nogood = '\t--->\t{context} at {filename}:{lineno}' nogood = '\t--->\t{context} at {filename}:{lineno}'
message = 'Suspicious requests to set or unset the variable \'{var}\' found' # NOQA: ignore=E501 message = "Suspicious requests to set or unset '{var}' found"
errstream(message.format(var=variable)) errstream(message.format(var=variable))
for ii, item in enumerate(changes): for ii, item in enumerate(changes):
print_format = nogood if ii in indexes else good print_format = nogood if ii in indexes else good

View file

@ -27,21 +27,21 @@
import llnl.util.tty as tty import llnl.util.tty as tty
import spack import spack
class SpackError(Exception): class SpackError(Exception):
"""This is the superclass for all Spack errors. """This is the superclass for all Spack errors.
Subclasses can be found in the modules they have to do with. Subclasses can be found in the modules they have to do with.
""" """
def __init__(self, message, long_message=None): def __init__(self, message, long_message=None):
super(SpackError, self).__init__() super(SpackError, self).__init__()
self.message = message self.message = message
self._long_message = long_message self._long_message = long_message
@property @property
def long_message(self): def long_message(self):
return self._long_message return self._long_message
def die(self): def die(self):
if spack.debug: if spack.debug:
sys.excepthook(*sys.exc_info()) sys.excepthook(*sys.exc_info())
@ -52,21 +52,23 @@ def die(self):
print self.long_message print self.long_message
os._exit(1) os._exit(1)
def __str__(self): def __str__(self):
msg = self.message msg = self.message
if self._long_message: if self._long_message:
msg += "\n %s" % self._long_message msg += "\n %s" % self._long_message
return msg return msg
class UnsupportedPlatformError(SpackError): class UnsupportedPlatformError(SpackError):
"""Raised by packages when a platform is not supported""" """Raised by packages when a platform is not supported"""
def __init__(self, message): def __init__(self, message):
super(UnsupportedPlatformError, self).__init__(message) super(UnsupportedPlatformError, self).__init__(message)
class NoNetworkConnectionError(SpackError): class NoNetworkConnectionError(SpackError):
"""Raised when an operation needs an internet connection.""" """Raised when an operation needs an internet connection."""
def __init__(self, message, url): def __init__(self, message, url):
super(NoNetworkConnectionError, self).__init__( super(NoNetworkConnectionError, self).__init__(
"No network connection: " + str(message), "No network connection: " + str(message),

View file

@ -356,6 +356,7 @@ def __str__(self):
class CacheURLFetchStrategy(URLFetchStrategy): class CacheURLFetchStrategy(URLFetchStrategy):
"""The resource associated with a cache URL may be out of date.""" """The resource associated with a cache URL may be out of date."""
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(CacheURLFetchStrategy, self).__init__(*args, **kwargs) super(CacheURLFetchStrategy, self).__init__(*args, **kwargs)
@ -836,6 +837,7 @@ def for_package_version(pkg, version):
class FsCache(object): class FsCache(object):
def __init__(self, root): def __init__(self, root):
self.root = os.path.abspath(root) self.root = os.path.abspath(root)

View file

@ -41,6 +41,7 @@ class FileCache(object):
client code need not manage locks for cache entries. client code need not manage locks for cache entries.
""" """
def __init__(self, root): def __init__(self, root):
"""Create a file cache object. """Create a file cache object.
@ -131,6 +132,7 @@ def write_transaction(self, key):
""" """
class WriteContextManager(object): class WriteContextManager(object):
def __enter__(cm): def __enter__(cm):
cm.orig_filename = self.cache_path(key) cm.orig_filename = self.cache_path(key)
cm.orig_file = None cm.orig_file = None

View file

@ -136,6 +136,7 @@ def find(seq, predicate):
class AsciiGraph(object): class AsciiGraph(object):
def __init__(self): def __init__(self):
# These can be set after initialization or after a call to # These can be set after initialization or after a call to
# graph() to change behavior. # graph() to change behavior.
@ -288,22 +289,22 @@ def advance(to_pos, edges):
self._indent() self._indent()
for p in prev_ends: for p in prev_ends:
advance(p, lambda: [("| ", self._pos)]) # NOQA: ignore=E272 advance(p, lambda: [("| ", self._pos)])
advance(p + 1, lambda: [("|/", self._pos)]) # NOQA: ignore=E272 advance(p + 1, lambda: [("|/", self._pos)])
if end >= 0: if end >= 0:
advance(end + 1, lambda: [("| ", self._pos)]) # NOQA: ignore=E272 advance(end + 1, lambda: [("| ", self._pos)])
advance(start - 1, lambda: [("|", self._pos), ("_", end)]) # NOQA: ignore=E272 advance(start - 1, lambda: [("|", self._pos), ("_", end)])
else: else:
advance(start - 1, lambda: [("| ", self._pos)]) # NOQA: ignore=E272 advance(start - 1, lambda: [("| ", self._pos)])
if start >= 0: if start >= 0:
advance(start, lambda: [("|", self._pos), ("/", end)]) # NOQA: ignore=E272 advance(start, lambda: [("|", self._pos), ("/", end)])
if collapse: if collapse:
advance(flen, lambda: [(" /", self._pos)]) # NOQA: ignore=E272 advance(flen, lambda: [(" /", self._pos)])
else: else:
advance(flen, lambda: [("| ", self._pos)]) # NOQA: ignore=E272 advance(flen, lambda: [("| ", self._pos)])
self._set_state(BACK_EDGE, end, label) self._set_state(BACK_EDGE, end, label)
self._out.write("\n") self._out.write("\n")
@ -438,8 +439,8 @@ def write(self, spec, **kwargs):
# Expand forward after doing all back connections # Expand forward after doing all back connections
if (i + 1 < len(self._frontier) and if (i + 1 < len(self._frontier) and
len(self._frontier[i + 1]) == 1 and len(self._frontier[i + 1]) == 1 and
self._frontier[i + 1][0] in self._frontier[i]): self._frontier[i + 1][0] in self._frontier[i]):
# We need to connect to the element to the right. # We need to connect to the element to the right.
# Keep lines straight by connecting directly and # Keep lines straight by connecting directly and
# avoiding unnecessary expand/contract. # avoiding unnecessary expand/contract.

View file

@ -45,6 +45,7 @@
from llnl.util.filesystem import join_path from llnl.util.filesystem import join_path
import spack import spack
@memoized @memoized
def all_hook_modules(): def all_hook_modules():
modules = [] modules = []
@ -58,6 +59,7 @@ def all_hook_modules():
class HookRunner(object): class HookRunner(object):
def __init__(self, hook_name): def __init__(self, hook_name):
self.hook_name = hook_name self.hook_name = hook_name

View file

@ -23,8 +23,6 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import spack
def pre_uninstall(pkg): def pre_uninstall(pkg):
assert(pkg.spec.concrete) assert(pkg.spec.concrete)

View file

@ -40,9 +40,8 @@
import spack.url as url import spack.url as url
import spack.fetch_strategy as fs import spack.fetch_strategy as fs
from spack.spec import Spec from spack.spec import Spec
from spack.stage import Stage
from spack.version import * from spack.version import *
from spack.util.compression import extension, allowed_archive from spack.util.compression import allowed_archive
def mirror_archive_filename(spec, fetcher): def mirror_archive_filename(spec, fetcher):
@ -52,10 +51,10 @@ def mirror_archive_filename(spec, fetcher):
if isinstance(fetcher, fs.URLFetchStrategy): if isinstance(fetcher, fs.URLFetchStrategy):
if fetcher.expand_archive: if fetcher.expand_archive:
# If we fetch this version with a URLFetchStrategy, use URL's archive type # If we fetch with a URLFetchStrategy, use URL's archive type
ext = url.downloaded_file_extension(fetcher.url) ext = url.downloaded_file_extension(fetcher.url)
else: else:
# If the archive shouldn't be expanded, don't check for its extension. # If the archive shouldn't be expanded, don't check extension.
ext = None ext = None
else: else:
# Otherwise we'll make a .tar.gz ourselves # Otherwise we'll make a .tar.gz ourselves
@ -106,7 +105,9 @@ def get_matching_versions(specs, **kwargs):
def suggest_archive_basename(resource): def suggest_archive_basename(resource):
""" """
Return a tentative basename for an archive. Raise an exception if the name is among the allowed archive types. Return a tentative basename for an archive.
Raises an exception if the name is not an allowed archive type.
:param fetcher: :param fetcher:
:return: :return:
@ -170,7 +171,7 @@ def create(path, specs, **kwargs):
'error': [] 'error': []
} }
# Iterate through packages and download all the safe tarballs for each of them # Iterate through packages and download all safe tarballs for each
for spec in version_specs: for spec in version_specs:
add_single_spec(spec, mirror_root, categories, **kwargs) add_single_spec(spec, mirror_root, categories, **kwargs)
@ -190,12 +191,15 @@ def add_single_spec(spec, mirror_root, categories, **kwargs):
fetcher = stage.fetcher fetcher = stage.fetcher
if ii == 0: if ii == 0:
# create a subdirectory for the current package@version # create a subdirectory for the current package@version
archive_path = os.path.abspath(join_path(mirror_root, mirror_archive_path(spec, fetcher))) archive_path = os.path.abspath(join_path(
mirror_root, mirror_archive_path(spec, fetcher)))
name = spec.format("$_$@") name = spec.format("$_$@")
else: else:
resource = stage.resource resource = stage.resource
archive_path = join_path(subdir, suggest_archive_basename(resource)) archive_path = join_path(
name = "{resource} ({pkg}).".format(resource=resource.name, pkg=spec.format("$_$@")) subdir, suggest_archive_basename(resource))
name = "{resource} ({pkg}).".format(
resource=resource.name, pkg=spec.format("$_$@"))
subdir = os.path.dirname(archive_path) subdir = os.path.dirname(archive_path)
mkdirp(subdir) mkdirp(subdir)
@ -217,15 +221,18 @@ def add_single_spec(spec, mirror_root, categories, **kwargs):
categories['present'].append(spec) categories['present'].append(spec)
else: else:
categories['mirrored'].append(spec) categories['mirrored'].append(spec)
except Exception as e: except Exception as e:
if spack.debug: if spack.debug:
sys.excepthook(*sys.exc_info()) sys.excepthook(*sys.exc_info())
else: else:
tty.warn("Error while fetching %s" % spec.format('$_$@'), e.message) tty.warn("Error while fetching %s"
% spec.format('$_$@'), e.message)
categories['error'].append(spec) categories['error'].append(spec)
class MirrorError(spack.error.SpackError): class MirrorError(spack.error.SpackError):
"""Superclass of all mirror-creation related errors.""" """Superclass of all mirror-creation related errors."""
def __init__(self, msg, long_msg=None): def __init__(self, msg, long_msg=None):
super(MirrorError, self).__init__(msg, long_msg) super(MirrorError, self).__init__(msg, long_msg)

View file

@ -459,7 +459,8 @@ def process_environment_command(self, env):
yield self.environment_modifications_formats[type( yield self.environment_modifications_formats[type(
command)].format(**command.args) command)].format(**command.args)
except KeyError: except KeyError:
message = 'Cannot handle command of type {command} : skipping request' # NOQA: ignore=E501 message = ('Cannot handle command of type {command}: '
'skipping request')
details = '{context} at {filename}:{lineno}' details = '{context} at {filename}:{lineno}'
tty.warn(message.format(command=type(command))) tty.warn(message.format(command=type(command)))
tty.warn(details.format(**command.args)) tty.warn(details.format(**command.args))
@ -494,7 +495,8 @@ class Dotkit(EnvModule):
autoload_format = 'dk_op {module_file}\n' autoload_format = 'dk_op {module_file}\n'
default_naming_format = '{name}-{version}-{compiler.name}-{compiler.version}' # NOQA: ignore=E501 default_naming_format = \
'{name}-{version}-{compiler.name}-{compiler.version}'
@property @property
def file_name(self): def file_name(self):
@ -543,7 +545,8 @@ class TclModule(EnvModule):
prerequisite_format = 'prereq {module_file}\n' prerequisite_format = 'prereq {module_file}\n'
default_naming_format = '{name}-{version}-{compiler.name}-{compiler.version}' # NOQA: ignore=E501 default_naming_format = \
'{name}-{version}-{compiler.name}-{compiler.version}'
@property @property
def file_name(self): def file_name(self):
@ -554,7 +557,7 @@ def header(self):
timestamp = datetime.datetime.now() timestamp = datetime.datetime.now()
# TCL Modulefile header # TCL Modulefile header
header = '#%Module1.0\n' header = '#%Module1.0\n'
header += '## Module file created by spack (https://github.com/LLNL/spack) on %s\n' % timestamp # NOQA: ignore=E501 header += '## Module file created by spack (https://github.com/LLNL/spack) on %s\n' % timestamp
header += '##\n' header += '##\n'
header += '## %s\n' % self.spec.short_spec header += '## %s\n' % self.spec.short_spec
header += '##\n' header += '##\n'
@ -584,10 +587,12 @@ def module_specific_content(self, configuration):
for naming_dir, conflict_dir in zip( for naming_dir, conflict_dir in zip(
self.naming_scheme.split('/'), item.split('/')): self.naming_scheme.split('/'), item.split('/')):
if naming_dir != conflict_dir: if naming_dir != conflict_dir:
message = 'conflict scheme does not match naming scheme [{spec}]\n\n' # NOQA: ignore=E501 message = 'conflict scheme does not match naming '
message += 'scheme [{spec}]\n\n'
message += 'naming scheme : "{nformat}"\n' message += 'naming scheme : "{nformat}"\n'
message += 'conflict scheme : "{cformat}"\n\n' message += 'conflict scheme : "{cformat}"\n\n'
message += '** You may want to check your `modules.yaml` configuration file **\n' # NOQA: ignore=E501 message += '** You may want to check your '
message += '`modules.yaml` configuration file **\n'
tty.error(message.format(spec=self.spec, tty.error(message.format(spec=self.spec,
nformat=self.naming_scheme, nformat=self.naming_scheme,
cformat=item)) cformat=item))

View file

@ -43,15 +43,13 @@
depending on the scenario, regular old conditionals might be clearer, depending on the scenario, regular old conditionals might be clearer,
so package authors should use their judgement. so package authors should use their judgement.
""" """
import sys
import functools import functools
import collections
from llnl.util.lang import * from llnl.util.lang import *
import spack.architecture import spack.architecture
import spack.error import spack.error
from spack.spec import parse_anonymous_spec, Spec from spack.spec import parse_anonymous_spec
class SpecMultiMethod(object): class SpecMultiMethod(object):
@ -89,13 +87,13 @@ class SpecMultiMethod(object):
See the docs for decorators below for more details. See the docs for decorators below for more details.
""" """
def __init__(self, default=None): def __init__(self, default=None):
self.method_list = [] self.method_list = []
self.default = default self.default = default
if default: if default:
functools.update_wrapper(self, default) functools.update_wrapper(self, default)
def register(self, spec, method): def register(self, spec, method):
"""Register a version of a method for a particular sys_type.""" """Register a version of a method for a particular sys_type."""
self.method_list.append((spec, method)) self.method_list.append((spec, method))
@ -105,12 +103,10 @@ def register(self, spec, method):
else: else:
assert(self.__name__ == method.__name__) assert(self.__name__ == method.__name__)
def __get__(self, obj, objtype): def __get__(self, obj, objtype):
"""This makes __call__ support instance methods.""" """This makes __call__ support instance methods."""
return functools.partial(self.__call__, obj) return functools.partial(self.__call__, obj)
def __call__(self, package_self, *args, **kwargs): def __call__(self, package_self, *args, **kwargs):
"""Find the first method with a spec that matches the """Find the first method with a spec that matches the
package's spec. If none is found, call the default package's spec. If none is found, call the default
@ -127,7 +123,6 @@ def __call__(self, package_self, *args, **kwargs):
type(package_self), self.__name__, spec, type(package_self), self.__name__, spec,
[m[0] for m in self.method_list]) [m[0] for m in self.method_list])
def __str__(self): def __str__(self):
return "SpecMultiMethod {\n\tdefault: %s,\n\tspecs: %s\n}" % ( return "SpecMultiMethod {\n\tdefault: %s,\n\tspecs: %s\n}" % (
self.default, self.method_list) self.default, self.method_list)
@ -195,11 +190,13 @@ def install(self, prefix):
platform-specific versions. There's not much we can do to get platform-specific versions. There's not much we can do to get
around this because of the way decorators work. around this because of the way decorators work.
""" """
def __init__(self, spec): def __init__(self, spec):
pkg = get_calling_module_name() pkg = get_calling_module_name()
if spec is True: if spec is True:
spec = pkg spec = pkg
self.spec = parse_anonymous_spec(spec, pkg) if spec is not False else None self.spec = (parse_anonymous_spec(spec, pkg)
if spec is not False else None)
def __call__(self, method): def __call__(self, method):
# Get the first definition of the method in the calling scope # Get the first definition of the method in the calling scope
@ -218,12 +215,14 @@ def __call__(self, method):
class MultiMethodError(spack.error.SpackError): class MultiMethodError(spack.error.SpackError):
"""Superclass for multimethod dispatch errors""" """Superclass for multimethod dispatch errors"""
def __init__(self, message): def __init__(self, message):
super(MultiMethodError, self).__init__(message) super(MultiMethodError, self).__init__(message)
class NoSuchMethodError(spack.error.SpackError): class NoSuchMethodError(spack.error.SpackError):
"""Raised when we can't find a version of a multi-method.""" """Raised when we can't find a version of a multi-method."""
def __init__(self, cls, method_name, spec, possible_specs): def __init__(self, cls, method_name, spec, possible_specs):
super(NoSuchMethodError, self).__init__( super(NoSuchMethodError, self).__init__(
"Package %s does not support %s called with %s. Options are: %s" "Package %s does not support %s called with %s. Options are: %s"

View file

@ -15,6 +15,7 @@ class Cnl(OperatingSystem):
modules. If updated, user must make sure that version and name are modules. If updated, user must make sure that version and name are
updated to indicate that OS has been upgraded (or downgraded) updated to indicate that OS has been upgraded (or downgraded)
""" """
def __init__(self): def __init__(self):
name = 'CNL' name = 'CNL'
version = '10' version = '10'

View file

@ -2,6 +2,7 @@
import platform as py_platform import platform as py_platform
from spack.architecture import OperatingSystem from spack.architecture import OperatingSystem
class LinuxDistro(OperatingSystem): class LinuxDistro(OperatingSystem):
""" This class will represent the autodetected operating system """ This class will represent the autodetected operating system
for a Linux System. Since there are many different flavors of for a Linux System. Since there are many different flavors of
@ -9,6 +10,7 @@ class LinuxDistro(OperatingSystem):
autodetection using the python module platform and the method autodetection using the python module platform and the method
platform.dist() platform.dist()
""" """
def __init__(self): def __init__(self):
distname, version, _ = py_platform.linux_distribution( distname, version, _ = py_platform.linux_distribution(
full_distribution_name=False) full_distribution_name=False)

View file

@ -1,6 +1,7 @@
import platform as py_platform import platform as py_platform
from spack.architecture import OperatingSystem from spack.architecture import OperatingSystem
class MacOs(OperatingSystem): class MacOs(OperatingSystem):
"""This class represents the macOS operating system. This will be """This class represents the macOS operating system. This will be
auto detected using the python platform.mac_ver. The macOS auto detected using the python platform.mac_ver. The macOS

View file

@ -34,6 +34,7 @@
README. README.
""" """
import os import os
import sys
import re import re
import textwrap import textwrap
import time import time
@ -178,12 +179,10 @@ def install(self, spec, prefix):
Most software comes in nicely packaged tarballs, like this one: Most software comes in nicely packaged tarballs, like this one:
http://www.cmake.org/files/v2.8/cmake-2.8.10.2.tar.gz http://www.cmake.org/files/v2.8/cmake-2.8.10.2.tar.gz
Taking a page from homebrew, spack deduces pretty much everything it Taking a page from homebrew, spack deduces pretty much everything it
needs to know from the URL above. If you simply type this: needs to know from the URL above. If you simply type this:
spack create http://www.cmake.org/files/v2.8/cmake-2.8.10.2.tar.gz spack create http://www.cmake.org/files/v2.8/cmake-2.8.10.2.tar.gz
Spack will download the tarball, generate an md5 hash, figure out the Spack will download the tarball, generate an md5 hash, figure out the
version and the name of the package from the URL, and create a new version and the name of the package from the URL, and create a new
package file for you with all the names and attributes set correctly. package file for you with all the names and attributes set correctly.
@ -705,13 +704,13 @@ def do_fetch(self, mirror_only=False):
# Ask the user whether to skip the checksum if we're # Ask the user whether to skip the checksum if we're
# interactive, but just fail if non-interactive. # interactive, but just fail if non-interactive.
checksum_msg = "Add a checksum or use --no-checksum to skip this check." # NOQA: ignore=E501 ck_msg = "Add a checksum or use --no-checksum to skip this check."
ignore_checksum = False ignore_checksum = False
if sys.stdout.isatty(): if sys.stdout.isatty():
ignore_checksum = tty.get_yes_or_no(" Fetch anyway?", ignore_checksum = tty.get_yes_or_no(" Fetch anyway?",
default=False) default=False)
if ignore_checksum: if ignore_checksum:
tty.msg("Fetching with no checksum.", checksum_msg) tty.msg("Fetching with no checksum.", ck_msg)
if not ignore_checksum: if not ignore_checksum:
raise FetchError("Will not fetch %s" % raise FetchError("Will not fetch %s" %
@ -1305,9 +1304,10 @@ def do_deactivate(self, **kwargs):
continue continue
for dep in aspec.traverse(deptype='run'): for dep in aspec.traverse(deptype='run'):
if self.spec == dep: if self.spec == dep:
msg = ("Cannot deactivate %s because %s is activated "
"and depends on it.")
raise ActivationError( raise ActivationError(
"Cannot deactivate %s because %s is activated and depends on it." # NOQA: ignore=E501 msg % (self.spec.short_spec, aspec.short_spec))
% (self.spec.short_spec, aspec.short_spec))
self.extendee_spec.package.deactivate(self, **self.extendee_args) self.extendee_spec.package.deactivate(self, **self.extendee_args)
@ -1564,6 +1564,7 @@ def make_executable(path):
class CMakePackage(StagedPackage): class CMakePackage(StagedPackage):
def make_make(self): def make_make(self):
import multiprocessing import multiprocessing
# number of jobs spack will to build with. # number of jobs spack will to build with.
@ -1740,12 +1741,14 @@ class ExtensionError(PackageError):
class ExtensionConflictError(ExtensionError): class ExtensionConflictError(ExtensionError):
def __init__(self, path): def __init__(self, path):
super(ExtensionConflictError, self).__init__( super(ExtensionConflictError, self).__init__(
"Extension blocked by file: %s" % path) "Extension blocked by file: %s" % path)
class ActivationError(ExtensionError): class ActivationError(ExtensionError):
def __init__(self, msg, long_msg=None): def __init__(self, msg, long_msg=None):
super(ActivationError, self).__init__(msg, long_msg) super(ActivationError, self).__init__(msg, long_msg)

View file

@ -29,6 +29,7 @@
class Token: class Token:
"""Represents tokens; generated from input by lexer and fed to parse().""" """Represents tokens; generated from input by lexer and fed to parse()."""
def __init__(self, type, value='', start=0, end=0): def __init__(self, type, value='', start=0, end=0):
self.type = type self.type = type
self.value = value self.value = value
@ -51,11 +52,13 @@ def __cmp__(self, other):
class Lexer(object): class Lexer(object):
"""Base class for Lexers that keep track of line numbers.""" """Base class for Lexers that keep track of line numbers."""
def __init__(self, lexicon): def __init__(self, lexicon):
self.scanner = re.Scanner(lexicon) self.scanner = re.Scanner(lexicon)
def token(self, type, value=''): def token(self, type, value=''):
return Token(type, value, self.scanner.match.start(0), self.scanner.match.end(0)) return Token(type, value,
self.scanner.match.start(0), self.scanner.match.end(0))
def lex(self, text): def lex(self, text):
tokens, remainder = self.scanner.scan(text) tokens, remainder = self.scanner.scan(text)
@ -66,10 +69,11 @@ def lex(self, text):
class Parser(object): class Parser(object):
"""Base class for simple recursive descent parsers.""" """Base class for simple recursive descent parsers."""
def __init__(self, lexer): def __init__(self, lexer):
self.tokens = iter([]) # iterators over tokens, handled in order. Starts empty. self.tokens = iter([]) # iterators over tokens, handled in order.
self.token = Token(None) # last accepted token starts at beginning of file self.token = Token(None) # last accepted token
self.next = None # next token self.next = None # next token
self.lexer = lexer self.lexer = lexer
self.text = None self.text = None
@ -82,11 +86,12 @@ def gettok(self):
def push_tokens(self, iterable): def push_tokens(self, iterable):
"""Adds all tokens in some iterable to the token stream.""" """Adds all tokens in some iterable to the token stream."""
self.tokens = itertools.chain(iter(iterable), iter([self.next]), self.tokens) self.tokens = itertools.chain(
iter(iterable), iter([self.next]), self.tokens)
self.gettok() self.gettok()
def accept(self, id): def accept(self, id):
"""Puts the next symbol in self.token if we like it. Then calls gettok()""" """Put the next symbol in self.token if accepted, then call gettok()"""
if self.next and self.next.is_a(id): if self.next and self.next.is_a(id):
self.token = self.next self.token = self.next
self.gettok() self.gettok()
@ -124,9 +129,9 @@ def parse(self, text):
return self.do_parse() return self.do_parse()
class ParseError(spack.error.SpackError): class ParseError(spack.error.SpackError):
"""Raised when we don't hit an error while parsing.""" """Raised when we don't hit an error while parsing."""
def __init__(self, message, string, pos): def __init__(self, message, string, pos):
super(ParseError, self).__init__(message) super(ParseError, self).__init__(message)
self.string = string self.string = string
@ -135,5 +140,6 @@ def __init__(self, message, string, pos):
class LexError(ParseError): class LexError(ParseError):
"""Raised when we don't know how to lex something.""" """Raised when we don't know how to lex something."""
def __init__(self, message, string, pos): def __init__(self, message, string, pos):
super(LexError, self).__init__(message, string, pos) super(LexError, self).__init__(message, string, pos)

View file

@ -24,7 +24,6 @@
############################################################################## ##############################################################################
import os import os
import llnl.util.tty as tty
from llnl.util.filesystem import join_path from llnl.util.filesystem import join_path
import spack import spack
@ -59,7 +58,6 @@ def __init__(self, pkg, path_or_url, level):
if not os.path.isfile(self.path): if not os.path.isfile(self.path):
raise NoSuchPatchFileError(pkg_name, self.path) raise NoSuchPatchFileError(pkg_name, self.path)
def apply(self, stage): def apply(self, stage):
"""Fetch this patch, if necessary, and apply it to the source """Fetch this patch, if necessary, and apply it to the source
code in the supplied stage. code in the supplied stage.
@ -84,9 +82,9 @@ def apply(self, stage):
patch_stage.destroy() patch_stage.destroy()
class NoSuchPatchFileError(spack.error.SpackError): class NoSuchPatchFileError(spack.error.SpackError):
"""Raised when user specifies a patch file that doesn't exist.""" """Raised when user specifies a patch file that doesn't exist."""
def __init__(self, package, path): def __init__(self, package, path):
super(NoSuchPatchFileError, self).__init__( super(NoSuchPatchFileError, self).__init__(
"No such patch file for package %s: %s" % (package, path)) "No such patch file for package %s: %s" % (package, path))

View file

@ -1,6 +1,7 @@
import os import os
from spack.architecture import Platform, Target from spack.architecture import Platform, Target
class Bgq(Platform): class Bgq(Platform):
priority = 30 priority = 30
front_end = 'power7' front_end = 'power7'
@ -15,4 +16,3 @@ def __init__(self):
@classmethod @classmethod
def detect(self): def detect(self):
return os.path.exists('/bgsys') return os.path.exists('/bgsys')

View file

@ -2,6 +2,7 @@
from spack.architecture import Platform, Target from spack.architecture import Platform, Target
from spack.operating_systems.mac_os import MacOs from spack.operating_systems.mac_os import MacOs
class Darwin(Platform): class Darwin(Platform):
priority = 89 priority = 89
front_end = 'x86_64' front_end = 'x86_64'
@ -21,6 +22,6 @@ def __init__(self):
@classmethod @classmethod
def detect(self): def detect(self):
platform = subprocess.Popen(['uname', '-a'], stdout = subprocess.PIPE) platform = subprocess.Popen(['uname', '-a'], stdout=subprocess.PIPE)
platform, _ = platform.communicate() platform, _ = platform.communicate()
return 'darwin' in platform.strip().lower() return 'darwin' in platform.strip().lower()

View file

@ -3,6 +3,7 @@
from spack.architecture import Platform, Target from spack.architecture import Platform, Target
from spack.operating_systems.linux_distro import LinuxDistro from spack.operating_systems.linux_distro import LinuxDistro
class Linux(Platform): class Linux(Platform):
priority = 90 priority = 90
@ -26,6 +27,6 @@ def __init__(self):
@classmethod @classmethod
def detect(self): def detect(self):
platform = subprocess.Popen(['uname', '-a'], stdout = subprocess.PIPE) platform = subprocess.Popen(['uname', '-a'], stdout=subprocess.PIPE)
platform, _ = platform.communicate() platform, _ = platform.communicate()
return 'linux' in platform.strip().lower() return 'linux' in platform.strip().lower()

View file

@ -1,4 +1,27 @@
import subprocess ##############################################################################
# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
# Produced at the Lawrence Livermore National Laboratory.
#
# This file is part of Spack.
# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
# LLNL-CODE-647188
#
# For details, see https://github.com/llnl/spack
# Please also see the LICENSE file for our notice and the LGPL.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License (as
# published by the Free Software Foundation) version 2.1, February 1999.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
# conditions of the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
from spack.architecture import Platform, Target from spack.architecture import Platform, Target
from spack.operating_systems.linux_distro import LinuxDistro from spack.operating_systems.linux_distro import LinuxDistro
from spack.operating_systems.cnl import Cnl from spack.operating_systems.cnl import Cnl
@ -9,7 +32,7 @@ class Test(Platform):
front_end = 'x86_32' front_end = 'x86_32'
back_end = 'x86_64' back_end = 'x86_64'
default = 'x86_64' default = 'x86_64'
back_os = 'CNL10' back_os = 'CNL10'
default_os = 'CNL10' default_os = 'CNL10'

View file

@ -156,7 +156,7 @@ def spec_has_preferred_provider(self, pkgname, provider_str):
"""Return True iff the named package has a list of preferred """Return True iff the named package has a list of preferred
providers""" providers"""
return bool(self._order_for_package(pkgname, 'providers', return bool(self._order_for_package(pkgname, 'providers',
provider_str, False)) provider_str, False))
def spec_preferred_variants(self, pkgname): def spec_preferred_variants(self, pkgname):
"""Return a VariantMap of preferred variants and their values""" """Return a VariantMap of preferred variants and their values"""

View file

@ -52,6 +52,7 @@ class ProviderIndex(object):
matching implementation of MPI. matching implementation of MPI.
""" """
def __init__(self, specs=None, restrict=False): def __init__(self, specs=None, restrict=False):
"""Create a new ProviderIndex. """Create a new ProviderIndex.

View file

@ -68,6 +68,7 @@
def _autospec(function): def _autospec(function):
"""Decorator that automatically converts the argument of a single-arg """Decorator that automatically converts the argument of a single-arg
function to a Spec.""" function to a Spec."""
def converter(self, spec_like, *args, **kwargs): def converter(self, spec_like, *args, **kwargs):
if not isinstance(spec_like, spack.spec.Spec): if not isinstance(spec_like, spack.spec.Spec):
spec_like = spack.spec.Spec(spec_like) spec_like = spack.spec.Spec(spec_like)
@ -77,6 +78,7 @@ def converter(self, spec_like, *args, **kwargs):
class SpackNamespace(ModuleType): class SpackNamespace(ModuleType):
""" Allow lazy loading of modules.""" """ Allow lazy loading of modules."""
def __init__(self, namespace): def __init__(self, namespace):
super(SpackNamespace, self).__init__(namespace) super(SpackNamespace, self).__init__(namespace)
self.__file__ = "(spack namespace)" self.__file__ = "(spack namespace)"
@ -112,6 +114,7 @@ class RepoPath(object):
combined results of the Repos in its list instead of on a combined results of the Repos in its list instead of on a
single package repository. single package repository.
""" """
def __init__(self, *repo_dirs, **kwargs): def __init__(self, *repo_dirs, **kwargs):
# super-namespace for all packages in the RepoPath # super-namespace for all packages in the RepoPath
self.super_namespace = kwargs.get('namespace', repo_namespace) self.super_namespace = kwargs.get('namespace', repo_namespace)
@ -360,6 +363,7 @@ class Repo(object):
A Python namespace where the repository's packages should live. A Python namespace where the repository's packages should live.
""" """
def __init__(self, root, namespace=repo_namespace): def __init__(self, root, namespace=repo_namespace):
"""Instantiate a package repository from a filesystem path. """Instantiate a package repository from a filesystem path.
@ -923,6 +927,7 @@ class PackageLoadError(spack.error.SpackError):
class UnknownPackageError(PackageLoadError): class UnknownPackageError(PackageLoadError):
"""Raised when we encounter a package spack doesn't have.""" """Raised when we encounter a package spack doesn't have."""
def __init__(self, name, repo=None): def __init__(self, name, repo=None):
msg = None msg = None
if repo: if repo:
@ -935,6 +940,7 @@ def __init__(self, name, repo=None):
class UnknownNamespaceError(PackageLoadError): class UnknownNamespaceError(PackageLoadError):
"""Raised when we encounter an unknown namespace""" """Raised when we encounter an unknown namespace"""
def __init__(self, namespace): def __init__(self, namespace):
super(UnknownNamespaceError, self).__init__( super(UnknownNamespaceError, self).__init__(
"Unknown namespace: %s" % namespace) "Unknown namespace: %s" % namespace)
@ -942,6 +948,7 @@ def __init__(self, namespace):
class FailedConstructorError(PackageLoadError): class FailedConstructorError(PackageLoadError):
"""Raised when a package's class constructor fails.""" """Raised when a package's class constructor fails."""
def __init__(self, name, exc_type, exc_obj, exc_tb): def __init__(self, name, exc_type, exc_obj, exc_tb):
super(FailedConstructorError, self).__init__( super(FailedConstructorError, self).__init__(
"Class constructor failed for package '%s'." % name, "Class constructor failed for package '%s'." % name,

View file

@ -31,9 +31,11 @@
class Resource(object): class Resource(object):
"""Represents an optional resource to be fetched by a package.
Aggregates a name, a fetcher, a destination and a placement.
""" """
Represents an optional resource. Aggregates a name, a fetcher, a destination and a placement
"""
def __init__(self, name, fetcher, destination, placement): def __init__(self, name, fetcher, destination, placement):
self.name = name self.name = name
self.fetcher = fetcher self.fetcher = fetcher

View file

@ -166,6 +166,7 @@ def colorize_spec(spec):
"""Returns a spec colorized according to the colors specified in """Returns a spec colorized according to the colors specified in
color_formats.""" color_formats."""
class insert_color: class insert_color:
def __init__(self): def __init__(self):
self.last = None self.last = None
@ -186,6 +187,7 @@ class CompilerSpec(object):
"""The CompilerSpec field represents the compiler or range of compiler """The CompilerSpec field represents the compiler or range of compiler
versions that a package should be built with. CompilerSpecs have a versions that a package should be built with. CompilerSpecs have a
name and a version list. """ name and a version list. """
def __init__(self, *args): def __init__(self, *args):
nargs = len(args) nargs = len(args)
if nargs == 1: if nargs == 1:
@ -296,6 +298,7 @@ class DependencySpec(object):
- spec: the spack.spec.Spec description of a dependency. - spec: the spack.spec.Spec description of a dependency.
- deptypes: strings representing the type of dependency this is. - deptypes: strings representing the type of dependency this is.
""" """
def __init__(self, spec, deptypes): def __init__(self, spec, deptypes):
self.spec = spec self.spec = spec
self.deptypes = deptypes self.deptypes = deptypes
@ -317,6 +320,7 @@ class VariantSpec(object):
on the particular package being built, and each named variant can on the particular package being built, and each named variant can
be enabled or disabled. be enabled or disabled.
""" """
def __init__(self, name, value): def __init__(self, name, value):
self.name = name self.name = name
self.value = value self.value = value
@ -447,9 +451,9 @@ def __str__(self):
sorted_keys = filter( sorted_keys = filter(
lambda flag: self[flag] != [], sorted(self.keys())) lambda flag: self[flag] != [], sorted(self.keys()))
cond_symbol = ' ' if len(sorted_keys) > 0 else '' cond_symbol = ' ' if len(sorted_keys) > 0 else ''
return cond_symbol + ' '.join(str(key) + '=\"' + ' '.join(str(f) return cond_symbol + ' '.join(
for f in self[key]) + '\"' str(key) + '=\"' + ' '.join(
for key in sorted_keys) str(f) for f in self[key]) + '\"' for key in sorted_keys)
class DependencyMap(HashableMap): class DependencyMap(HashableMap):
@ -910,7 +914,7 @@ def to_node_dict(self):
params = dict((name, v.value) for name, v in self.variants.items()) params = dict((name, v.value) for name, v in self.variants.items())
params.update(dict((name, value) params.update(dict((name, value)
for name, value in self.compiler_flags.items())) for name, value in self.compiler_flags.items()))
if params: if params:
d['parameters'] = params d['parameters'] = params
@ -1598,8 +1602,8 @@ def constrain(self, other, deps=True):
raise UnsatisfiableSpecNameError(self.name, other.name) raise UnsatisfiableSpecNameError(self.name, other.name)
if (other.namespace is not None and if (other.namespace is not None and
self.namespace is not None and self.namespace is not None and
other.namespace != self.namespace): other.namespace != self.namespace):
raise UnsatisfiableSpecNameError(self.fullname, other.fullname) raise UnsatisfiableSpecNameError(self.fullname, other.fullname)
if not self.versions.overlaps(other.versions): if not self.versions.overlaps(other.versions):
@ -1753,8 +1757,8 @@ def satisfies(self, other, deps=True, strict=False):
# namespaces either match, or other doesn't require one. # namespaces either match, or other doesn't require one.
if (other.namespace is not None and if (other.namespace is not None and
self.namespace is not None and self.namespace is not None and
self.namespace != other.namespace): self.namespace != other.namespace):
return False return False
if self.versions and other.versions: if self.versions and other.versions:
if not self.versions.satisfies(other.versions, strict=strict): if not self.versions.satisfies(other.versions, strict=strict):
@ -1849,7 +1853,7 @@ def satisfies_dependencies(self, other, strict=False):
# compatible with mpich2) # compatible with mpich2)
for spec in self.virtual_dependencies(): for spec in self.virtual_dependencies():
if (spec.name in other_index and if (spec.name in other_index and
not other_index.providers_for(spec)): not other_index.providers_for(spec)):
return False return False
for spec in other.virtual_dependencies(): for spec in other.virtual_dependencies():
@ -2345,6 +2349,7 @@ def __init__(self):
class SpecParser(spack.parse.Parser): class SpecParser(spack.parse.Parser):
def __init__(self): def __init__(self):
super(SpecParser, self).__init__(_lexer) super(SpecParser, self).__init__(_lexer)
self.previous = None self.previous = None

View file

@ -40,6 +40,7 @@
class ArchitectureTest(MockPackagesTest): class ArchitectureTest(MockPackagesTest):
def setUp(self): def setUp(self):
super(ArchitectureTest, self).setUp() super(ArchitectureTest, self).setUp()
self.platform = spack.architecture.platform() self.platform = spack.architecture.platform()

View file

@ -45,7 +45,8 @@
'-llib1', '-llib2', '-llib1', '-llib2',
'arg4', 'arg4',
'-Wl,--end-group', '-Wl,--end-group',
'-Xlinker', '-rpath', '-Xlinker', '/third/rpath', '-Xlinker', '-rpath', '-Xlinker', '/fourth/rpath', '-Xlinker', '-rpath', '-Xlinker', '/third/rpath', '-Xlinker',
'-rpath', '-Xlinker', '/fourth/rpath',
'-llib3', '-llib4', '-llib3', '-llib4',
'arg5', 'arg6'] 'arg5', 'arg6']
@ -67,7 +68,7 @@ def setUp(self):
os.environ['SPACK_FC'] = self.realcc os.environ['SPACK_FC'] = self.realcc
os.environ['SPACK_PREFIX'] = self.prefix os.environ['SPACK_PREFIX'] = self.prefix
os.environ['SPACK_ENV_PATH']="test" os.environ['SPACK_ENV_PATH'] = "test"
os.environ['SPACK_DEBUG_LOG_DIR'] = "." os.environ['SPACK_DEBUG_LOG_DIR'] = "."
os.environ['SPACK_COMPILER_SPEC'] = "gcc@4.4.7" os.environ['SPACK_COMPILER_SPEC'] = "gcc@4.4.7"
os.environ['SPACK_SHORT_SPEC'] = "foo@1.2" os.environ['SPACK_SHORT_SPEC'] = "foo@1.2"
@ -97,16 +98,13 @@ def setUp(self):
if 'SPACK_DEPENDENCIES' in os.environ: if 'SPACK_DEPENDENCIES' in os.environ:
del os.environ['SPACK_DEPENDENCIES'] del os.environ['SPACK_DEPENDENCIES']
def tearDown(self): def tearDown(self):
shutil.rmtree(self.tmp_deps, True) shutil.rmtree(self.tmp_deps, True)
def check_cc(self, command, args, expected): def check_cc(self, command, args, expected):
os.environ['SPACK_TEST_COMMAND'] = command os.environ['SPACK_TEST_COMMAND'] = command
self.assertEqual(self.cc(*args, output=str).strip(), expected) self.assertEqual(self.cc(*args, output=str).strip(), expected)
def check_cxx(self, command, args, expected): def check_cxx(self, command, args, expected):
os.environ['SPACK_TEST_COMMAND'] = command os.environ['SPACK_TEST_COMMAND'] = command
self.assertEqual(self.cxx(*args, output=str).strip(), expected) self.assertEqual(self.cxx(*args, output=str).strip(), expected)
@ -115,46 +113,46 @@ def check_fc(self, command, args, expected):
os.environ['SPACK_TEST_COMMAND'] = command os.environ['SPACK_TEST_COMMAND'] = command
self.assertEqual(self.fc(*args, output=str).strip(), expected) self.assertEqual(self.fc(*args, output=str).strip(), expected)
def check_ld(self, command, args, expected): def check_ld(self, command, args, expected):
os.environ['SPACK_TEST_COMMAND'] = command os.environ['SPACK_TEST_COMMAND'] = command
self.assertEqual(self.ld(*args, output=str).strip(), expected) self.assertEqual(self.ld(*args, output=str).strip(), expected)
def check_cpp(self, command, args, expected): def check_cpp(self, command, args, expected):
os.environ['SPACK_TEST_COMMAND'] = command os.environ['SPACK_TEST_COMMAND'] = command
self.assertEqual(self.cpp(*args, output=str).strip(), expected) self.assertEqual(self.cpp(*args, output=str).strip(), expected)
def test_vcheck_mode(self): def test_vcheck_mode(self):
self.check_cc('dump-mode', ['-I/include', '--version'], "vcheck") self.check_cc('dump-mode', ['-I/include', '--version'], "vcheck")
self.check_cc('dump-mode', ['-I/include', '-V'], "vcheck") self.check_cc('dump-mode', ['-I/include', '-V'], "vcheck")
self.check_cc('dump-mode', ['-I/include', '-v'], "vcheck") self.check_cc('dump-mode', ['-I/include', '-v'], "vcheck")
self.check_cc('dump-mode', ['-I/include', '-dumpversion'], "vcheck") self.check_cc('dump-mode', ['-I/include', '-dumpversion'], "vcheck")
self.check_cc('dump-mode', ['-I/include', '--version', '-c'], "vcheck") self.check_cc('dump-mode', ['-I/include', '--version', '-c'], "vcheck")
self.check_cc('dump-mode', ['-I/include', '-V', '-o', 'output'], "vcheck") self.check_cc('dump-mode', ['-I/include',
'-V', '-o', 'output'], "vcheck")
def test_cpp_mode(self): def test_cpp_mode(self):
self.check_cc('dump-mode', ['-E'], "cpp") self.check_cc('dump-mode', ['-E'], "cpp")
self.check_cpp('dump-mode', [], "cpp") self.check_cpp('dump-mode', [], "cpp")
def test_as_mode(self): def test_as_mode(self):
self.check_cc('dump-mode', ['-S'], "as") self.check_cc('dump-mode', ['-S'], "as")
def test_ccld_mode(self): def test_ccld_mode(self):
self.check_cc('dump-mode', [], "ccld") self.check_cc('dump-mode', [], "ccld")
self.check_cc('dump-mode', ['foo.c', '-o', 'foo'], "ccld") self.check_cc('dump-mode', ['foo.c', '-o', 'foo'], "ccld")
self.check_cc('dump-mode', ['foo.c', '-o', 'foo', '-Wl,-rpath,foo'], "ccld") self.check_cc('dump-mode', ['foo.c', '-o',
self.check_cc('dump-mode', ['foo.o', 'bar.o', 'baz.o', '-o', 'foo', '-Wl,-rpath,foo'], "ccld") 'foo', '-Wl,-rpath,foo'], "ccld")
self.check_cc(
'dump-mode',
['foo.o', 'bar.o', 'baz.o', '-o', 'foo', '-Wl,-rpath,foo'],
"ccld")
def test_ld_mode(self): def test_ld_mode(self):
self.check_ld('dump-mode', [], "ld") self.check_ld('dump-mode', [], "ld")
self.check_ld('dump-mode', ['foo.o', 'bar.o', 'baz.o', '-o', 'foo', '-Wl,-rpath,foo'], "ld") self.check_ld(
'dump-mode',
['foo.o', 'bar.o', 'baz.o', '-o', 'foo', '-Wl,-rpath,foo'],
"ld")
def test_flags(self): def test_flags(self):
os.environ['SPACK_LDFLAGS'] = '-L foo' os.environ['SPACK_LDFLAGS'] = '-L foo'
@ -176,10 +174,11 @@ def test_flags(self):
# Test cppflags added properly in cpp mode # Test cppflags added properly in cpp mode
self.check_cpp('dump-args', test_command, self.check_cpp('dump-args', test_command,
"cpp " + "cpp " +
'-g -O1 ' + '-g -O1 ' +
' '.join(test_command)) ' '.join(test_command))
# Test ldflags, cppflags, and language specific flags are added in proper order # Test ldflags, cppflags, and language specific flags are added in
# proper order
self.check_cc('dump-args', test_command, self.check_cc('dump-args', test_command,
self.realcc + ' ' + self.realcc + ' ' +
'-Wl,-rpath,' + self.prefix + '/lib ' + '-Wl,-rpath,' + self.prefix + '/lib ' +
@ -191,14 +190,14 @@ def test_flags(self):
'-lfoo') '-lfoo')
self.check_cxx('dump-args', test_command, self.check_cxx('dump-args', test_command,
self.realcc + ' ' + self.realcc + ' ' +
'-Wl,-rpath,' + self.prefix + '/lib ' + '-Wl,-rpath,' + self.prefix + '/lib ' +
'-Wl,-rpath,' + self.prefix + '/lib64 ' + '-Wl,-rpath,' + self.prefix + '/lib64 ' +
'-g -O1 ' + '-g -O1 ' +
'-Werror ' + '-Werror ' +
'-L foo ' + '-L foo ' +
' '.join(test_command) + ' ' + ' '.join(test_command) + ' ' +
'-lfoo') '-lfoo')
self.check_fc('dump-args', test_command, self.check_fc('dump-args', test_command,
self.realcc + ' ' + self.realcc + ' ' +
@ -210,9 +209,8 @@ def test_flags(self):
' '.join(test_command) + ' ' + ' '.join(test_command) + ' ' +
'-lfoo') '-lfoo')
os.environ['SPACK_LDFLAGS']='' os.environ['SPACK_LDFLAGS'] = ''
os.environ['SPACK_LDLIBS']='' os.environ['SPACK_LDLIBS'] = ''
def test_dep_rpath(self): def test_dep_rpath(self):
"""Ensure RPATHs for root package are added.""" """Ensure RPATHs for root package are added."""
@ -222,7 +220,6 @@ def test_dep_rpath(self):
'-Wl,-rpath,' + self.prefix + '/lib64 ' + '-Wl,-rpath,' + self.prefix + '/lib64 ' +
' '.join(test_command)) ' '.join(test_command))
def test_dep_include(self): def test_dep_include(self):
"""Ensure a single dependency include directory is added.""" """Ensure a single dependency include directory is added."""
os.environ['SPACK_DEPENDENCIES'] = self.dep4 os.environ['SPACK_DEPENDENCIES'] = self.dep4
@ -233,7 +230,6 @@ def test_dep_include(self):
'-I' + self.dep4 + '/include ' + '-I' + self.dep4 + '/include ' +
' '.join(test_command)) ' '.join(test_command))
def test_dep_lib(self): def test_dep_lib(self):
"""Ensure a single dependency RPATH is added.""" """Ensure a single dependency RPATH is added."""
os.environ['SPACK_DEPENDENCIES'] = self.dep2 os.environ['SPACK_DEPENDENCIES'] = self.dep2
@ -245,7 +241,6 @@ def test_dep_lib(self):
'-Wl,-rpath,' + self.dep2 + '/lib64 ' + '-Wl,-rpath,' + self.dep2 + '/lib64 ' +
' '.join(test_command)) ' '.join(test_command))
def test_all_deps(self): def test_all_deps(self):
"""Ensure includes and RPATHs for all deps are added. """ """Ensure includes and RPATHs for all deps are added. """
os.environ['SPACK_DEPENDENCIES'] = ':'.join([ os.environ['SPACK_DEPENDENCIES'] = ':'.join([
@ -274,7 +269,6 @@ def test_all_deps(self):
' '.join(test_command)) ' '.join(test_command))
def test_ld_deps(self): def test_ld_deps(self):
"""Ensure no (extra) -I args or -Wl, are passed in ld mode.""" """Ensure no (extra) -I args or -Wl, are passed in ld mode."""
os.environ['SPACK_DEPENDENCIES'] = ':'.join([ os.environ['SPACK_DEPENDENCIES'] = ':'.join([

View file

@ -33,16 +33,17 @@
class TestModule(spack.test.mock_database.MockDatabase): class TestModule(spack.test.mock_database.MockDatabase):
def _get_module_files(self, args): def _get_module_files(self, args):
return [ return [modules.module_types[args.module_type](spec).file_name
modules.module_types[args.module_type](spec).file_name for spec in args.specs # NOQA: ignore=E501 for spec in args.specs]
]
def test_module_common_operations(self): def test_module_common_operations(self):
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
module.setup_parser(parser) module.setup_parser(parser)
# Try to remove a non existing module [tcl] # Try to remove a non existing module [tcl]
args = parser.parse_args(['rm', 'doesnotexist']) args = parser.parse_args(['rm', 'doesnotexist'])
self.assertRaises(SystemExit, module.module, parser, args) self.assertRaises(SystemExit, module.module, parser, args)
# Remove existing modules [tcl] # Remove existing modules [tcl]
args = parser.parse_args(['rm', '-y', 'mpileaks']) args = parser.parse_args(['rm', '-y', 'mpileaks'])
module_files = self._get_module_files(args) module_files = self._get_module_files(args)
@ -51,22 +52,28 @@ def test_module_common_operations(self):
module.module(parser, args) module.module(parser, args)
for item in module_files: for item in module_files:
self.assertFalse(os.path.exists(item)) self.assertFalse(os.path.exists(item))
# Add them back [tcl] # Add them back [tcl]
args = parser.parse_args(['refresh', '-y', 'mpileaks']) args = parser.parse_args(['refresh', '-y', 'mpileaks'])
module.module(parser, args) module.module(parser, args)
for item in module_files: for item in module_files:
self.assertTrue(os.path.exists(item)) self.assertTrue(os.path.exists(item))
# TODO : test the --delete-tree option # TODO : test the --delete-tree option
# TODO : this requires having a separate directory for test modules # TODO : this requires having a separate directory for test modules
# Try to find a module with multiple matches # Try to find a module with multiple matches
args = parser.parse_args(['find', 'mpileaks']) args = parser.parse_args(['find', 'mpileaks'])
self.assertRaises(SystemExit, module.module, parser, args) self.assertRaises(SystemExit, module.module, parser, args)
# Try to find a module with no matches # Try to find a module with no matches
args = parser.parse_args(['find', 'doesnotexist']) args = parser.parse_args(['find', 'doesnotexist'])
self.assertRaises(SystemExit, module.module, parser, args) self.assertRaises(SystemExit, module.module, parser, args)
# Try to find a module # Try to find a module
args = parser.parse_args(['find', 'libelf']) args = parser.parse_args(['find', 'libelf'])
module.module(parser, args) module.module(parser, args)
# Remove existing modules [dotkit] # Remove existing modules [dotkit]
args = parser.parse_args(['rm', '-y', '-m', 'dotkit', 'mpileaks']) args = parser.parse_args(['rm', '-y', '-m', 'dotkit', 'mpileaks'])
module_files = self._get_module_files(args) module_files = self._get_module_files(args)
@ -75,6 +82,7 @@ def test_module_common_operations(self):
module.module(parser, args) module.module(parser, args)
for item in module_files: for item in module_files:
self.assertFalse(os.path.exists(item)) self.assertFalse(os.path.exists(item))
# Add them back [dotkit] # Add them back [dotkit]
args = parser.parse_args(['refresh', '-y', '-m', 'dotkit', 'mpileaks']) args = parser.parse_args(['refresh', '-y', '-m', 'dotkit', 'mpileaks'])
module.module(parser, args) module.module(parser, args)

View file

@ -12,7 +12,9 @@
test_version = '4.5-spacktest' test_version = '4.5-spacktest'
class MockArgs(object): class MockArgs(object):
def __init__(self, add_paths=[], scope=None, compiler_spec=None, all=None): def __init__(self, add_paths=[], scope=None, compiler_spec=None, all=None):
self.add_paths = add_paths self.add_paths = add_paths
self.scope = scope self.scope = scope
@ -52,14 +54,12 @@ def make_mock_compiler():
class CompilerCmdTest(MockPackagesTest): class CompilerCmdTest(MockPackagesTest):
""" Test compiler commands for add and remove """ """ Test compiler commands for add and remove """
def test_compiler_remove(self): def test_compiler_remove(self):
args = MockArgs(all=True, compiler_spec='gcc@4.5.0') args = MockArgs(all=True, compiler_spec='gcc@4.5.0')
spack.cmd.compiler.compiler_remove(args) spack.cmd.compiler.compiler_remove(args)
compilers = spack.compilers.all_compilers() compilers = spack.compilers.all_compilers()
self.assertTrue(spack.spec.CompilerSpec("gcc@4.5.0") not in compilers) self.assertTrue(spack.spec.CompilerSpec("gcc@4.5.0") not in compilers)
def test_compiler_add(self): def test_compiler_add(self):
# compilers available by default. # compilers available by default.
old_compilers = set(spack.compilers.all_compilers()) old_compilers = set(spack.compilers.all_compilers())
@ -75,7 +75,8 @@ def test_compiler_add(self):
new_compilers = set(spack.compilers.all_compilers()) new_compilers = set(spack.compilers.all_compilers())
new_compiler = new_compilers - old_compilers new_compiler = new_compilers - old_compilers
self.assertTrue(new_compiler) self.assertTrue(new_compiler)
self.assertTrue(new_compiler.pop().version == Version(test_version)) self.assertTrue(new_compiler.pop().version ==
Version(test_version))
finally: finally:
shutil.rmtree(compiler_dir, ignore_errors=True) shutil.rmtree(compiler_dir, ignore_errors=True)

Some files were not shown because too many files have changed in this diff Show more