diff options
-rw-r--r-- | lib/spack/spack/spec.py | 87 | ||||
-rw-r--r-- | lib/spack/spack/test/spec_syntax.py | 54 |
2 files changed, 100 insertions, 41 deletions
diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py index 99fc2d3ea4..108e771748 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,45 @@ _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, '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 +608,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 +622,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() @@ -2718,6 +2775,10 @@ class InvalidDependencyError(SpecError): of the package.""" +class InvalidDependencyTypeError(SpecError): + """Raised when a dependency type is not a legal Spack dep type.""" + + class NoProviderError(SpecError): """Raised when there is no package that provides a particular virtual dependency. @@ -2804,8 +2865,6 @@ class UnsatisfiableProviderSpecError(UnsatisfiableSpecError): # 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): diff --git a/lib/spack/spack/test/spec_syntax.py b/lib/spack/spack/test/spec_syntax.py index 3079288c77..d4eb9e057f 100644 --- a/lib/spack/spack/test/spec_syntax.py +++ b/lib/spack/spack/test/spec_syntax.py @@ -24,34 +24,34 @@ ############################################################################## import unittest -import spack.spec +import spack.spec as sp from spack.parse import Token from spack.spec import * # Sample output for a complex lexing. -complex_lex = [Token(ID, 'mvapich_foo'), - Token(DEP), - Token(ID, '_openmpi'), - Token(AT), - Token(ID, '1.2'), - Token(COLON), - Token(ID, '1.4'), - Token(COMMA), - Token(ID, '1.6'), - Token(PCT), - Token(ID, 'intel'), - Token(AT), - Token(ID, '12.1'), - Token(COLON), - Token(ID, '12.6'), - Token(ON), - Token(ID, 'debug'), - Token(OFF), - Token(ID, 'qt_4'), - Token(DEP), - Token(ID, 'stackwalker'), - Token(AT), - Token(ID, '8.1_1e')] +complex_lex = [Token(sp.ID, 'mvapich_foo'), + Token(sp.DEP), + Token(sp.ID, '_openmpi'), + Token(sp.AT), + Token(sp.ID, '1.2'), + Token(sp.COLON), + Token(sp.ID, '1.4'), + Token(sp.COMMA), + Token(sp.ID, '1.6'), + Token(sp.PCT), + Token(sp.ID, 'intel'), + Token(sp.AT), + Token(sp.ID, '12.1'), + Token(sp.COLON), + Token(sp.ID, '12.6'), + Token(sp.ON), + Token(sp.ID, 'debug'), + Token(sp.OFF), + Token(sp.ID, 'qt_4'), + Token(sp.DEP), + Token(sp.ID, 'stackwalker'), + Token(sp.AT), + Token(sp.ID, '8.1_1e')] class SpecSyntaxTest(unittest.TestCase): @@ -74,16 +74,16 @@ class SpecSyntaxTest(unittest.TestCase): """ if spec is None: spec = expected - output = spack.spec.parse(spec) + output = sp.parse(spec) parsed = (" ".join(str(spec) for spec in output)) self.assertEqual(expected, parsed) def check_lex(self, tokens, spec): """Check that the provided spec parses to the provided token list.""" - lex_output = SpecLexer().lex(spec) + lex_output = sp.SpecLexer().lex(spec) for tok, spec_tok in zip(tokens, lex_output): - if tok.type == ID: + if tok.type == sp.ID: self.assertEqual(tok, spec_tok) else: # Only check the type for non-identifiers. |