diff options
Diffstat (limited to 'lib/spack/spack/spec.py')
-rw-r--r-- | lib/spack/spack/spec.py | 154 |
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: |