Merge branch 'features/python-2.6-compatibility' into develop
- Changed 'import argparse' to 'from external import argparse' in conflicts. Conflicts: lib/spack/spack/cmd/dotkit.py lib/spack/spack/cmd/unuse.py lib/spack/spack/cmd/use.py
This commit is contained in:
commit
8cc2298181
44 changed files with 3375 additions and 187 deletions
|
@ -24,11 +24,10 @@
|
|||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##############################################################################
|
||||
import sys
|
||||
if not sys.version_info[:2] >= (2,7):
|
||||
sys.exit("Spack requires Python 2.7. Version was %s." % sys.version_info)
|
||||
if not sys.version_info[:2] >= (2,6):
|
||||
sys.exit("Spack requires Python 2.6. Version was %s." % sys.version_info)
|
||||
|
||||
import os
|
||||
import argparse
|
||||
|
||||
# Find spack's location and its prefix.
|
||||
SPACK_FILE = os.path.realpath(os.path.expanduser(__file__))
|
||||
|
@ -51,6 +50,7 @@ del SPACK_FILE, SPACK_PREFIX, SPACK_LIB_PATH
|
|||
import llnl.util.tty as tty
|
||||
import spack
|
||||
from spack.error import SpackError
|
||||
from external import argparse
|
||||
|
||||
# Command parsing
|
||||
parser = argparse.ArgumentParser(
|
||||
|
|
6
lib/spack/env/cc
vendored
6
lib/spack/env/cc
vendored
|
@ -1,12 +1,11 @@
|
|||
#!/usr/bin/env python
|
||||
import sys
|
||||
if not sys.version_info[:2] >= (2,7):
|
||||
sys.exit("Spack requires Python 2.7. Version was %s." % sys.version_info)
|
||||
if not sys.version_info[:2] >= (2,6):
|
||||
sys.exit("Spack requires Python 2.6. Version was %s." % sys.version_info)
|
||||
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import argparse
|
||||
from contextlib import closing
|
||||
|
||||
# Import spack parameters through the build environment.
|
||||
|
@ -18,6 +17,7 @@ if not spack_lib:
|
|||
# Grab a minimal set of spack packages
|
||||
sys.path.append(spack_lib)
|
||||
from spack.compilation import *
|
||||
from external import argparse
|
||||
import llnl.util.tty as tty
|
||||
|
||||
spack_prefix = get_env_var("SPACK_PREFIX")
|
||||
|
|
33
lib/spack/external/__init__.py
vendored
Normal file
33
lib/spack/external/__init__.py
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
##############################################################################
|
||||
# Copyright (c) 2013, Lawrence Livermore National Security, LLC.
|
||||
# Produced at the Lawrence Livermore National Laboratory.
|
||||
#
|
||||
# This file is part of Spack.
|
||||
# Written by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
|
||||
# LLNL-CODE-647188
|
||||
#
|
||||
# For details, see https://scalability-llnl.github.io/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 General Public License (as published by
|
||||
# the Free Software Foundation) version 2.1 dated 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 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
|
||||
##############################################################################
|
||||
"""
|
||||
This module contains external, potentially separately licensed,
|
||||
packages that are included in spack.
|
||||
|
||||
So far:
|
||||
argparse: We include our own version to be Python 2.6 compatible.
|
||||
pyqver2: External script to query required python version of python source code.
|
||||
Used for ensuring 2.6 compatibility.
|
||||
"""
|
2382
lib/spack/external/argparse.py
vendored
Normal file
2382
lib/spack/external/argparse.py
vendored
Normal file
File diff suppressed because it is too large
Load diff
30
lib/spack/external/functools.py
vendored
Normal file
30
lib/spack/external/functools.py
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
#
|
||||
# Backport of Python 2.7's total_ordering.
|
||||
#
|
||||
|
||||
def total_ordering(cls):
|
||||
"""Class decorator that fills in missing ordering methods"""
|
||||
convert = {
|
||||
'__lt__': [('__gt__', lambda self, other: not (self < other or self == other)),
|
||||
('__le__', lambda self, other: self < other or self == other),
|
||||
('__ge__', lambda self, other: not self < other)],
|
||||
'__le__': [('__ge__', lambda self, other: not self <= other or self == other),
|
||||
('__lt__', lambda self, other: self <= other and not self == other),
|
||||
('__gt__', lambda self, other: not self <= other)],
|
||||
'__gt__': [('__lt__', lambda self, other: not (self > other or self == other)),
|
||||
('__ge__', lambda self, other: self > other or self == other),
|
||||
('__le__', lambda self, other: not self > other)],
|
||||
'__ge__': [('__le__', lambda self, other: (not self >= other) or self == other),
|
||||
('__gt__', lambda self, other: self >= other and not self == other),
|
||||
('__lt__', lambda self, other: not self >= other)]
|
||||
}
|
||||
roots = set(dir(cls)) & set(convert)
|
||||
if not roots:
|
||||
raise ValueError('must define at least one ordering operation: < > <= >=')
|
||||
root = max(roots) # prefer __lt__ to __le__ to __gt__ to __ge__
|
||||
for opname, opfunc in convert[root]:
|
||||
if opname not in roots:
|
||||
opfunc.__name__ = opname
|
||||
opfunc.__doc__ = getattr(int, opname).__doc__
|
||||
setattr(cls, opname, opfunc)
|
||||
return cls
|
262
lib/spack/external/ordereddict.py
vendored
Normal file
262
lib/spack/external/ordereddict.py
vendored
Normal file
|
@ -0,0 +1,262 @@
|
|||
#
|
||||
# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy.
|
||||
# Passes Python2.7's test suite and incorporates all the latest updates.
|
||||
#
|
||||
# From http://code.activestate.com/recipes/576693-ordered-dictionary-for-py24/
|
||||
# This file is in the public domain, and has no particular license.
|
||||
#
|
||||
try:
|
||||
from thread import get_ident as _get_ident
|
||||
except ImportError:
|
||||
from dummy_thread import get_ident as _get_ident
|
||||
|
||||
try:
|
||||
from _abcoll import KeysView, ValuesView, ItemsView
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
class OrderedDict(dict):
|
||||
'Dictionary that remembers insertion order'
|
||||
# An inherited dict maps keys to values.
|
||||
# The inherited dict provides __getitem__, __len__, __contains__, and get.
|
||||
# The remaining methods are order-aware.
|
||||
# Big-O running times for all methods are the same as for regular dictionaries.
|
||||
|
||||
# The internal self.__map dictionary maps keys to links in a doubly linked list.
|
||||
# The circular doubly linked list starts and ends with a sentinel element.
|
||||
# The sentinel element never gets deleted (this simplifies the algorithm).
|
||||
# Each link is stored as a list of length three: [PREV, NEXT, KEY].
|
||||
|
||||
def __init__(self, *args, **kwds):
|
||||
'''Initialize an ordered dictionary. Signature is the same as for
|
||||
regular dictionaries, but keyword arguments are not recommended
|
||||
because their insertion order is arbitrary.
|
||||
|
||||
'''
|
||||
if len(args) > 1:
|
||||
raise TypeError('expected at most 1 arguments, got %d' % len(args))
|
||||
try:
|
||||
self.__root
|
||||
except AttributeError:
|
||||
self.__root = root = [] # sentinel node
|
||||
root[:] = [root, root, None]
|
||||
self.__map = {}
|
||||
self.__update(*args, **kwds)
|
||||
|
||||
def __setitem__(self, key, value, dict_setitem=dict.__setitem__):
|
||||
'od.__setitem__(i, y) <==> od[i]=y'
|
||||
# Setting a new item creates a new link which goes at the end of the linked
|
||||
# list, and the inherited dictionary is updated with the new key/value pair.
|
||||
if key not in self:
|
||||
root = self.__root
|
||||
last = root[0]
|
||||
last[1] = root[0] = self.__map[key] = [last, root, key]
|
||||
dict_setitem(self, key, value)
|
||||
|
||||
def __delitem__(self, key, dict_delitem=dict.__delitem__):
|
||||
'od.__delitem__(y) <==> del od[y]'
|
||||
# Deleting an existing item uses self.__map to find the link which is
|
||||
# then removed by updating the links in the predecessor and successor nodes.
|
||||
dict_delitem(self, key)
|
||||
link_prev, link_next, key = self.__map.pop(key)
|
||||
link_prev[1] = link_next
|
||||
link_next[0] = link_prev
|
||||
|
||||
def __iter__(self):
|
||||
'od.__iter__() <==> iter(od)'
|
||||
root = self.__root
|
||||
curr = root[1]
|
||||
while curr is not root:
|
||||
yield curr[2]
|
||||
curr = curr[1]
|
||||
|
||||
def __reversed__(self):
|
||||
'od.__reversed__() <==> reversed(od)'
|
||||
root = self.__root
|
||||
curr = root[0]
|
||||
while curr is not root:
|
||||
yield curr[2]
|
||||
curr = curr[0]
|
||||
|
||||
def clear(self):
|
||||
'od.clear() -> None. Remove all items from od.'
|
||||
try:
|
||||
for node in self.__map.itervalues():
|
||||
del node[:]
|
||||
root = self.__root
|
||||
root[:] = [root, root, None]
|
||||
self.__map.clear()
|
||||
except AttributeError:
|
||||
pass
|
||||
dict.clear(self)
|
||||
|
||||
def popitem(self, last=True):
|
||||
'''od.popitem() -> (k, v), return and remove a (key, value) pair.
|
||||
Pairs are returned in LIFO order if last is true or FIFO order if false.
|
||||
|
||||
'''
|
||||
if not self:
|
||||
raise KeyError('dictionary is empty')
|
||||
root = self.__root
|
||||
if last:
|
||||
link = root[0]
|
||||
link_prev = link[0]
|
||||
link_prev[1] = root
|
||||
root[0] = link_prev
|
||||
else:
|
||||
link = root[1]
|
||||
link_next = link[1]
|
||||
root[1] = link_next
|
||||
link_next[0] = root
|
||||
key = link[2]
|
||||
del self.__map[key]
|
||||
value = dict.pop(self, key)
|
||||
return key, value
|
||||
|
||||
# -- the following methods do not depend on the internal structure --
|
||||
|
||||
def keys(self):
|
||||
'od.keys() -> list of keys in od'
|
||||
return list(self)
|
||||
|
||||
def values(self):
|
||||
'od.values() -> list of values in od'
|
||||
return [self[key] for key in self]
|
||||
|
||||
def items(self):
|
||||
'od.items() -> list of (key, value) pairs in od'
|
||||
return [(key, self[key]) for key in self]
|
||||
|
||||
def iterkeys(self):
|
||||
'od.iterkeys() -> an iterator over the keys in od'
|
||||
return iter(self)
|
||||
|
||||
def itervalues(self):
|
||||
'od.itervalues -> an iterator over the values in od'
|
||||
for k in self:
|
||||
yield self[k]
|
||||
|
||||
def iteritems(self):
|
||||
'od.iteritems -> an iterator over the (key, value) items in od'
|
||||
for k in self:
|
||||
yield (k, self[k])
|
||||
|
||||
def update(*args, **kwds):
|
||||
'''od.update(E, **F) -> None. Update od from dict/iterable E and F.
|
||||
|
||||
If E is a dict instance, does: for k in E: od[k] = E[k]
|
||||
If E has a .keys() method, does: for k in E.keys(): od[k] = E[k]
|
||||
Or if E is an iterable of items, does: for k, v in E: od[k] = v
|
||||
In either case, this is followed by: for k, v in F.items(): od[k] = v
|
||||
|
||||
'''
|
||||
if len(args) > 2:
|
||||
raise TypeError('update() takes at most 2 positional '
|
||||
'arguments (%d given)' % (len(args),))
|
||||
elif not args:
|
||||
raise TypeError('update() takes at least 1 argument (0 given)')
|
||||
self = args[0]
|
||||
# Make progressively weaker assumptions about "other"
|
||||
other = ()
|
||||
if len(args) == 2:
|
||||
other = args[1]
|
||||
if isinstance(other, dict):
|
||||
for key in other:
|
||||
self[key] = other[key]
|
||||
elif hasattr(other, 'keys'):
|
||||
for key in other.keys():
|
||||
self[key] = other[key]
|
||||
else:
|
||||
for key, value in other:
|
||||
self[key] = value
|
||||
for key, value in kwds.items():
|
||||
self[key] = value
|
||||
|
||||
__update = update # let subclasses override update without breaking __init__
|
||||
|
||||
__marker = object()
|
||||
|
||||
def pop(self, key, default=__marker):
|
||||
'''od.pop(k[,d]) -> v, remove specified key and return the corresponding value.
|
||||
If key is not found, d is returned if given, otherwise KeyError is raised.
|
||||
|
||||
'''
|
||||
if key in self:
|
||||
result = self[key]
|
||||
del self[key]
|
||||
return result
|
||||
if default is self.__marker:
|
||||
raise KeyError(key)
|
||||
return default
|
||||
|
||||
def setdefault(self, key, default=None):
|
||||
'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'
|
||||
if key in self:
|
||||
return self[key]
|
||||
self[key] = default
|
||||
return default
|
||||
|
||||
def __repr__(self, _repr_running={}):
|
||||
'od.__repr__() <==> repr(od)'
|
||||
call_key = id(self), _get_ident()
|
||||
if call_key in _repr_running:
|
||||
return '...'
|
||||
_repr_running[call_key] = 1
|
||||
try:
|
||||
if not self:
|
||||
return '%s()' % (self.__class__.__name__,)
|
||||
return '%s(%r)' % (self.__class__.__name__, self.items())
|
||||
finally:
|
||||
del _repr_running[call_key]
|
||||
|
||||
def __reduce__(self):
|
||||
'Return state information for pickling'
|
||||
items = [[k, self[k]] for k in self]
|
||||
inst_dict = vars(self).copy()
|
||||
for k in vars(OrderedDict()):
|
||||
inst_dict.pop(k, None)
|
||||
if inst_dict:
|
||||
return (self.__class__, (items,), inst_dict)
|
||||
return self.__class__, (items,)
|
||||
|
||||
def copy(self):
|
||||
'od.copy() -> a shallow copy of od'
|
||||
return self.__class__(self)
|
||||
|
||||
@classmethod
|
||||
def fromkeys(cls, iterable, value=None):
|
||||
'''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
|
||||
and values equal to v (which defaults to None).
|
||||
|
||||
'''
|
||||
d = cls()
|
||||
for key in iterable:
|
||||
d[key] = value
|
||||
return d
|
||||
|
||||
def __eq__(self, other):
|
||||
'''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
|
||||
while comparison to a regular mapping is order-insensitive.
|
||||
|
||||
'''
|
||||
if isinstance(other, OrderedDict):
|
||||
return len(self)==len(other) and self.items() == other.items()
|
||||
return dict.__eq__(self, other)
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
# -- the following methods are only used in Python 2.7 --
|
||||
|
||||
def viewkeys(self):
|
||||
"od.viewkeys() -> a set-like object providing a view on od's keys"
|
||||
return KeysView(self)
|
||||
|
||||
def viewvalues(self):
|
||||
"od.viewvalues() -> an object providing a view on od's values"
|
||||
return ValuesView(self)
|
||||
|
||||
def viewitems(self):
|
||||
"od.viewitems() -> a set-like object providing a view on od's items"
|
||||
return ItemsView(self)
|
393
lib/spack/external/pyqver2.py
vendored
Executable file
393
lib/spack/external/pyqver2.py
vendored
Executable file
|
@ -0,0 +1,393 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# pyqver2.py
|
||||
# by Greg Hewgill
|
||||
# https://github.com/ghewgill/pyqver
|
||||
#
|
||||
# This software is provided 'as-is', without any express or implied
|
||||
# warranty. In no event will the author be held liable for any damages
|
||||
# arising from the use of this software.
|
||||
#
|
||||
# Permission is granted to anyone to use this software for any purpose,
|
||||
# including commercial applications, and to alter it and redistribute it
|
||||
# freely, subject to the following restrictions:
|
||||
#
|
||||
# 1. The origin of this software must not be misrepresented; you must not
|
||||
# claim that you wrote the original software. If you use this software
|
||||
# in a product, an acknowledgment in the product documentation would be
|
||||
# appreciated but is not required.
|
||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||
# misrepresented as being the original software.
|
||||
# 3. This notice may not be removed or altered from any source distribution.
|
||||
#
|
||||
# Copyright (c) 2009-2013 Greg Hewgill http://hewgill.com
|
||||
#
|
||||
|
||||
import compiler
|
||||
import platform
|
||||
import sys
|
||||
|
||||
StandardModules = {
|
||||
"__future__": (2, 1),
|
||||
"abc": (2, 6),
|
||||
"argparse": (2, 7),
|
||||
"ast": (2, 6),
|
||||
"atexit": (2, 0),
|
||||
"bz2": (2, 3),
|
||||
"cgitb": (2, 2),
|
||||
"collections": (2, 4),
|
||||
"contextlib": (2, 5),
|
||||
"cookielib": (2, 4),
|
||||
"cProfile": (2, 5),
|
||||
"csv": (2, 3),
|
||||
"ctypes": (2, 5),
|
||||
"datetime": (2, 3),
|
||||
"decimal": (2, 4),
|
||||
"difflib": (2, 1),
|
||||
"DocXMLRPCServer": (2, 3),
|
||||
"dummy_thread": (2, 3),
|
||||
"dummy_threading": (2, 3),
|
||||
"email": (2, 2),
|
||||
"fractions": (2, 6),
|
||||
"functools": (2, 5),
|
||||
"future_builtins": (2, 6),
|
||||
"hashlib": (2, 5),
|
||||
"heapq": (2, 3),
|
||||
"hmac": (2, 2),
|
||||
"hotshot": (2, 2),
|
||||
"HTMLParser": (2, 2),
|
||||
"importlib": (2, 7),
|
||||
"inspect": (2, 1),
|
||||
"io": (2, 6),
|
||||
"itertools": (2, 3),
|
||||
"json": (2, 6),
|
||||
"logging": (2, 3),
|
||||
"modulefinder": (2, 3),
|
||||
"msilib": (2, 5),
|
||||
"multiprocessing": (2, 6),
|
||||
"netrc": (1, 5, 2),
|
||||
"numbers": (2, 6),
|
||||
"optparse": (2, 3),
|
||||
"ossaudiodev": (2, 3),
|
||||
"pickletools": (2, 3),
|
||||
"pkgutil": (2, 3),
|
||||
"platform": (2, 3),
|
||||
"pydoc": (2, 1),
|
||||
"runpy": (2, 5),
|
||||
"sets": (2, 3),
|
||||
"shlex": (1, 5, 2),
|
||||
"SimpleXMLRPCServer": (2, 2),
|
||||
"spwd": (2, 5),
|
||||
"sqlite3": (2, 5),
|
||||
"ssl": (2, 6),
|
||||
"stringprep": (2, 3),
|
||||
"subprocess": (2, 4),
|
||||
"sysconfig": (2, 7),
|
||||
"tarfile": (2, 3),
|
||||
"textwrap": (2, 3),
|
||||
"timeit": (2, 3),
|
||||
"unittest": (2, 1),
|
||||
"uuid": (2, 5),
|
||||
"warnings": (2, 1),
|
||||
"weakref": (2, 1),
|
||||
"winsound": (1, 5, 2),
|
||||
"wsgiref": (2, 5),
|
||||
"xml.dom": (2, 0),
|
||||
"xml.dom.minidom": (2, 0),
|
||||
"xml.dom.pulldom": (2, 0),
|
||||
"xml.etree.ElementTree": (2, 5),
|
||||
"xml.parsers.expat":(2, 0),
|
||||
"xml.sax": (2, 0),
|
||||
"xml.sax.handler": (2, 0),
|
||||
"xml.sax.saxutils": (2, 0),
|
||||
"xml.sax.xmlreader":(2, 0),
|
||||
"xmlrpclib": (2, 2),
|
||||
"zipfile": (1, 6),
|
||||
"zipimport": (2, 3),
|
||||
"_ast": (2, 5),
|
||||
"_winreg": (2, 0),
|
||||
}
|
||||
|
||||
Functions = {
|
||||
"all": (2, 5),
|
||||
"any": (2, 5),
|
||||
"collections.Counter": (2, 7),
|
||||
"collections.defaultdict": (2, 5),
|
||||
"collections.OrderedDict": (2, 7),
|
||||
"functools.total_ordering": (2, 7),
|
||||
"enumerate": (2, 3),
|
||||
"frozenset": (2, 4),
|
||||
"itertools.compress": (2, 7),
|
||||
"math.erf": (2, 7),
|
||||
"math.erfc": (2, 7),
|
||||
"math.expm1": (2, 7),
|
||||
"math.gamma": (2, 7),
|
||||
"math.lgamma": (2, 7),
|
||||
"memoryview": (2, 7),
|
||||
"next": (2, 6),
|
||||
"os.getresgid": (2, 7),
|
||||
"os.getresuid": (2, 7),
|
||||
"os.initgroups": (2, 7),
|
||||
"os.setresgid": (2, 7),
|
||||
"os.setresuid": (2, 7),
|
||||
"reversed": (2, 4),
|
||||
"set": (2, 4),
|
||||
"subprocess.check_call": (2, 5),
|
||||
"subprocess.check_output": (2, 7),
|
||||
"sum": (2, 3),
|
||||
"symtable.is_declared_global": (2, 7),
|
||||
"weakref.WeakSet": (2, 7),
|
||||
}
|
||||
|
||||
Identifiers = {
|
||||
"False": (2, 2),
|
||||
"True": (2, 2),
|
||||
}
|
||||
|
||||
def uniq(a):
|
||||
if len(a) == 0:
|
||||
return []
|
||||
else:
|
||||
return [a[0]] + uniq([x for x in a if x != a[0]])
|
||||
|
||||
class NodeChecker(object):
|
||||
def __init__(self):
|
||||
self.vers = dict()
|
||||
self.vers[(2,0)] = []
|
||||
def add(self, node, ver, msg):
|
||||
if ver not in self.vers:
|
||||
self.vers[ver] = []
|
||||
self.vers[ver].append((node.lineno, msg))
|
||||
def default(self, node):
|
||||
for child in node.getChildNodes():
|
||||
self.visit(child)
|
||||
def visitCallFunc(self, node):
|
||||
def rollup(n):
|
||||
if isinstance(n, compiler.ast.Name):
|
||||
return n.name
|
||||
elif isinstance(n, compiler.ast.Getattr):
|
||||
r = rollup(n.expr)
|
||||
if r:
|
||||
return r + "." + n.attrname
|
||||
name = rollup(node.node)
|
||||
if name:
|
||||
v = Functions.get(name)
|
||||
if v is not None:
|
||||
self.add(node, v, name)
|
||||
self.default(node)
|
||||
def visitClass(self, node):
|
||||
if node.bases:
|
||||
self.add(node, (2,2), "new-style class")
|
||||
if node.decorators:
|
||||
self.add(node, (2,6), "class decorator")
|
||||
self.default(node)
|
||||
def visitDictComp(self, node):
|
||||
self.add(node, (2,7), "dictionary comprehension")
|
||||
self.default(node)
|
||||
def visitFloorDiv(self, node):
|
||||
self.add(node, (2,2), "// operator")
|
||||
self.default(node)
|
||||
def visitFrom(self, node):
|
||||
v = StandardModules.get(node.modname)
|
||||
if v is not None:
|
||||
self.add(node, v, node.modname)
|
||||
for n in node.names:
|
||||
name = node.modname + "." + n[0]
|
||||
v = Functions.get(name)
|
||||
if v is not None:
|
||||
self.add(node, v, name)
|
||||
def visitFunction(self, node):
|
||||
if node.decorators:
|
||||
self.add(node, (2,4), "function decorator")
|
||||
self.default(node)
|
||||
def visitGenExpr(self, node):
|
||||
self.add(node, (2,4), "generator expression")
|
||||
self.default(node)
|
||||
def visitGetattr(self, node):
|
||||
if (isinstance(node.expr, compiler.ast.Const)
|
||||
and isinstance(node.expr.value, str)
|
||||
and node.attrname == "format"):
|
||||
self.add(node, (2,6), "string literal .format()")
|
||||
self.default(node)
|
||||
def visitIfExp(self, node):
|
||||
self.add(node, (2,5), "inline if expression")
|
||||
self.default(node)
|
||||
def visitImport(self, node):
|
||||
for n in node.names:
|
||||
v = StandardModules.get(n[0])
|
||||
if v is not None:
|
||||
self.add(node, v, n[0])
|
||||
self.default(node)
|
||||
def visitName(self, node):
|
||||
v = Identifiers.get(node.name)
|
||||
if v is not None:
|
||||
self.add(node, v, node.name)
|
||||
self.default(node)
|
||||
def visitSet(self, node):
|
||||
self.add(node, (2,7), "set literal")
|
||||
self.default(node)
|
||||
def visitSetComp(self, node):
|
||||
self.add(node, (2,7), "set comprehension")
|
||||
self.default(node)
|
||||
def visitTryFinally(self, node):
|
||||
# try/finally with a suite generates a Stmt node as the body,
|
||||
# but try/except/finally generates a TryExcept as the body
|
||||
if isinstance(node.body, compiler.ast.TryExcept):
|
||||
self.add(node, (2,5), "try/except/finally")
|
||||
self.default(node)
|
||||
def visitWith(self, node):
|
||||
if isinstance(node.body, compiler.ast.With):
|
||||
self.add(node, (2,7), "with statement with multiple contexts")
|
||||
else:
|
||||
self.add(node, (2,5), "with statement")
|
||||
self.default(node)
|
||||
def visitYield(self, node):
|
||||
self.add(node, (2,2), "yield expression")
|
||||
self.default(node)
|
||||
|
||||
def get_versions(source):
|
||||
"""Return information about the Python versions required for specific features.
|
||||
|
||||
The return value is a dictionary with keys as a version number as a tuple
|
||||
(for example Python 2.6 is (2,6)) and the value are a list of features that
|
||||
require the indicated Python version.
|
||||
"""
|
||||
tree = compiler.parse(source)
|
||||
checker = compiler.walk(tree, NodeChecker())
|
||||
return checker.vers
|
||||
|
||||
def v27(source):
|
||||
if sys.version_info >= (2, 7):
|
||||
return qver(source)
|
||||
else:
|
||||
print >>sys.stderr, "Not all features tested, run --test with Python 2.7"
|
||||
return (2, 7)
|
||||
|
||||
def qver(source):
|
||||
"""Return the minimum Python version required to run a particular bit of code.
|
||||
|
||||
>>> qver('print "hello world"')
|
||||
(2, 0)
|
||||
>>> qver('class test(object): pass')
|
||||
(2, 2)
|
||||
>>> qver('yield 1')
|
||||
(2, 2)
|
||||
>>> qver('a // b')
|
||||
(2, 2)
|
||||
>>> qver('True')
|
||||
(2, 2)
|
||||
>>> qver('enumerate(a)')
|
||||
(2, 3)
|
||||
>>> qver('total = sum')
|
||||
(2, 0)
|
||||
>>> qver('sum(a)')
|
||||
(2, 3)
|
||||
>>> qver('(x*x for x in range(5))')
|
||||
(2, 4)
|
||||
>>> qver('class C:\\n @classmethod\\n def m(): pass')
|
||||
(2, 4)
|
||||
>>> qver('y if x else z')
|
||||
(2, 5)
|
||||
>>> qver('import hashlib')
|
||||
(2, 5)
|
||||
>>> qver('from hashlib import md5')
|
||||
(2, 5)
|
||||
>>> qver('import xml.etree.ElementTree')
|
||||
(2, 5)
|
||||
>>> qver('try:\\n try: pass;\\n except: pass;\\nfinally: pass')
|
||||
(2, 0)
|
||||
>>> qver('try: pass;\\nexcept: pass;\\nfinally: pass')
|
||||
(2, 5)
|
||||
>>> qver('from __future__ import with_statement\\nwith x: pass')
|
||||
(2, 5)
|
||||
>>> qver('collections.defaultdict(list)')
|
||||
(2, 5)
|
||||
>>> qver('from collections import defaultdict')
|
||||
(2, 5)
|
||||
>>> qver('"{0}".format(0)')
|
||||
(2, 6)
|
||||
>>> qver('memoryview(x)')
|
||||
(2, 7)
|
||||
>>> v27('{1, 2, 3}')
|
||||
(2, 7)
|
||||
>>> v27('{x for x in s}')
|
||||
(2, 7)
|
||||
>>> v27('{x: y for x in s}')
|
||||
(2, 7)
|
||||
>>> qver('from __future__ import with_statement\\nwith x:\\n with y: pass')
|
||||
(2, 5)
|
||||
>>> v27('from __future__ import with_statement\\nwith x, y: pass')
|
||||
(2, 7)
|
||||
>>> qver('@decorator\\ndef f(): pass')
|
||||
(2, 4)
|
||||
>>> qver('@decorator\\nclass test:\\n pass')
|
||||
(2, 6)
|
||||
|
||||
#>>> qver('0o0')
|
||||
#(2, 6)
|
||||
#>>> qver('@foo\\nclass C: pass')
|
||||
#(2, 6)
|
||||
"""
|
||||
return max(get_versions(source).keys())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
Verbose = False
|
||||
MinVersion = (2, 3)
|
||||
Lint = False
|
||||
|
||||
files = []
|
||||
i = 1
|
||||
while i < len(sys.argv):
|
||||
a = sys.argv[i]
|
||||
if a == "--test":
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
sys.exit(0)
|
||||
if a == "-v" or a == "--verbose":
|
||||
Verbose = True
|
||||
elif a == "-l" or a == "--lint":
|
||||
Lint = True
|
||||
elif a == "-m" or a == "--min-version":
|
||||
i += 1
|
||||
MinVersion = tuple(map(int, sys.argv[i].split(".")))
|
||||
else:
|
||||
files.append(a)
|
||||
i += 1
|
||||
|
||||
if not files:
|
||||
print >>sys.stderr, """Usage: %s [options] source ...
|
||||
|
||||
Report minimum Python version required to run given source files.
|
||||
|
||||
-m x.y or --min-version x.y (default 2.3)
|
||||
report version triggers at or above version x.y in verbose mode
|
||||
-v or --verbose
|
||||
print more detailed report of version triggers for each version
|
||||
""" % sys.argv[0]
|
||||
sys.exit(1)
|
||||
|
||||
for fn in files:
|
||||
try:
|
||||
f = open(fn)
|
||||
source = f.read()
|
||||
f.close()
|
||||
ver = get_versions(source)
|
||||
if Verbose:
|
||||
print fn
|
||||
for v in sorted([k for k in ver.keys() if k >= MinVersion], reverse=True):
|
||||
reasons = [x for x in uniq(ver[v]) if x]
|
||||
if reasons:
|
||||
# each reason is (lineno, message)
|
||||
print "\t%s\t%s" % (".".join(map(str, v)), ", ".join([x[1] for x in reasons]))
|
||||
elif Lint:
|
||||
for v in sorted([k for k in ver.keys() if k >= MinVersion], reverse=True):
|
||||
reasons = [x for x in uniq(ver[v]) if x]
|
||||
for r in reasons:
|
||||
# each reason is (lineno, message)
|
||||
print "%s:%s: %s %s" % (fn, r[0], ".".join(map(str, v)), r[1])
|
||||
else:
|
||||
print "%s\t%s" % (".".join(map(str, max(ver.keys()))), fn)
|
||||
except SyntaxError, x:
|
||||
print "%s: syntax error compiling with Python %s: %s" % (fn, platform.python_version(), x)
|
|
@ -23,12 +23,13 @@
|
|||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##############################################################################
|
||||
import os
|
||||
from subprocess import check_call, check_output
|
||||
from subprocess import check_call
|
||||
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.filesystem import join_path
|
||||
from llnl.util.filesystem import join_path, mkdirp
|
||||
|
||||
import spack
|
||||
from spack.util.executable import which
|
||||
|
||||
description = "Create a new installation of spack in another prefix"
|
||||
|
||||
|
@ -38,8 +39,10 @@ def setup_parser(subparser):
|
|||
|
||||
def get_origin_url():
|
||||
git_dir = join_path(spack.prefix, '.git')
|
||||
origin_url = check_output(
|
||||
['git', '--git-dir=%s' % git_dir, 'config', '--get', 'remote.origin.url'])
|
||||
git = which('git', required=True)
|
||||
origin_url = git(
|
||||
'--git-dir=%s' % git_dir, 'config', '--get', 'remote.origin.url',
|
||||
return_output=True)
|
||||
return origin_url.strip()
|
||||
|
||||
|
||||
|
@ -49,6 +52,11 @@ def bootstrap(parser, args):
|
|||
|
||||
tty.msg("Fetching spack from origin: %s" % origin_url)
|
||||
|
||||
if os.path.isfile(prefix):
|
||||
tty.die("There is already a file at %s" % prefix)
|
||||
|
||||
mkdirp(prefix)
|
||||
|
||||
if os.path.exists(join_path(prefix, '.git')):
|
||||
tty.die("There already seems to be a git repository in %s" % prefix)
|
||||
|
||||
|
@ -62,10 +70,11 @@ def bootstrap(parser, args):
|
|||
"%s/lib/spack/..." % prefix)
|
||||
|
||||
os.chdir(prefix)
|
||||
check_call(['git', 'init', '--shared', '-q'])
|
||||
check_call(['git', 'remote', 'add', 'origin', origin_url])
|
||||
check_call(['git', 'fetch', 'origin', 'master:refs/remotes/origin/master', '-n', '-q'])
|
||||
check_call(['git', 'reset', '--hard', 'origin/master', '-q'])
|
||||
git = which('git', required=True)
|
||||
git('init', '--shared', '-q')
|
||||
git('remote', 'add', 'origin', origin_url)
|
||||
git('fetch', 'origin', 'master:refs/remotes/origin/master', '-n', '-q')
|
||||
git('reset', '--hard', 'origin/master', '-q')
|
||||
|
||||
tty.msg("Successfully created a new spack in %s" % prefix,
|
||||
"Run %s/bin/spack to use this installation." % prefix)
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
##############################################################################
|
||||
import os
|
||||
import re
|
||||
import argparse
|
||||
from external import argparse
|
||||
import hashlib
|
||||
from pprint import pprint
|
||||
from subprocess import CalledProcessError
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##############################################################################
|
||||
import argparse
|
||||
from external import argparse
|
||||
|
||||
import llnl.util.tty as tty
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##############################################################################
|
||||
import argparse
|
||||
from external import argparse
|
||||
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.tty.colify import colify
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##############################################################################
|
||||
import sys
|
||||
import argparse
|
||||
from external import argparse
|
||||
|
||||
import llnl.util.tty as tty
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##############################################################################
|
||||
import argparse
|
||||
from external import argparse
|
||||
|
||||
import llnl.util.tty as tty
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##############################################################################
|
||||
import argparse
|
||||
from external import argparse
|
||||
|
||||
import spack
|
||||
import spack.cmd
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
##############################################################################
|
||||
import sys
|
||||
import collections
|
||||
import argparse
|
||||
from external import argparse
|
||||
from StringIO import StringIO
|
||||
|
||||
import llnl.util.tty as tty
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##############################################################################
|
||||
import sys
|
||||
import argparse
|
||||
from external import argparse
|
||||
|
||||
import spack
|
||||
import spack.cmd
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##############################################################################
|
||||
import argparse
|
||||
from external import argparse
|
||||
import spack.modules
|
||||
|
||||
description ="Add package to environment using modules."
|
||||
|
|
|
@ -24,10 +24,10 @@
|
|||
##############################################################################
|
||||
import os
|
||||
import shutil
|
||||
import argparse
|
||||
from datetime import datetime
|
||||
from contextlib import closing
|
||||
|
||||
from external import argparse
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.tty.colify import colify
|
||||
from llnl.util.filesystem import mkdirp, join_path
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
import sys
|
||||
import os
|
||||
import shutil
|
||||
import argparse
|
||||
from external import argparse
|
||||
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.lang import partition_list
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##############################################################################
|
||||
import argparse
|
||||
from external import argparse
|
||||
|
||||
import spack.cmd
|
||||
import spack
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##############################################################################
|
||||
import os
|
||||
import argparse
|
||||
from external import argparse
|
||||
|
||||
from llnl.util.tty.colify import colify
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
import os
|
||||
import sys
|
||||
import code
|
||||
import argparse
|
||||
from external import argparse
|
||||
import platform
|
||||
from contextlib import closing
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##############################################################################
|
||||
import argparse
|
||||
from external import argparse
|
||||
import spack.cmd
|
||||
|
||||
import llnl.util.tty as tty
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##############################################################################
|
||||
import argparse
|
||||
from external import argparse
|
||||
|
||||
import spack
|
||||
import spack.cmd
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##############################################################################
|
||||
import argparse
|
||||
from external import argparse
|
||||
|
||||
import llnl.util.tty as tty
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##############################################################################
|
||||
import argparse
|
||||
from external import argparse
|
||||
import spack.modules
|
||||
|
||||
description ="Remove package from environment using module."
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##############################################################################
|
||||
import argparse
|
||||
from external import argparse
|
||||
import spack.modules
|
||||
|
||||
description ="Remove package from environment using dotkit."
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##############################################################################
|
||||
import argparse
|
||||
from external import argparse
|
||||
import spack.modules
|
||||
|
||||
description ="Add package to environment using dotkit."
|
||||
|
|
|
@ -189,7 +189,7 @@ def check(key):
|
|||
return None
|
||||
|
||||
successful = [key for key in parmap(check, checks) if key is not None]
|
||||
return { (v, p, s) : path for v, p, s, path in successful }
|
||||
return dict(((v, p, s), path) for v, p, s, path in successful)
|
||||
|
||||
@classmethod
|
||||
def find(cls, *path):
|
||||
|
|
|
@ -176,7 +176,7 @@ def compilers_for_spec(compiler_spec):
|
|||
config = _get_config()
|
||||
|
||||
def get_compiler(cspec):
|
||||
items = { k:v for k,v in config.items('compiler "%s"' % cspec) }
|
||||
items = dict((k,v) for k,v in config.items('compiler "%s"' % cspec))
|
||||
|
||||
if not all(n in items for n in _required_instance_vars):
|
||||
raise InvalidCompilerConfigurationError(cspec)
|
||||
|
|
|
@ -84,10 +84,9 @@
|
|||
import re
|
||||
import inspect
|
||||
import ConfigParser as cp
|
||||
from collections import OrderedDict
|
||||
|
||||
from external.ordereddict import OrderedDict
|
||||
from llnl.util.lang import memoized
|
||||
|
||||
import spack.error
|
||||
|
||||
__all__ = [
|
||||
|
@ -222,7 +221,6 @@ class SpackConfigParser(cp.RawConfigParser):
|
|||
"""
|
||||
# Slightly modify Python option expressions to allow leading whitespace
|
||||
OPTCRE = re.compile(r'\s*' + cp.RawConfigParser.OPTCRE.pattern)
|
||||
OPTCRE_NV = re.compile(r'\s*' + cp.RawConfigParser.OPTCRE_NV.pattern)
|
||||
|
||||
def __init__(self, file_or_files):
|
||||
cp.RawConfigParser.__init__(self, dict_type=OrderedDict)
|
||||
|
@ -341,13 +339,12 @@ def write(self, path_or_fp=None):
|
|||
|
||||
|
||||
def _read(self, fp, fpname):
|
||||
"""This is a copy of Python 2.7's _read() method, with support for
|
||||
continuation lines removed.
|
||||
"""
|
||||
"""This is a copy of Python 2.6's _read() method, with support for
|
||||
continuation lines removed."""
|
||||
cursect = None # None, or a dictionary
|
||||
optname = None
|
||||
lineno = 0
|
||||
comment = 0
|
||||
lineno = 0
|
||||
e = None # None, or an exception
|
||||
while True:
|
||||
line = fp.readline()
|
||||
|
@ -359,7 +356,6 @@ def _read(self, fp, fpname):
|
|||
(line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR")):
|
||||
self._sections["comment-%d" % comment] = line
|
||||
comment += 1
|
||||
continue
|
||||
# a section header or option header?
|
||||
else:
|
||||
# is it a section header?
|
||||
|
@ -381,13 +377,9 @@ def _read(self, fp, fpname):
|
|||
raise cp.MissingSectionHeaderError(fpname, lineno, line)
|
||||
# an option line?
|
||||
else:
|
||||
mo = self._optcre.match(line)
|
||||
mo = self.OPTCRE.match(line)
|
||||
if mo:
|
||||
optname, vi, optval = mo.group('option', 'vi', 'value')
|
||||
optname = self.optionxform(optname.rstrip())
|
||||
# This check is fine because the OPTCRE cannot
|
||||
# match if it would set optval to None
|
||||
if optval is not None:
|
||||
if vi in ('=', ':') and ';' in optval:
|
||||
# ';' is a comment delimiter only if it follows
|
||||
# a spacing character
|
||||
|
@ -398,9 +390,7 @@ def _read(self, fp, fpname):
|
|||
# allow empty values
|
||||
if optval == '""':
|
||||
optval = ''
|
||||
cursect[optname] = [optval]
|
||||
else:
|
||||
# valueless option handling
|
||||
optname = self.optionxform(optname.rstrip())
|
||||
cursect[optname] = optval
|
||||
else:
|
||||
# a non-fatal parsing error occurred. set up the
|
||||
|
@ -414,23 +404,13 @@ def _read(self, fp, fpname):
|
|||
if e:
|
||||
raise e
|
||||
|
||||
# join the multi-line values collected while reading
|
||||
all_sections = [self._defaults]
|
||||
all_sections.extend(self._sections.values())
|
||||
for options in all_sections:
|
||||
# skip comments
|
||||
if isinstance(options, basestring):
|
||||
continue
|
||||
|
||||
for name, val in options.items():
|
||||
if isinstance(val, list):
|
||||
options[name] = '\n'.join(val)
|
||||
|
||||
|
||||
def _write(self, fp):
|
||||
"""Write an .ini-format representation of the configuration state.
|
||||
|
||||
This is taken from the default Python 2.7 source. It writes 4
|
||||
This is taken from the default Python 2.6 source. It writes 4
|
||||
spaces at the beginning of lines instead of no leading space.
|
||||
"""
|
||||
if self._defaults:
|
||||
|
@ -449,11 +429,9 @@ def _write(self, fp):
|
|||
# Allow leading whitespace
|
||||
fp.write("[%s]\n" % section)
|
||||
for (key, value) in self._sections[section].items():
|
||||
if key == "__name__":
|
||||
continue
|
||||
if (value is not None) or (self._optcre == self.OPTCRE):
|
||||
key = " = ".join((key, str(value).replace('\n', '\n\t')))
|
||||
fp.write(" %s\n" % (key))
|
||||
if key != "__name__":
|
||||
fp.write(" %s = %s\n" %
|
||||
(key, str(value).replace('\n', '\n\t')))
|
||||
|
||||
|
||||
class SpackConfigurationError(spack.error.SpackError):
|
||||
|
|
|
@ -28,7 +28,8 @@ class SpackError(Exception):
|
|||
Subclasses can be found in the modules they have to do with.
|
||||
"""
|
||||
def __init__(self, message, long_message=None):
|
||||
super(SpackError, self).__init__(message)
|
||||
super(SpackError, self).__init__()
|
||||
self.message = message
|
||||
self.long_message = long_message
|
||||
|
||||
|
||||
|
|
|
@ -360,7 +360,7 @@ def sanity_check_dict(attr_name):
|
|||
|
||||
# Version-ize the keys in versions dict
|
||||
try:
|
||||
self.versions = { Version(v):h for v,h in self.versions.items() }
|
||||
self.versions = dict((Version(v), h) for v,h in self.versions.items())
|
||||
except ValueError:
|
||||
raise ValueError("Keys of versions dict in package %s must be versions!"
|
||||
% self.name)
|
||||
|
|
|
@ -72,7 +72,6 @@ class Mpileaks(Package):
|
|||
|
||||
import re
|
||||
import inspect
|
||||
import importlib
|
||||
|
||||
from llnl.util.lang import *
|
||||
|
||||
|
|
|
@ -838,7 +838,7 @@ def normalize(self, **kwargs):
|
|||
|
||||
# If there are deps specified but not visited, they're not
|
||||
# actually deps of this package. Raise an error.
|
||||
extra = set(spec_deps.viewkeys()).difference(visited)
|
||||
extra = set(spec_deps.keys()).difference(visited)
|
||||
|
||||
# Also subtract out all the packags that provide a needed vpkg
|
||||
vdeps = [v for v in self.package.virtual_dependencies()]
|
||||
|
|
|
@ -120,8 +120,7 @@ def _need_to_create_path(self):
|
|||
if spack.use_tmp_stage:
|
||||
# If we're using a tmp dir, it's a link, and it points at the right spot,
|
||||
# then keep it.
|
||||
if (os.path.commonprefix((real_path, real_tmp)) == real_tmp
|
||||
and os.path.exists(real_path)):
|
||||
if (real_path.startswith(real_tmp) and os.path.exists(real_path)):
|
||||
return False
|
||||
else:
|
||||
# otherwise, just unlink it and start over.
|
||||
|
|
|
@ -46,7 +46,8 @@
|
|||
'install',
|
||||
'package_sanity',
|
||||
'config',
|
||||
'directory_layout']
|
||||
'directory_layout',
|
||||
'python_version']
|
||||
|
||||
|
||||
def list_tests():
|
||||
|
@ -71,7 +72,7 @@ def run(names, verbose=False):
|
|||
|
||||
runner = unittest.TextTestRunner(verbosity=verbosity)
|
||||
|
||||
testsRun = errors = failures = skipped = 0
|
||||
testsRun = errors = failures = 0
|
||||
for test in names:
|
||||
module = 'spack.test.' + test
|
||||
print module
|
||||
|
@ -82,12 +83,10 @@ def run(names, verbose=False):
|
|||
testsRun += result.testsRun
|
||||
errors += len(result.errors)
|
||||
failures += len(result.failures)
|
||||
skipped += len(result.skipped)
|
||||
|
||||
succeeded = not errors and not failures
|
||||
tty.msg("Tests Complete.",
|
||||
"%5d tests run" % testsRun,
|
||||
"%5d skipped" % skipped,
|
||||
"%5d failures" % failures,
|
||||
"%5d errors" % errors)
|
||||
|
||||
|
|
|
@ -134,29 +134,29 @@ def test_concretize_with_provides_when(self):
|
|||
def test_virtual_is_fully_expanded_for_callpath(self):
|
||||
# force dependence on fake "zmpi" by asking for MPI 10.0
|
||||
spec = Spec('callpath ^mpi@10.0')
|
||||
self.assertIn('mpi', spec.dependencies)
|
||||
self.assertNotIn('fake', spec)
|
||||
self.assertTrue('mpi' in spec.dependencies)
|
||||
self.assertFalse('fake' in spec)
|
||||
|
||||
spec.concretize()
|
||||
|
||||
self.assertIn('zmpi', spec.dependencies)
|
||||
self.assertNotIn('mpi', spec)
|
||||
self.assertIn('fake', spec.dependencies['zmpi'])
|
||||
self.assertTrue('zmpi' in spec.dependencies)
|
||||
self.assertFalse('mpi' in spec)
|
||||
self.assertTrue('fake' in spec.dependencies['zmpi'])
|
||||
|
||||
|
||||
def test_virtual_is_fully_expanded_for_mpileaks(self):
|
||||
spec = Spec('mpileaks ^mpi@10.0')
|
||||
self.assertIn('mpi', spec.dependencies)
|
||||
self.assertNotIn('fake', spec)
|
||||
self.assertTrue('mpi' in spec.dependencies)
|
||||
self.assertFalse('fake' in spec)
|
||||
|
||||
spec.concretize()
|
||||
|
||||
self.assertIn('zmpi', spec.dependencies)
|
||||
self.assertIn('callpath', spec.dependencies)
|
||||
self.assertIn('zmpi', spec.dependencies['callpath'].dependencies)
|
||||
self.assertIn('fake', spec.dependencies['callpath'].dependencies['zmpi'].dependencies)
|
||||
self.assertTrue('zmpi' in spec.dependencies)
|
||||
self.assertTrue('callpath' in spec.dependencies)
|
||||
self.assertTrue('zmpi' in spec.dependencies['callpath'].dependencies)
|
||||
self.assertTrue('fake' in spec.dependencies['callpath'].dependencies['zmpi'].dependencies)
|
||||
|
||||
self.assertNotIn('mpi', spec)
|
||||
self.assertFalse('mpi' in spec)
|
||||
|
||||
|
||||
def test_my_dep_depends_on_provider_of_my_virtual_dep(self):
|
||||
|
|
|
@ -39,7 +39,6 @@ def set_pkg_dep(pkg, spec):
|
|||
|
||||
|
||||
class MockPackagesTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUp(self):
|
||||
# Use the mock packages database for these tests. This allows
|
||||
# us to set up contrived packages that don't interfere with
|
||||
|
@ -52,7 +51,7 @@ def setUp(self):
|
|||
'site' : spack.mock_site_config,
|
||||
'user' : spack.mock_user_config }
|
||||
|
||||
@classmethod
|
||||
|
||||
def tearDown(self):
|
||||
"""Restore the real packages path after any test."""
|
||||
spack.db = self.real_db
|
||||
|
|
97
lib/spack/spack/test/python_version.py
Normal file
97
lib/spack/spack/test/python_version.py
Normal file
|
@ -0,0 +1,97 @@
|
|||
##############################################################################
|
||||
# Copyright (c) 2013, Lawrence Livermore National Security, LLC.
|
||||
# Produced at the Lawrence Livermore National Laboratory.
|
||||
#
|
||||
# This file is part of Spack.
|
||||
# Written by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
|
||||
# LLNL-CODE-647188
|
||||
#
|
||||
# For details, see https://scalability-llnl.github.io/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 General Public License (as published by
|
||||
# the Free Software Foundation) version 2.1 dated 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 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
|
||||
##############################################################################
|
||||
"""
|
||||
This test ensures that all Spack files are Python version 2.6 or less.
|
||||
|
||||
Spack was originally 2.7, but enough systems in 2014 are still using
|
||||
2.6 on their frontend nodes that we need 2.6 to get adopted.
|
||||
"""
|
||||
import unittest
|
||||
import os
|
||||
import re
|
||||
from contextlib import closing
|
||||
|
||||
import llnl.util.tty as tty
|
||||
|
||||
from external import pyqver2
|
||||
import spack
|
||||
|
||||
spack_max_version = (2,6)
|
||||
|
||||
class PythonVersionTest(unittest.TestCase):
|
||||
|
||||
def spack_python_files(self):
|
||||
# first file is the spack script.
|
||||
yield spack.spack_file
|
||||
yield os.path.join(spack.build_env_path, 'cc')
|
||||
|
||||
# Next files are all the source files and package files.
|
||||
search_paths = [spack.lib_path, spack.var_path]
|
||||
|
||||
# Iterate through the whole spack source tree.
|
||||
for path in search_paths:
|
||||
for root, dirnames, filenames in os.walk(path):
|
||||
for filename in filenames:
|
||||
if re.match(r'^[^.#].*\.py$', filename):
|
||||
yield os.path.join(root, filename)
|
||||
|
||||
|
||||
def test_python_versions(self):
|
||||
# dict version -> filename -> reasons
|
||||
all_issues = {}
|
||||
|
||||
for fn in self.spack_python_files():
|
||||
with closing(open(fn)) as pyfile:
|
||||
versions = pyqver2.get_versions(pyfile.read())
|
||||
for ver, reasons in versions.items():
|
||||
if ver > spack_max_version:
|
||||
if not ver in all_issues:
|
||||
all_issues[ver] = {}
|
||||
all_issues[ver][fn] = reasons
|
||||
|
||||
if all_issues:
|
||||
tty.error("Spack must run on Python version %d.%d"
|
||||
% spack_max_version)
|
||||
|
||||
for v in sorted(all_issues.keys(), reverse=True):
|
||||
msgs = []
|
||||
for fn in sorted(all_issues[v].keys()):
|
||||
short_fn = fn
|
||||
if fn.startswith(spack.prefix):
|
||||
short_fn = fn[len(spack.prefix):]
|
||||
|
||||
reasons = [r for r in set(all_issues[v][fn]) if r]
|
||||
for r in reasons:
|
||||
msgs.append(("%s:%s" % ('spack' + short_fn, r[0]), r[1]))
|
||||
|
||||
tty.error("These files require version %d.%d:" % v)
|
||||
maxlen = max(len(f) for f, prob in msgs)
|
||||
fmt = "%%-%ds%%s" % (maxlen+3)
|
||||
print fmt % ('File', 'Reason')
|
||||
print fmt % ('-' * (maxlen), '-' * 20)
|
||||
for msg in msgs:
|
||||
print fmt % msg
|
||||
|
||||
self.assertTrue(len(all_issues) == 0)
|
|
@ -57,10 +57,10 @@ def test_preorder_node_traversal(self):
|
|||
pairs = zip([0,1,2,3,4,2,3], names)
|
||||
|
||||
traversal = dag.traverse()
|
||||
self.assertListEqual([x.name for x in traversal], names)
|
||||
self.assertEqual([x.name for x in traversal], names)
|
||||
|
||||
traversal = dag.traverse(depth=True)
|
||||
self.assertListEqual([(x, y.name) for x,y in traversal], pairs)
|
||||
self.assertEqual([(x, y.name) for x,y in traversal], pairs)
|
||||
|
||||
|
||||
def test_preorder_edge_traversal(self):
|
||||
|
@ -72,10 +72,10 @@ def test_preorder_edge_traversal(self):
|
|||
pairs = zip([0,1,2,3,4,3,2,3,1], names)
|
||||
|
||||
traversal = dag.traverse(cover='edges')
|
||||
self.assertListEqual([x.name for x in traversal], names)
|
||||
self.assertEqual([x.name for x in traversal], names)
|
||||
|
||||
traversal = dag.traverse(cover='edges', depth=True)
|
||||
self.assertListEqual([(x, y.name) for x,y in traversal], pairs)
|
||||
self.assertEqual([(x, y.name) for x,y in traversal], pairs)
|
||||
|
||||
|
||||
def test_preorder_path_traversal(self):
|
||||
|
@ -87,10 +87,10 @@ def test_preorder_path_traversal(self):
|
|||
pairs = zip([0,1,2,3,4,3,2,3,1,2], names)
|
||||
|
||||
traversal = dag.traverse(cover='paths')
|
||||
self.assertListEqual([x.name for x in traversal], names)
|
||||
self.assertEqual([x.name for x in traversal], names)
|
||||
|
||||
traversal = dag.traverse(cover='paths', depth=True)
|
||||
self.assertListEqual([(x, y.name) for x,y in traversal], pairs)
|
||||
self.assertEqual([(x, y.name) for x,y in traversal], pairs)
|
||||
|
||||
|
||||
def test_postorder_node_traversal(self):
|
||||
|
@ -102,10 +102,10 @@ def test_postorder_node_traversal(self):
|
|||
pairs = zip([4,3,2,3,2,1,0], names)
|
||||
|
||||
traversal = dag.traverse(order='post')
|
||||
self.assertListEqual([x.name for x in traversal], names)
|
||||
self.assertEqual([x.name for x in traversal], names)
|
||||
|
||||
traversal = dag.traverse(depth=True, order='post')
|
||||
self.assertListEqual([(x, y.name) for x,y in traversal], pairs)
|
||||
self.assertEqual([(x, y.name) for x,y in traversal], pairs)
|
||||
|
||||
|
||||
def test_postorder_edge_traversal(self):
|
||||
|
@ -117,10 +117,10 @@ def test_postorder_edge_traversal(self):
|
|||
pairs = zip([4,3,3,2,3,2,1,1,0], names)
|
||||
|
||||
traversal = dag.traverse(cover='edges', order='post')
|
||||
self.assertListEqual([x.name for x in traversal], names)
|
||||
self.assertEqual([x.name for x in traversal], names)
|
||||
|
||||
traversal = dag.traverse(cover='edges', depth=True, order='post')
|
||||
self.assertListEqual([(x, y.name) for x,y in traversal], pairs)
|
||||
self.assertEqual([(x, y.name) for x,y in traversal], pairs)
|
||||
|
||||
|
||||
def test_postorder_path_traversal(self):
|
||||
|
@ -132,10 +132,10 @@ def test_postorder_path_traversal(self):
|
|||
pairs = zip([4,3,3,2,3,2,1,2,1,0], names)
|
||||
|
||||
traversal = dag.traverse(cover='paths', order='post')
|
||||
self.assertListEqual([x.name for x in traversal], names)
|
||||
self.assertEqual([x.name for x in traversal], names)
|
||||
|
||||
traversal = dag.traverse(cover='paths', depth=True, order='post')
|
||||
self.assertListEqual([(x, y.name) for x,y in traversal], pairs)
|
||||
self.assertEqual([(x, y.name) for x,y in traversal], pairs)
|
||||
|
||||
|
||||
def test_conflicting_spec_constraints(self):
|
||||
|
@ -199,13 +199,13 @@ def test_normalize_with_virtual_spec(self):
|
|||
def check_links(self, spec_to_check):
|
||||
for spec in spec_to_check.traverse():
|
||||
for dependent in spec.dependents.values():
|
||||
self.assertIn(
|
||||
spec.name, dependent.dependencies,
|
||||
self.assertTrue(
|
||||
spec.name in dependent.dependencies,
|
||||
"%s not in dependencies of %s" % (spec.name, dependent.name))
|
||||
|
||||
for dependency in spec.dependencies.values():
|
||||
self.assertIn(
|
||||
spec.name, dependency.dependents,
|
||||
self.assertTrue(
|
||||
spec.name in dependency.dependents,
|
||||
"%s not in dependents of %s" % (spec.name, dependency.name))
|
||||
|
||||
|
||||
|
@ -385,13 +385,13 @@ def test_normalize_with_virtual_package(self):
|
|||
|
||||
def test_contains(self):
|
||||
spec = Spec('mpileaks ^mpi ^libelf@1.8.11 ^libdwarf')
|
||||
self.assertIn(Spec('mpi'), spec)
|
||||
self.assertIn(Spec('libelf'), spec)
|
||||
self.assertIn(Spec('libelf@1.8.11'), spec)
|
||||
self.assertNotIn(Spec('libelf@1.8.12'), spec)
|
||||
self.assertIn(Spec('libdwarf'), spec)
|
||||
self.assertNotIn(Spec('libgoblin'), spec)
|
||||
self.assertIn(Spec('mpileaks'), spec)
|
||||
self.assertTrue(Spec('mpi') in spec)
|
||||
self.assertTrue(Spec('libelf') in spec)
|
||||
self.assertTrue(Spec('libelf@1.8.11') in spec)
|
||||
self.assertFalse(Spec('libelf@1.8.12') in spec)
|
||||
self.assertTrue(Spec('libdwarf') in spec)
|
||||
self.assertFalse(Spec('libgoblin') in spec)
|
||||
self.assertTrue(Spec('mpileaks') in spec)
|
||||
|
||||
|
||||
def test_copy_simple(self):
|
||||
|
|
|
@ -51,28 +51,20 @@
|
|||
stage_name = 'spack-test-stage'
|
||||
|
||||
|
||||
class with_tmp(object):
|
||||
"""Decorator that executes a function with or without spack set to use
|
||||
a temp dir. Spack allows builds to happen directly in the
|
||||
stage directory or in a tmp dir and symlinked into the stage
|
||||
directory, so this lets us use the same test in both cases.
|
||||
@contextmanager
|
||||
def use_tmp(use_tmp):
|
||||
"""Allow some test code to be executed with spack.use_tmp_stage
|
||||
set to a certain value. Context manager makes sure it's reset
|
||||
on failure.
|
||||
"""
|
||||
def __init__(self, use_tmp):
|
||||
self.use_tmp = use_tmp
|
||||
|
||||
def __call__(self, fun):
|
||||
use_tmp = self.use_tmp
|
||||
def new_test_function(self):
|
||||
old_tmp = spack.use_tmp_stage
|
||||
spack.use_tmp_stage = use_tmp
|
||||
fun(self)
|
||||
yield
|
||||
spack.use_tmp_stage = old_tmp
|
||||
return new_test_function
|
||||
|
||||
|
||||
class StageTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
def setUp(self):
|
||||
"""This sets up a mock archive to fetch, and a mock temp space for use
|
||||
by the Stage class. It doesn't actually create the Stage -- that
|
||||
is done by individual tests.
|
||||
|
@ -92,52 +84,58 @@ def setUpClass(cls):
|
|||
tar('czf', archive_name, archive_dir)
|
||||
|
||||
# Make spack use the test environment for tmp stuff.
|
||||
cls.old_tmp_dirs = spack.tmp_dirs
|
||||
self.old_tmp_dirs = spack.tmp_dirs
|
||||
spack.tmp_dirs = [test_tmp_path]
|
||||
|
||||
# record this since this test changes to directories that will
|
||||
# be removed.
|
||||
self.working_dir = os.getcwd()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
|
||||
def tearDown(self):
|
||||
"""Blows away the test environment directory."""
|
||||
shutil.rmtree(test_files_dir)
|
||||
|
||||
# chdir back to original working dir
|
||||
os.chdir(self.working_dir)
|
||||
|
||||
# restore spack's original tmp environment
|
||||
spack.tmp_dirs = cls.old_tmp_dirs
|
||||
spack.tmp_dirs = self.old_tmp_dirs
|
||||
|
||||
|
||||
def get_stage_path(self, stage, stage_name):
|
||||
"""Figure out based on a stage and an intended name where it should
|
||||
be living. This depends on whether it's named or not.
|
||||
"""Figure out where a stage should be living. This depends on
|
||||
whether it's named.
|
||||
"""
|
||||
if stage_name:
|
||||
if stage_name is not None:
|
||||
# If it is a named stage, we know where the stage should be
|
||||
stage_path = join_path(spack.stage_path, stage_name)
|
||||
return join_path(spack.stage_path, stage_name)
|
||||
else:
|
||||
# If it's unnamed, ensure that we ran mkdtemp in the right spot.
|
||||
stage_path = stage.path
|
||||
self.assertIsNotNone(stage_path)
|
||||
self.assertEqual(
|
||||
os.path.commonprefix((stage_path, spack.stage_path)),
|
||||
spack.stage_path)
|
||||
return stage_path
|
||||
self.assertTrue(stage.path is not None)
|
||||
self.assertTrue(stage.path.startswith(spack.stage_path))
|
||||
return stage.path
|
||||
|
||||
|
||||
def check_setup(self, stage, stage_name):
|
||||
"""Figure out whether a stage was set up correctly."""
|
||||
stage_path = self.get_stage_path(stage, stage_name)
|
||||
|
||||
# Ensure stage was created in the spack stage directory
|
||||
self.assertTrue(os.path.isdir(stage_path))
|
||||
|
||||
if spack.use_tmp_stage:
|
||||
# Make sure everything was created and linked correctly for
|
||||
# a tmp stage.
|
||||
# Check that the stage dir is really a symlink.
|
||||
self.assertTrue(os.path.islink(stage_path))
|
||||
|
||||
# Make sure it points to a valid directory
|
||||
target = os.path.realpath(stage_path)
|
||||
self.assertTrue(os.path.isdir(target))
|
||||
self.assertFalse(os.path.islink(target))
|
||||
self.assertEqual(
|
||||
os.path.commonprefix((target, test_tmp_path)),
|
||||
test_tmp_path)
|
||||
|
||||
# Make sure the directory is in the place we asked it to
|
||||
# be (see setUp and tearDown)
|
||||
self.assertTrue(target.startswith(test_tmp_path))
|
||||
|
||||
else:
|
||||
# Make sure the stage path is NOT a link for a non-tmp stage
|
||||
|
@ -146,15 +144,15 @@ def check_setup(self, stage, stage_name):
|
|||
|
||||
def check_fetch(self, stage, stage_name):
|
||||
stage_path = self.get_stage_path(stage, stage_name)
|
||||
self.assertIn(archive_name, os.listdir(stage_path))
|
||||
self.assertTrue(archive_name in os.listdir(stage_path))
|
||||
self.assertEqual(join_path(stage_path, archive_name),
|
||||
stage.archive_file)
|
||||
|
||||
|
||||
def check_expand_archive(self, stage, stage_name):
|
||||
stage_path = self.get_stage_path(stage, stage_name)
|
||||
self.assertIn(archive_name, os.listdir(stage_path))
|
||||
self.assertIn(archive_dir, os.listdir(stage_path))
|
||||
self.assertTrue(archive_name in os.listdir(stage_path))
|
||||
self.assertTrue(archive_dir in os.listdir(stage_path))
|
||||
|
||||
self.assertEqual(
|
||||
join_path(stage_path, archive_dir),
|
||||
|
@ -192,7 +190,8 @@ def check_destroy(self, stage, stage_name):
|
|||
self.assertFalse(os.path.exists(target))
|
||||
|
||||
|
||||
def checkSetupAndDestroy(self, stage_name=None):
|
||||
def test_setup_and_destroy_name_with_tmp(self):
|
||||
with use_tmp(True):
|
||||
stage = Stage(archive_url, name=stage_name)
|
||||
self.check_setup(stage, stage_name)
|
||||
|
||||
|
@ -200,24 +199,31 @@ def checkSetupAndDestroy(self, stage_name=None):
|
|||
self.check_destroy(stage, stage_name)
|
||||
|
||||
|
||||
@with_tmp(True)
|
||||
def test_setup_and_destroy_name_with_tmp(self):
|
||||
self.checkSetupAndDestroy(stage_name)
|
||||
|
||||
|
||||
@with_tmp(False)
|
||||
def test_setup_and_destroy_name_without_tmp(self):
|
||||
self.checkSetupAndDestroy(stage_name)
|
||||
with use_tmp(False):
|
||||
stage = Stage(archive_url, name=stage_name)
|
||||
self.check_setup(stage, stage_name)
|
||||
|
||||
stage.destroy()
|
||||
self.check_destroy(stage, stage_name)
|
||||
|
||||
|
||||
@with_tmp(True)
|
||||
def test_setup_and_destroy_no_name_with_tmp(self):
|
||||
self.checkSetupAndDestroy(None)
|
||||
with use_tmp(True):
|
||||
stage = Stage(archive_url)
|
||||
self.check_setup(stage, None)
|
||||
|
||||
stage.destroy()
|
||||
self.check_destroy(stage, None)
|
||||
|
||||
|
||||
@with_tmp(False)
|
||||
def test_setup_and_destroy_no_name_without_tmp(self):
|
||||
self.checkSetupAndDestroy(None)
|
||||
with use_tmp(False):
|
||||
stage = Stage(archive_url)
|
||||
self.check_setup(stage, None)
|
||||
|
||||
stage.destroy()
|
||||
self.check_destroy(stage, None)
|
||||
|
||||
|
||||
def test_chdir(self):
|
||||
|
@ -286,7 +292,7 @@ def test_restage(self):
|
|||
with closing(open('foobar', 'w')) as file:
|
||||
file.write("this file is to be destroyed.")
|
||||
|
||||
self.assertIn('foobar', os.listdir(stage.expanded_archive_path))
|
||||
self.assertTrue('foobar' in os.listdir(stage.expanded_archive_path))
|
||||
|
||||
# Make sure the file is not there after restage.
|
||||
stage.restage()
|
||||
|
@ -295,7 +301,7 @@ def test_restage(self):
|
|||
|
||||
stage.chdir_to_archive()
|
||||
self.check_chdir_to_archive(stage, stage_name)
|
||||
self.assertNotIn('foobar', os.listdir(stage.expanded_archive_path))
|
||||
self.assertFalse('foobar' in os.listdir(stage.expanded_archive_path))
|
||||
|
||||
stage.destroy()
|
||||
self.check_destroy(stage, stage_name)
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
hashlib.sha512 ]
|
||||
|
||||
"""Index for looking up hasher for a digest."""
|
||||
_size_to_hash = { h().digest_size : h for h in _acceptable_hashes }
|
||||
_size_to_hash = dict((h().digest_size, h) for h in _acceptable_hashes)
|
||||
|
||||
|
||||
def checksum(hashlib_algo, filename, **kwargs):
|
||||
|
|
|
@ -47,7 +47,8 @@
|
|||
import sys
|
||||
import re
|
||||
from bisect import bisect_left
|
||||
from functools import total_ordering, wraps
|
||||
from functools import wraps
|
||||
from external.functools import total_ordering
|
||||
|
||||
import llnl.util.compare.none_high as none_high
|
||||
import llnl.util.compare.none_low as none_low
|
||||
|
|
Loading…
Reference in a new issue