summaryrefslogtreecommitdiff
path: root/lib/spack/spack/spec.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/spack/spack/spec.py')
-rw-r--r--lib/spack/spack/spec.py154
1 files changed, 78 insertions, 76 deletions
diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py
index c92594da72..ba9cea876d 100644
--- a/lib/spack/spack/spec.py
+++ b/lib/spack/spack/spec.py
@@ -123,6 +123,39 @@ from spack.util.spack_yaml import syaml_dict
from spack.version import *
from spack.provider_index import ProviderIndex
+__all__ = [
+ 'Spec',
+ 'alldeps',
+ 'nolink',
+ 'nobuild',
+ 'canonical_deptype',
+ 'validate_deptype',
+ 'parse',
+ 'parse_anonymous_spec',
+ 'SpecError',
+ 'SpecParseError',
+ 'DuplicateDependencyError',
+ 'DuplicateVariantError',
+ 'DuplicateCompilerSpecError',
+ 'UnsupportedCompilerError',
+ 'UnknownVariantError',
+ 'DuplicateArchitectureError',
+ 'InconsistentSpecError',
+ 'InvalidDependencyError',
+ 'InvalidDependencyTypeError',
+ 'NoProviderError',
+ 'MultipleProviderError',
+ 'UnsatisfiableSpecError',
+ 'UnsatisfiableSpecNameError',
+ 'UnsatisfiableVersionSpecError',
+ 'UnsatisfiableCompilerSpecError',
+ 'UnsatisfiableVariantSpecError',
+ 'UnsatisfiableCompilerFlagSpecError',
+ 'UnsatisfiableArchitectureSpecError',
+ 'UnsatisfiableProviderSpecError',
+ 'UnsatisfiableDependencySpecError',
+ 'SpackYAMLError',
+ 'AmbiguousHashError']
# Valid pattern for an identifier in Spack
identifier_re = r'\w[\w-]*'
@@ -156,12 +189,46 @@ _any_version = VersionList([':'])
# Special types of dependencies.
alldeps = ('build', 'link', 'run')
-nolink = ('build', 'run')
+nolink = ('build', 'run')
+nobuild = ('link', 'run')
+norun = ('link', 'build')
special_types = {
'alldeps': alldeps,
+ 'all': alldeps, # allow "all" as string but not symbol.
'nolink': nolink,
+ 'nobuild': nobuild,
+ 'norun': norun,
}
+legal_deps = tuple(special_types) + alldeps
+
+
+def validate_deptype(deptype):
+ if isinstance(deptype, str):
+ if deptype not in legal_deps:
+ raise InvalidDependencyTypeError(
+ "Invalid dependency type: %s" % deptype)
+
+ elif isinstance(deptype, (list, tuple)):
+ for t in deptype:
+ validate_deptype(t)
+
+ elif deptype is None:
+ raise InvalidDependencyTypeError("deptype cannot be None!")
+
+
+def canonical_deptype(deptype):
+ if deptype is None:
+ return alldeps
+
+ elif isinstance(deptype, str):
+ return special_types.get(deptype, (deptype,))
+
+ elif isinstance(deptype, (tuple, list)):
+ return (sum((canonical_deptype(d) for d in deptype), ()))
+
+ return deptype
+
def colorize_spec(spec):
"""Returns a spec colorized according to the colors specified in
@@ -542,17 +609,8 @@ class Spec(object):
raise InvalidDependencyException(
self.name + " does not depend on " + comma_or(name))
- def _deptype_norm(self, deptype):
- if deptype is None:
- return alldeps
- # Force deptype to be a set object so that we can do set intersections.
- if isinstance(deptype, str):
- # Support special deptypes.
- return special_types.get(deptype, (deptype,))
- return deptype
-
def _find_deps(self, where, deptype):
- deptype = self._deptype_norm(deptype)
+ deptype = canonical_deptype(deptype)
return [dep.spec
for dep in where.values()
@@ -565,7 +623,7 @@ class Spec(object):
return self._find_deps(self._dependents, deptype)
def _find_deps_dict(self, where, deptype):
- deptype = self._deptype_norm(deptype)
+ deptype = canonical_deptype(deptype)
return dict((dep.spec.name, dep)
for dep in where.values()
@@ -1361,12 +1419,11 @@ class Spec(object):
# parser doesn't allow it. Spack must be broken!
raise InconsistentSpecError("Invalid Spec DAG: %s" % e.message)
- def index(self):
+ def index(self, deptype=None):
"""Return DependencyMap that points to all the dependencies in this
spec."""
dm = DependencyMap()
- # XXX(deptype): use a deptype kwarg.
- for spec in self.traverse():
+ for spec in self.traverse(deptype=deptype):
dm[spec.name] = spec
return dm
@@ -1569,7 +1626,7 @@ class Spec(object):
# actually deps of this package. Raise an error.
extra = set(spec_deps.keys()).difference(visited)
if extra:
- raise InvalidDependencyException(
+ raise InvalidDependencyError(
self.name + " does not depend on " + comma_or(extra))
# Mark the spec as normal once done.
@@ -2667,17 +2724,11 @@ def parse_anonymous_spec(spec_like, pkg_name):
class SpecError(spack.error.SpackError):
-
"""Superclass for all errors that occur while constructing specs."""
- def __init__(self, message):
- super(SpecError, self).__init__(message)
-
class SpecParseError(SpecError):
-
"""Wrapper for ParseError for when we're parsing specs."""
-
def __init__(self, parse_error):
super(SpecParseError, self).__init__(parse_error.message)
self.string = parse_error.string
@@ -2685,79 +2736,53 @@ class SpecParseError(SpecError):
class DuplicateDependencyError(SpecError):
-
"""Raised when the same dependency occurs in a spec twice."""
- def __init__(self, message):
- super(DuplicateDependencyError, self).__init__(message)
-
class DuplicateVariantError(SpecError):
-
"""Raised when the same variant occurs in a spec twice."""
- def __init__(self, message):
- super(DuplicateVariantError, self).__init__(message)
-
class DuplicateCompilerSpecError(SpecError):
-
"""Raised when the same compiler occurs in a spec twice."""
- def __init__(self, message):
- super(DuplicateCompilerSpecError, self).__init__(message)
-
class UnsupportedCompilerError(SpecError):
-
"""Raised when the user asks for a compiler spack doesn't know about."""
-
def __init__(self, compiler_name):
super(UnsupportedCompilerError, self).__init__(
"The '%s' compiler is not yet supported." % compiler_name)
class UnknownVariantError(SpecError):
-
"""Raised when the same variant occurs in a spec twice."""
-
def __init__(self, pkg, variant):
super(UnknownVariantError, self).__init__(
"Package %s has no variant %s!" % (pkg, variant))
class DuplicateArchitectureError(SpecError):
-
"""Raised when the same architecture occurs in a spec twice."""
- def __init__(self, message):
- super(DuplicateArchitectureError, self).__init__(message)
-
class InconsistentSpecError(SpecError):
-
"""Raised when two nodes in the same spec DAG have inconsistent
constraints."""
- def __init__(self, message):
- super(InconsistentSpecError, self).__init__(message)
-
-
-class InvalidDependencyException(SpecError):
+class InvalidDependencyError(SpecError):
"""Raised when a dependency in a spec is not actually a dependency
of the package."""
- def __init__(self, message):
- super(InvalidDependencyException, self).__init__(message)
+class InvalidDependencyTypeError(SpecError):
+ """Raised when a dependency type is not a legal Spack dep type."""
-class NoProviderError(SpecError):
+class NoProviderError(SpecError):
"""Raised when there is no package that provides a particular
virtual dependency.
"""
-
def __init__(self, vpkg):
super(NoProviderError, self).__init__(
"No providers found for virtual package: '%s'" % vpkg)
@@ -2765,11 +2790,9 @@ class NoProviderError(SpecError):
class MultipleProviderError(SpecError):
-
"""Raised when there is no package that provides a particular
virtual dependency.
"""
-
def __init__(self, vpkg, providers):
"""Takes the name of the vpkg"""
super(MultipleProviderError, self).__init__(
@@ -2780,10 +2803,8 @@ class MultipleProviderError(SpecError):
class UnsatisfiableSpecError(SpecError):
-
"""Raised when a spec conflicts with package constraints.
Provide the requirement that was violated when raising."""
-
def __init__(self, provided, required, constraint_type):
super(UnsatisfiableSpecError, self).__init__(
"%s does not satisfy %s" % (provided, required))
@@ -2793,89 +2814,70 @@ class UnsatisfiableSpecError(SpecError):
class UnsatisfiableSpecNameError(UnsatisfiableSpecError):
-
"""Raised when two specs aren't even for the same package."""
-
def __init__(self, provided, required):
super(UnsatisfiableSpecNameError, self).__init__(
provided, required, "name")
class UnsatisfiableVersionSpecError(UnsatisfiableSpecError):
-
"""Raised when a spec version conflicts with package constraints."""
-
def __init__(self, provided, required):
super(UnsatisfiableVersionSpecError, self).__init__(
provided, required, "version")
class UnsatisfiableCompilerSpecError(UnsatisfiableSpecError):
-
"""Raised when a spec comiler conflicts with package constraints."""
-
def __init__(self, provided, required):
super(UnsatisfiableCompilerSpecError, self).__init__(
provided, required, "compiler")
class UnsatisfiableVariantSpecError(UnsatisfiableSpecError):
-
"""Raised when a spec variant conflicts with package constraints."""
-
def __init__(self, provided, required):
super(UnsatisfiableVariantSpecError, self).__init__(
provided, required, "variant")
class UnsatisfiableCompilerFlagSpecError(UnsatisfiableSpecError):
-
"""Raised when a spec variant conflicts with package constraints."""
-
def __init__(self, provided, required):
super(UnsatisfiableCompilerFlagSpecError, self).__init__(
provided, required, "compiler_flags")
class UnsatisfiableArchitectureSpecError(UnsatisfiableSpecError):
-
"""Raised when a spec architecture conflicts with package constraints."""
-
def __init__(self, provided, required):
super(UnsatisfiableArchitectureSpecError, self).__init__(
provided, required, "architecture")
class UnsatisfiableProviderSpecError(UnsatisfiableSpecError):
-
"""Raised when a provider is supplied but constraints don't match
a vpkg requirement"""
-
def __init__(self, provided, required):
super(UnsatisfiableProviderSpecError, self).__init__(
provided, required, "provider")
+
# TODO: get rid of this and be more specific about particular incompatible
# dep constraints
-
-
class UnsatisfiableDependencySpecError(UnsatisfiableSpecError):
-
"""Raised when some dependency of constrained specs are incompatible"""
-
def __init__(self, provided, required):
super(UnsatisfiableDependencySpecError, self).__init__(
provided, required, "dependency")
class SpackYAMLError(spack.error.SpackError):
-
def __init__(self, msg, yaml_error):
super(SpackYAMLError, self).__init__(msg, str(yaml_error))
class AmbiguousHashError(SpecError):
-
def __init__(self, msg, *specs):
super(AmbiguousHashError, self).__init__(msg)
for spec in specs: