summaryrefslogtreecommitdiff
path: root/lib/spack/llnl/util/lang.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/spack/llnl/util/lang.py')
-rw-r--r--lib/spack/llnl/util/lang.py198
1 files changed, 99 insertions, 99 deletions
diff --git a/lib/spack/llnl/util/lang.py b/lib/spack/llnl/util/lang.py
index 463310b7a2..314566e97a 100644
--- a/lib/spack/llnl/util/lang.py
+++ b/lib/spack/llnl/util/lang.py
@@ -21,7 +21,7 @@ from six import string_types
from llnl.util.compat import MutableMapping, MutableSequence, zip_longest
# Ignore emacs backups when listing modules
-ignore_modules = [r'^\.#', '~$']
+ignore_modules = [r"^\.#", "~$"]
def index_by(objects, *funcs):
@@ -91,9 +91,9 @@ def index_by(objects, *funcs):
def caller_locals():
"""This will return the locals of the *parent* of the caller.
- This allows a function to insert variables into its caller's
- scope. Yes, this is some black magic, and yes it's useful
- for implementing things like depends_on and provides.
+ This allows a function to insert variables into its caller's
+ scope. Yes, this is some black magic, and yes it's useful
+ for implementing things like depends_on and provides.
"""
# Passing zero here skips line context for speed.
stack = inspect.stack(0)
@@ -105,7 +105,7 @@ def caller_locals():
def get_calling_module_name():
"""Make sure that the caller is a class definition, and return the
- enclosing module's name.
+ enclosing module's name.
"""
# Passing zero here skips line context for speed.
stack = inspect.stack(0)
@@ -115,12 +115,13 @@ def get_calling_module_name():
finally:
del stack
- if '__module__' not in caller_locals:
- raise RuntimeError("Must invoke get_calling_module_name() "
- "from inside a class definition!")
+ if "__module__" not in caller_locals:
+ raise RuntimeError(
+ "Must invoke get_calling_module_name() " "from inside a class definition!"
+ )
- module_name = caller_locals['__module__']
- base_name = module_name.split('.')[-1]
+ module_name = caller_locals["__module__"]
+ base_name = module_name.split(".")[-1]
return base_name
@@ -128,8 +129,8 @@ def attr_required(obj, attr_name):
"""Ensure that a class has a required attribute."""
if not hasattr(obj, attr_name):
raise RequiredAttributeError(
- "No required attribute '%s' in class '%s'"
- % (attr_name, obj.__class__.__name__))
+ "No required attribute '%s' in class '%s'" % (attr_name, obj.__class__.__name__)
+ )
def attr_setdefault(obj, name, value):
@@ -201,33 +202,35 @@ def memoized(func):
# TypeError is raised when indexing into a dict if the key is unhashable.
raise six.raise_from(
UnhashableArguments(
- "args + kwargs '{}' was not hashable for function '{}'"
- .format(key, func.__name__),
+ "args + kwargs '{}' was not hashable for function '{}'".format(
+ key, func.__name__
+ ),
),
- e)
+ e,
+ )
return _memoized_function
def list_modules(directory, **kwargs):
"""Lists all of the modules, excluding ``__init__.py``, in a
- particular directory. Listed packages have no particular
- order."""
- list_directories = kwargs.setdefault('directories', True)
+ particular directory. Listed packages have no particular
+ order."""
+ list_directories = kwargs.setdefault("directories", True)
for name in os.listdir(directory):
- if name == '__init__.py':
+ if name == "__init__.py":
continue
path = os.path.join(directory, name)
if list_directories and os.path.isdir(path):
- init_py = os.path.join(path, '__init__.py')
+ init_py = os.path.join(path, "__init__.py")
if os.path.isfile(init_py):
yield name
- elif name.endswith('.py'):
+ elif name.endswith(".py"):
if not any(re.search(pattern, name) for pattern in ignore_modules):
- yield re.sub('.py$', '', name)
+ yield re.sub(".py$", "", name)
def decorator_with_or_without_args(decorator):
@@ -257,41 +260,34 @@ def decorator_with_or_without_args(decorator):
def key_ordering(cls):
"""Decorates a class with extra methods that implement rich comparison
- operations and ``__hash__``. The decorator assumes that the class
- implements a function called ``_cmp_key()``. The rich comparison
- operations will compare objects using this key, and the ``__hash__``
- function will return the hash of this key.
+ operations and ``__hash__``. The decorator assumes that the class
+ implements a function called ``_cmp_key()``. The rich comparison
+ operations will compare objects using this key, and the ``__hash__``
+ function will return the hash of this key.
- If a class already has ``__eq__``, ``__ne__``, ``__lt__``, ``__le__``,
- ``__gt__``, or ``__ge__`` defined, this decorator will overwrite them.
+ If a class already has ``__eq__``, ``__ne__``, ``__lt__``, ``__le__``,
+ ``__gt__``, or ``__ge__`` defined, this decorator will overwrite them.
- Raises:
- TypeError: If the class does not have a ``_cmp_key`` method
+ Raises:
+ TypeError: If the class does not have a ``_cmp_key`` method
"""
+
def setter(name, value):
value.__name__ = name
setattr(cls, 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__)
- setter('__eq__',
- lambda s, o:
- (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("__eq__", lambda s, o: (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('__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("__ne__", lambda s, o: (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()))
return cls
@@ -458,8 +454,7 @@ def lazy_lexicographic_ordering(cls, set_hash=True):
def le(self, other):
if self is other:
return True
- return (other is not None) and not lazy_lt(other._cmp_iter,
- self._cmp_iter)
+ return (other is not None) and not lazy_lt(other._cmp_iter, self._cmp_iter)
def ge(self, other):
if self is other:
@@ -489,7 +484,7 @@ def lazy_lexicographic_ordering(cls, set_hash=True):
@lazy_lexicographic_ordering
class HashableMap(MutableMapping):
"""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 __init__(self):
self.dict = {}
@@ -527,7 +522,7 @@ class HashableMap(MutableMapping):
def in_function(function_name):
"""True if the caller was called from some function with
- the supplied Name, False otherwise."""
+ the supplied Name, False otherwise."""
stack = inspect.stack()
try:
for elt in stack[2:]:
@@ -540,24 +535,25 @@ def in_function(function_name):
def check_kwargs(kwargs, fun):
"""Helper for making functions with kwargs. Checks whether the kwargs
- are empty after all of them have been popped off. If they're
- not, raises an error describing which kwargs are invalid.
+ are empty after all of them have been popped off. If they're
+ not, raises an error describing which kwargs are invalid.
- Example::
+ Example::
- def foo(self, **kwargs):
- x = kwargs.pop('x', None)
- y = kwargs.pop('y', None)
- z = kwargs.pop('z', None)
- check_kwargs(kwargs, self.foo)
+ def foo(self, **kwargs):
+ x = kwargs.pop('x', None)
+ y = kwargs.pop('y', None)
+ z = kwargs.pop('z', None)
+ check_kwargs(kwargs, self.foo)
- # This raises a TypeError:
- foo(w='bad kwarg')
+ # This raises a TypeError:
+ foo(w='bad kwarg')
"""
if kwargs:
raise TypeError(
"'%s' is an invalid keyword argument for function %s()."
- % (next(iter(kwargs)), fun.__name__))
+ % (next(iter(kwargs)), fun.__name__)
+ )
def match_predicate(*args):
@@ -573,6 +569,7 @@ def match_predicate(*args):
* any regex in a list or tuple of regexes matches.
* any predicate in args matches.
"""
+
def match(string):
for arg in args:
if isinstance(arg, string_types):
@@ -585,9 +582,11 @@ def match_predicate(*args):
if arg(string):
return True
else:
- raise ValueError("args to match_predicate must be regex, "
- "list of regexes, or callable.")
+ raise ValueError(
+ "args to match_predicate must be regex, " "list of regexes, or callable."
+ )
return False
+
return match
@@ -647,7 +646,7 @@ def pretty_date(time, now=None):
day_diff = diff.days
if day_diff < 0:
- return ''
+ return ""
if day_diff == 0:
if second_diff < 10:
@@ -705,43 +704,40 @@ def pretty_string_to_date(date_str, now=None):
now = now or datetime.now()
# datetime formats
- pattern[re.compile(r'^\d{4}$')] = lambda x: datetime.strptime(x, '%Y')
- pattern[re.compile(r'^\d{4}-\d{2}$')] = lambda x: datetime.strptime(
- x, '%Y-%m'
+ pattern[re.compile(r"^\d{4}$")] = lambda x: datetime.strptime(x, "%Y")
+ pattern[re.compile(r"^\d{4}-\d{2}$")] = lambda x: datetime.strptime(x, "%Y-%m")
+ pattern[re.compile(r"^\d{4}-\d{2}-\d{2}$")] = lambda x: datetime.strptime(x, "%Y-%m-%d")
+ pattern[re.compile(r"^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$")] = lambda x: datetime.strptime(
+ x, "%Y-%m-%d %H:%M"
)
- pattern[re.compile(r'^\d{4}-\d{2}-\d{2}$')] = lambda x: datetime.strptime(
- x, '%Y-%m-%d'
+ pattern[re.compile(r"^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$")] = lambda x: datetime.strptime(
+ x, "%Y-%m-%d %H:%M:%S"
)
- pattern[re.compile(r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$')] = \
- lambda x: datetime.strptime(x, '%Y-%m-%d %H:%M')
- pattern[re.compile(r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$')] = \
- lambda x: datetime.strptime(x, '%Y-%m-%d %H:%M:%S')
- pretty_regex = re.compile(
- r'(a|\d+)\s*(year|month|week|day|hour|minute|second)s?\s*ago')
+ pretty_regex = re.compile(r"(a|\d+)\s*(year|month|week|day|hour|minute|second)s?\s*ago")
def _n_xxx_ago(x):
how_many, time_period = pretty_regex.search(x).groups()
- how_many = 1 if how_many == 'a' else int(how_many)
+ how_many = 1 if how_many == "a" else int(how_many)
# timedelta natively supports time periods up to 'weeks'.
# To apply month or year we convert to 30 and 365 days
- if time_period == 'month':
+ if time_period == "month":
how_many *= 30
- time_period = 'day'
- elif time_period == 'year':
+ time_period = "day"
+ elif time_period == "year":
how_many *= 365
- time_period = 'day'
+ time_period = "day"
- kwargs = {(time_period + 's'): how_many}
+ kwargs = {(time_period + "s"): how_many}
return now - timedelta(**kwargs)
pattern[pretty_regex] = _n_xxx_ago
# yesterday
callback = lambda x: now - timedelta(days=1)
- pattern[re.compile('^yesterday$')] = callback
+ pattern[re.compile("^yesterday$")] = callback
for regexp, parser in pattern.items():
if bool(regexp.match(date_str)):
@@ -752,7 +748,6 @@ def pretty_string_to_date(date_str, now=None):
class RequiredAttributeError(ValueError):
-
def __init__(self, message):
super(RequiredAttributeError, self).__init__(message)
@@ -764,6 +759,7 @@ class ObjectWrapper(object):
This class is modeled after the stackoverflow answer:
* http://stackoverflow.com/a/1445289/771663
"""
+
def __init__(self, wrapped_object):
wrapped_cls = type(wrapped_object)
wrapped_name = wrapped_cls.__name__
@@ -807,7 +803,7 @@ class Singleton(object):
# requested but not yet set. The final 'getattr' line here requires
# 'instance'/'_instance' to be defined or it will enter an infinite
# loop, so protect against that here.
- if name in ['_instance', 'instance']:
+ if name in ["_instance", "instance"]:
raise AttributeError()
return getattr(self.instance, name)
@@ -837,7 +833,7 @@ class LazyReference(object):
self.ref_function = ref_function
def __getattr__(self, name):
- if name == 'ref_function':
+ if name == "ref_function":
raise AttributeError()
return getattr(self.ref_function(), name)
@@ -875,8 +871,8 @@ def load_module_from_file(module_name, module_path):
# This recipe is adapted from https://stackoverflow.com/a/67692/771663
if sys.version_info[0] == 3 and sys.version_info[1] >= 5:
import importlib.util
- spec = importlib.util.spec_from_file_location( # novm
- module_name, module_path)
+
+ spec = importlib.util.spec_from_file_location(module_name, module_path) # novm
module = importlib.util.module_from_spec(spec) # novm
# The module object needs to exist in sys.modules before the
# loader executes the module code.
@@ -893,6 +889,7 @@ def load_module_from_file(module_name, module_path):
raise
elif sys.version_info[0] == 2:
import imp
+
module = imp.load_source(module_name, module_path)
return module
@@ -924,8 +921,10 @@ def uniq(sequence):
def star(func):
"""Unpacks arguments for use with Multiprocessing mapping functions"""
+
def _wrapper(args):
return func(*args)
+
return _wrapper
@@ -934,22 +933,23 @@ class Devnull(object):
See https://stackoverflow.com/a/2929954.
"""
+
def write(self, *_):
pass
def elide_list(line_list, max_num=10):
"""Takes a long list and limits it to a smaller number of elements,
- replacing intervening elements with '...'. For example::
+ replacing intervening elements with '...'. For example::
- elide_list([1,2,3,4,5,6], 4)
+ elide_list([1,2,3,4,5,6], 4)
- gives::
+ gives::
- [1, 2, 3, '...', 6]
+ [1, 2, 3, '...', 6]
"""
if len(line_list) > max_num:
- return line_list[:max_num - 1] + ['...'] + line_list[-1:]
+ return line_list[: max_num - 1] + ["..."] + line_list[-1:]
else:
return line_list
@@ -972,7 +972,7 @@ def enum(**kwargs):
Args:
**kwargs: explicit dictionary of enums
"""
- return type('Enum', (object,), kwargs)
+ return type("Enum", (object,), kwargs)
class TypedMutableSequence(MutableSequence):
@@ -988,6 +988,7 @@ class TypedMutableSequence(MutableSequence):
if isinstance(l, Foo):
# do something
"""
+
def __init__(self, iterable):
self.data = list(iterable)
@@ -1017,7 +1018,7 @@ class GroupedExceptionHandler(object):
"""A generic mechanism to coalesce multiple exceptions and preserve tracebacks."""
def __init__(self):
- self.exceptions = [] # type: List[Tuple[str, Exception, List[str]]]
+ self.exceptions = [] # type: List[Tuple[str, Exception, List[str]]]
def __bool__(self):
"""Whether any exceptions were handled."""
@@ -1036,17 +1037,15 @@ class GroupedExceptionHandler(object):
# type: (bool) -> str
"""Print out an error message coalescing all the forwarded errors."""
each_exception_message = [
- '{0} raised {1}: {2}{3}'.format(
+ "{0} raised {1}: {2}{3}".format(
context,
exc.__class__.__name__,
exc,
- '\n{0}'.format(''.join(tb)) if with_tracebacks else '',
+ "\n{0}".format("".join(tb)) if with_tracebacks else "",
)
for context, exc, tb in self.exceptions
]
- return 'due to the following failures:\n{0}'.format(
- '\n'.join(each_exception_message)
- )
+ return "due to the following failures:\n{0}".format("\n".join(each_exception_message))
class GroupedExceptionForwarder(object):
@@ -1079,6 +1078,7 @@ class classproperty(object):
the evaluation is injected at creation time and take an instance (could be None) and
an owner (i.e. the class that originated the instance)
"""
+
def __init__(self, callback):
self.callback = callback