Modularize directives. Now each directive specifies its storage.
This commit is contained in:
		@@ -132,16 +132,14 @@ def get_calling_module_name():
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
    stack = inspect.stack()
 | 
					    stack = inspect.stack()
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        # get calling function name (the relation)
 | 
					 | 
				
			||||||
        relation = stack[1][3]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # Make sure locals contain __module__
 | 
					        # Make sure locals contain __module__
 | 
				
			||||||
        caller_locals = stack[2][0].f_locals
 | 
					        caller_locals = stack[2][0].f_locals
 | 
				
			||||||
    finally:
 | 
					    finally:
 | 
				
			||||||
        del stack
 | 
					        del stack
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if not '__module__' in caller_locals:
 | 
					    if not '__module__' in caller_locals:
 | 
				
			||||||
        raise ScopeError(relation)
 | 
					        raise RuntimeError("Must invoke get_calling_module_name() "
 | 
				
			||||||
 | 
					                           "from inside a class definition!")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    module_name = caller_locals['__module__']
 | 
					    module_name = caller_locals['__module__']
 | 
				
			||||||
    base_name = module_name.split('.')[-1]
 | 
					    base_name = module_name.split('.')[-1]
 | 
				
			||||||
@@ -327,18 +325,15 @@ def DictWrapper(dictionary):
 | 
				
			|||||||
    """Returns a class that wraps a dictionary and enables it to be used
 | 
					    """Returns a class that wraps a dictionary and enables it to be used
 | 
				
			||||||
       like an object."""
 | 
					       like an object."""
 | 
				
			||||||
    class wrapper(object):
 | 
					    class wrapper(object):
 | 
				
			||||||
        def __getattr__(self, name):
 | 
					        def __getattr__(self, name):        return dictionary[name]
 | 
				
			||||||
            return dictionary[name]
 | 
					        def __setattr__(self, name, value): dictionary[name] = value
 | 
				
			||||||
 | 
					        def setdefault(self, *args):        return dictionary.setdefault(*args)
 | 
				
			||||||
 | 
					        def get(self, *args):               return dictionary.get(*args)
 | 
				
			||||||
 | 
					        def keys(self):                     return dictionary.keys()
 | 
				
			||||||
 | 
					        def values(self):                   return dictionary.values()
 | 
				
			||||||
 | 
					        def items(self):                    return dictionary.items()
 | 
				
			||||||
 | 
					        def __iter__(self):                 return iter(dictionary)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def __setattr__(self, name, value):
 | 
					 | 
				
			||||||
            dictionary[name] = value
 | 
					 | 
				
			||||||
            return value
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        def setdefault(self, *args):
 | 
					 | 
				
			||||||
            return dictionary.setdefault(*args)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        def get(self, *args):
 | 
					 | 
				
			||||||
            return dictionary.get(*args)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return wrapper()
 | 
					    return wrapper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,9 +41,11 @@ class OpenMpi(Package):
 | 
				
			|||||||
  * ``provides``
 | 
					  * ``provides``
 | 
				
			||||||
  * ``extends``
 | 
					  * ``extends``
 | 
				
			||||||
  * ``patch``
 | 
					  * ``patch``
 | 
				
			||||||
 | 
					  * ``variant``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
__all__ = [ 'depends_on', 'extends', 'provides', 'patch', 'version' ]
 | 
					__all__ = [ 'depends_on', 'extends', 'provides', 'patch', 'version',
 | 
				
			||||||
 | 
					            'variant' ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
import inspect
 | 
					import inspect
 | 
				
			||||||
@@ -59,52 +61,125 @@ class OpenMpi(Package):
 | 
				
			|||||||
from spack.spec import Spec, parse_anonymous_spec
 | 
					from spack.spec import Spec, parse_anonymous_spec
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def directive(fun):
 | 
					#
 | 
				
			||||||
    """Decorator that allows a function to be called while a class is
 | 
					# This is a list of all directives, built up as they are defined in
 | 
				
			||||||
       being constructed, and to modify the class.
 | 
					# this file.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					directives = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def ensure_dicts(pkg):
 | 
				
			||||||
 | 
					    """Ensure that a package has all the dicts required by directives."""
 | 
				
			||||||
 | 
					    for name, d in directives.items():
 | 
				
			||||||
 | 
					        d.ensure_dicts(pkg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class directive(object):
 | 
				
			||||||
 | 
					    """Decorator for Spack directives.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Spack directives allow you to modify a package while it is being
 | 
				
			||||||
 | 
					    defined, e.g. to add version or depenency information.  Directives
 | 
				
			||||||
 | 
					    are one of the key pieces of Spack's package "langauge", which is
 | 
				
			||||||
 | 
					    embedded in python.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Here's an example directive:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @directive(dicts='versions')
 | 
				
			||||||
 | 
					        version(pkg, ...):
 | 
				
			||||||
 | 
					            ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This directive allows you write:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        class Foo(Package):
 | 
				
			||||||
 | 
					            version(...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    The ``@directive`` decorator handles a couple things for you:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      1. Adds the class scope (pkg) as an initial parameter when
 | 
				
			||||||
 | 
					         called, like a class method would.  This allows you to modify
 | 
				
			||||||
 | 
					         a package from within a directive, while the package is still
 | 
				
			||||||
 | 
					         being defined.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      2. It automatically adds a dictionary called "versions" to the
 | 
				
			||||||
 | 
					         package so that you can refer to pkg.versions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    The ``(dicts='versions')`` part ensures that ALL packages in Spack
 | 
				
			||||||
 | 
					    will have a ``versions`` attribute after they're constructed, and
 | 
				
			||||||
 | 
					    that if no directive actually modified it, it will just be an
 | 
				
			||||||
 | 
					    empty dict.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This is just a modular way to add storage attributes to the
 | 
				
			||||||
 | 
					    Package class, and it's how Spack gets information from the
 | 
				
			||||||
 | 
					    packages to the core.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
       Adds the class scope as an initial parameter when called, like
 | 
					 | 
				
			||||||
       a class method would.
 | 
					 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    def directive_function(*args, **kwargs):
 | 
					
 | 
				
			||||||
        pkg      = DictWrapper(caller_locals())
 | 
					    def __init__(self, **kwargs):
 | 
				
			||||||
        pkg.name = get_calling_module_name()
 | 
					        # dict argument allows directives to have storage on the package.
 | 
				
			||||||
        return fun(pkg, *args, **kwargs)
 | 
					        dicts = kwargs.get('dicts', None)
 | 
				
			||||||
    return directive_function
 | 
					
 | 
				
			||||||
 | 
					        if isinstance(dicts, basestring):
 | 
				
			||||||
 | 
					            dicts = (dicts,)
 | 
				
			||||||
 | 
					        elif type(dicts) not in (list, tuple):
 | 
				
			||||||
 | 
					            raise TypeError(
 | 
				
			||||||
 | 
					                "dicts arg must be list, tuple, or string. Found %s."
 | 
				
			||||||
 | 
					                % type(dicts))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.dicts = dicts
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@directive
 | 
					    def ensure_dicts(self, pkg):
 | 
				
			||||||
 | 
					        """Ensure that a package has the dicts required by this directive."""
 | 
				
			||||||
 | 
					        for d in self.dicts:
 | 
				
			||||||
 | 
					            if not hasattr(pkg, d):
 | 
				
			||||||
 | 
					                setattr(pkg, d, {})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            attr = getattr(pkg, d)
 | 
				
			||||||
 | 
					            if not isinstance(attr, dict):
 | 
				
			||||||
 | 
					                raise spack.error.SpackError(
 | 
				
			||||||
 | 
					                    "Package %s has non-dict %s attribute!" % (pkg, d))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __call__(self, directive_function):
 | 
				
			||||||
 | 
					        directives[directive_function.__name__] = self
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        def wrapped(*args, **kwargs):
 | 
				
			||||||
 | 
					            pkg = DictWrapper(caller_locals())
 | 
				
			||||||
 | 
					            self.ensure_dicts(pkg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            pkg.name = get_calling_module_name()
 | 
				
			||||||
 | 
					            return directive_function(pkg, *args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return wrapped
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@directive(dicts='versions')
 | 
				
			||||||
def version(pkg, ver, checksum=None, **kwargs):
 | 
					def version(pkg, ver, checksum=None, **kwargs):
 | 
				
			||||||
    """Adds a version and metadata describing how to fetch it.
 | 
					    """Adds a version and metadata describing how to fetch it.
 | 
				
			||||||
       Metadata is just stored as a dict in the package's versions
 | 
					       Metadata is just stored as a dict in the package's versions
 | 
				
			||||||
       dictionary.  Package must turn it into a valid fetch strategy
 | 
					       dictionary.  Package must turn it into a valid fetch strategy
 | 
				
			||||||
       later.
 | 
					       later.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    versions = pkg.setdefault('versions', {})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # special case checksum for backward compatibility
 | 
					    # special case checksum for backward compatibility
 | 
				
			||||||
    if checksum:
 | 
					    if checksum:
 | 
				
			||||||
        kwargs['md5'] = checksum
 | 
					        kwargs['md5'] = checksum
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Store the kwargs for the package to use later when constructing
 | 
					    # Store kwargs for the package to later with a fetch_strategy.
 | 
				
			||||||
    # a fetch strategy.
 | 
					    pkg.versions[Version(ver)] = kwargs
 | 
				
			||||||
    versions[Version(ver)] = kwargs
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@directive
 | 
					@directive(dicts='dependencies')
 | 
				
			||||||
def depends_on(pkg, *specs):
 | 
					def depends_on(pkg, *specs):
 | 
				
			||||||
    """Adds a dependencies local variable in the locals of
 | 
					    """Adds a dependencies local variable in the locals of
 | 
				
			||||||
       the calling class, based on args. """
 | 
					       the calling class, based on args. """
 | 
				
			||||||
    dependencies = pkg.setdefault('dependencies', {})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for string in specs:
 | 
					    for string in specs:
 | 
				
			||||||
        for spec in spack.spec.parse(string):
 | 
					        for spec in spack.spec.parse(string):
 | 
				
			||||||
            if pkg.name == spec.name:
 | 
					            if pkg.name == spec.name:
 | 
				
			||||||
                raise CircularReferenceError('depends_on', pkg.name)
 | 
					                raise CircularReferenceError('depends_on', pkg.name)
 | 
				
			||||||
            dependencies[spec.name] = spec
 | 
					            pkg.dependencies[spec.name] = spec
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@directive
 | 
					@directive(dicts=('extendees', 'dependencies'))
 | 
				
			||||||
def extends(pkg, spec, **kwargs):
 | 
					def extends(pkg, spec, **kwargs):
 | 
				
			||||||
    """Same as depends_on, but dependency is symlinked into parent prefix.
 | 
					    """Same as depends_on, but dependency is symlinked into parent prefix.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -119,19 +194,17 @@ def extends(pkg, spec, **kwargs):
 | 
				
			|||||||
    mechanism.
 | 
					    mechanism.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    dependencies = pkg.setdefault('dependencies', {})
 | 
					    if pkg.extendees:
 | 
				
			||||||
    extendees = pkg.setdefault('extendees', {})
 | 
					        raise DirectiveError("Packages can extend at most one other package.")
 | 
				
			||||||
    if extendees:
 | 
					 | 
				
			||||||
        raise RelationError("Packages can extend at most one other package.")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    spec = Spec(spec)
 | 
					    spec = Spec(spec)
 | 
				
			||||||
    if pkg.name == spec.name:
 | 
					    if pkg.name == spec.name:
 | 
				
			||||||
        raise CircularReferenceError('extends', pkg.name)
 | 
					        raise CircularReferenceError('extends', pkg.name)
 | 
				
			||||||
    dependencies[spec.name] = spec
 | 
					    pkg.dependencies[spec.name] = spec
 | 
				
			||||||
    extendees[spec.name] = (spec, kwargs)
 | 
					    pkg.extendees[spec.name] = (spec, kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@directive
 | 
					@directive(dicts='provided')
 | 
				
			||||||
def provides(pkg, *specs, **kwargs):
 | 
					def provides(pkg, *specs, **kwargs):
 | 
				
			||||||
    """Allows packages to provide a virtual dependency.  If a package provides
 | 
					    """Allows packages to provide a virtual dependency.  If a package provides
 | 
				
			||||||
       'mpi', other packages can declare that they depend on "mpi", and spack
 | 
					       'mpi', other packages can declare that they depend on "mpi", and spack
 | 
				
			||||||
@@ -140,15 +213,14 @@ def provides(pkg, *specs, **kwargs):
 | 
				
			|||||||
    spec_string = kwargs.get('when', pkg.name)
 | 
					    spec_string = kwargs.get('when', pkg.name)
 | 
				
			||||||
    provider_spec = parse_anonymous_spec(spec_string, pkg.name)
 | 
					    provider_spec = parse_anonymous_spec(spec_string, pkg.name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    provided = pkg.setdefault("provided", {})
 | 
					 | 
				
			||||||
    for string in specs:
 | 
					    for string in specs:
 | 
				
			||||||
        for provided_spec in spack.spec.parse(string):
 | 
					        for provided_spec in spack.spec.parse(string):
 | 
				
			||||||
            if pkg.name == provided_spec.name:
 | 
					            if pkg.name == provided_spec.name:
 | 
				
			||||||
                raise CircularReferenceError('depends_on', pkg.name)
 | 
					                raise CircularReferenceError('depends_on', pkg.name)
 | 
				
			||||||
            provided[provided_spec] = provider_spec
 | 
					            pkg.provided[provided_spec] = provider_spec
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@directive
 | 
					@directive(dicts='patches')
 | 
				
			||||||
def patch(pkg, url_or_filename, **kwargs):
 | 
					def patch(pkg, url_or_filename, **kwargs):
 | 
				
			||||||
    """Packages can declare patches to apply to source.  You can
 | 
					    """Packages can declare patches to apply to source.  You can
 | 
				
			||||||
       optionally provide a when spec to indicate that a particular
 | 
					       optionally provide a when spec to indicate that a particular
 | 
				
			||||||
@@ -158,36 +230,42 @@ def patch(pkg, url_or_filename, **kwargs):
 | 
				
			|||||||
    level = kwargs.get('level', 1)
 | 
					    level = kwargs.get('level', 1)
 | 
				
			||||||
    when  = kwargs.get('when', pkg.name)
 | 
					    when  = kwargs.get('when', pkg.name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    patches = pkg.setdefault('patches', {})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    when_spec = parse_anonymous_spec(when, pkg.name)
 | 
					    when_spec = parse_anonymous_spec(when, pkg.name)
 | 
				
			||||||
    if when_spec not in patches:
 | 
					    if when_spec not in pkg.patches:
 | 
				
			||||||
        patches[when_spec] = [Patch(pkg.name, url_or_filename, level)]
 | 
					        pkg.patches[when_spec] = [Patch(pkg.name, url_or_filename, level)]
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        # if this spec is identical to some other, then append this
 | 
					        # if this spec is identical to some other, then append this
 | 
				
			||||||
        # patch to the existing list.
 | 
					        # patch to the existing list.
 | 
				
			||||||
        patches[when_spec].append(Patch(pkg.name, url_or_filename, level))
 | 
					        pkg.patches[when_spec].append(Patch(pkg.name, url_or_filename, level))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class RelationError(spack.error.SpackError):
 | 
					@directive(dicts='variants')
 | 
				
			||||||
    """This is raised when something is wrong with a package relation."""
 | 
					def variant(pkg, name, description="", **kwargs):
 | 
				
			||||||
    def __init__(self, relation, message):
 | 
					    """Define a variant for the package.  Allows the user to supply
 | 
				
			||||||
        super(RelationError, self).__init__(message)
 | 
					       +variant/-variant in a spec.  You can optionally supply an
 | 
				
			||||||
        self.relation = relation
 | 
					       initial + or - to make the variant enabled or disabled by defaut.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if not re.match(r'[-~+]?[A-Za-z0-9_][A-Za-z0-9_.-]*', name):
 | 
				
			||||||
 | 
					        raise DirectiveError("Invalid variant name in %s: '%s'"
 | 
				
			||||||
 | 
					                             % (pkg.name, name))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enabled = re.match(r'+', name)
 | 
				
			||||||
 | 
					    pkg.variants[name] = enabled
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ScopeError(RelationError):
 | 
					class DirectiveError(spack.error.SpackError):
 | 
				
			||||||
    """This is raised when a relation is called from outside a spack package."""
 | 
					    """This is raised when something is wrong with a package directive."""
 | 
				
			||||||
    def __init__(self, relation):
 | 
					    def __init__(self, directive, message):
 | 
				
			||||||
        super(ScopeError, self).__init__(
 | 
					        super(DirectiveError, self).__init__(message)
 | 
				
			||||||
            relation,
 | 
					        self.directive = directive
 | 
				
			||||||
            "Must invoke '%s' from inside a class definition!" % relation)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CircularReferenceError(RelationError):
 | 
					class CircularReferenceError(DirectiveError):
 | 
				
			||||||
    """This is raised when something depends on itself."""
 | 
					    """This is raised when something depends on itself."""
 | 
				
			||||||
    def __init__(self, relation, package):
 | 
					    def __init__(self, directive, package):
 | 
				
			||||||
        super(CircularReferenceError, self).__init__(
 | 
					        super(CircularReferenceError, self).__init__(
 | 
				
			||||||
            relation,
 | 
					            directive,
 | 
				
			||||||
            "Package '%s' cannot pass itself to %s." % (package, relation))
 | 
					            "Package '%s' cannot pass itself to %s." % (package, directive))
 | 
				
			||||||
        self.package = package
 | 
					        self.package = package
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,6 +55,7 @@
 | 
				
			|||||||
import spack.compilers
 | 
					import spack.compilers
 | 
				
			||||||
import spack.mirror
 | 
					import spack.mirror
 | 
				
			||||||
import spack.hooks
 | 
					import spack.hooks
 | 
				
			||||||
 | 
					import spack.directives
 | 
				
			||||||
import spack.build_environment as build_env
 | 
					import spack.build_environment as build_env
 | 
				
			||||||
import spack.url as url
 | 
					import spack.url as url
 | 
				
			||||||
import spack.fetch_strategy as fs
 | 
					import spack.fetch_strategy as fs
 | 
				
			||||||
@@ -301,33 +302,6 @@ class SomePackage(Package):
 | 
				
			|||||||
    clean() (some of them do this), and others to provide custom behavior.
 | 
					    clean() (some of them do this), and others to provide custom behavior.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					 | 
				
			||||||
    #
 | 
					 | 
				
			||||||
    # These variables are defaults for Spack's various package
 | 
					 | 
				
			||||||
    # directives.
 | 
					 | 
				
			||||||
    #
 | 
					 | 
				
			||||||
    """Map of information about Versions of this package.
 | 
					 | 
				
			||||||
       Map goes: Version -> dict of attributes"""
 | 
					 | 
				
			||||||
    versions = {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    """Specs of dependency packages, keyed by name."""
 | 
					 | 
				
			||||||
    dependencies = {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    """Specs of virtual packages provided by this package, keyed by name."""
 | 
					 | 
				
			||||||
    provided = {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    """Specs of conflicting packages, keyed by name. """
 | 
					 | 
				
			||||||
    conflicted = {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    """Patches to apply to newly expanded source, if any."""
 | 
					 | 
				
			||||||
    patches = {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    """Specs of package this one extends, or None.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Currently, ppackages can extend at most one other package.
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    extendees = {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #
 | 
					    #
 | 
				
			||||||
    # These are default values for instance variables.
 | 
					    # These are default values for instance variables.
 | 
				
			||||||
    #
 | 
					    #
 | 
				
			||||||
@@ -351,20 +325,8 @@ def __init__(self, spec):
 | 
				
			|||||||
        if '.' in self.name:
 | 
					        if '.' in self.name:
 | 
				
			||||||
            self.name = self.name[self.name.rindex('.') + 1:]
 | 
					            self.name = self.name[self.name.rindex('.') + 1:]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Sanity check some required variables that could be
 | 
					        # Sanity check attributes required by Spack directives.
 | 
				
			||||||
        # overridden by package authors.
 | 
					        spack.directives.ensure_dicts(type(self))
 | 
				
			||||||
        def ensure_has_dict(attr_name):
 | 
					 | 
				
			||||||
            if not hasattr(self, attr_name):
 | 
					 | 
				
			||||||
                raise PackageError("Package %s must define %s" % attr_name)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            attr = getattr(self, attr_name)
 | 
					 | 
				
			||||||
            if not isinstance(attr, dict):
 | 
					 | 
				
			||||||
                raise PackageError("Package %s has non-dict %s attribute!"
 | 
					 | 
				
			||||||
                                   % (self.name, attr_name))
 | 
					 | 
				
			||||||
        ensure_has_dict('versions')
 | 
					 | 
				
			||||||
        ensure_has_dict('dependencies')
 | 
					 | 
				
			||||||
        ensure_has_dict('conflicted')
 | 
					 | 
				
			||||||
        ensure_has_dict('patches')
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Check versions in the versions dict.
 | 
					        # Check versions in the versions dict.
 | 
				
			||||||
        for v in self.versions:
 | 
					        for v in self.versions:
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user