diff options
author | Todd Gamblin <tgamblin@llnl.gov> | 2015-03-17 20:59:47 -0400 |
---|---|---|
committer | Todd Gamblin <tgamblin@llnl.gov> | 2015-05-10 12:24:03 -0700 |
commit | 0944ba120cad3de7b84b15e19b9c889f5bea6241 (patch) | |
tree | aa93b47f69e95c93ae046afffdacf801d317e1d1 | |
parent | 8e87b2176ad762a75acfdab158ddd788648ee997 (diff) | |
download | spack-0944ba120cad3de7b84b15e19b9c889f5bea6241.tar.gz spack-0944ba120cad3de7b84b15e19b9c889f5bea6241.tar.bz2 spack-0944ba120cad3de7b84b15e19b9c889f5bea6241.tar.xz spack-0944ba120cad3de7b84b15e19b9c889f5bea6241.zip |
relations are now "directives", and code is cleaned up.
-rw-r--r-- | lib/spack/llnl/util/lang.py | 25 | ||||
-rw-r--r-- | lib/spack/spack/__init__.py | 6 | ||||
-rw-r--r-- | lib/spack/spack/directives.py (renamed from lib/spack/spack/relations.py) | 128 | ||||
-rw-r--r-- | lib/spack/spack/multimethod.py | 2 | ||||
-rw-r--r-- | lib/spack/spack/package.py | 3 |
5 files changed, 82 insertions, 82 deletions
diff --git a/lib/spack/llnl/util/lang.py b/lib/spack/llnl/util/lang.py index 332367f537..13453c20ed 100644 --- a/lib/spack/llnl/util/lang.py +++ b/lib/spack/llnl/util/lang.py @@ -126,9 +126,9 @@ def caller_locals(): del stack -def get_calling_package_name(): +def get_calling_module_name(): """Make sure that the caller is a class definition, and return the - module's name. + enclosing module's name. """ stack = inspect.stack() try: @@ -322,6 +322,27 @@ def match_predicate(*args): return match + +def DictWrapper(dictionary): + """Returns a class that wraps a dictionary and enables it to be used + like an object.""" + class wrapper(object): + def __getattr__(self, name): + return dictionary[name] + + 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() + + class RequiredAttributeError(ValueError): def __init__(self, message): super(RequiredAttributeError, self).__init__(message) diff --git a/lib/spack/spack/__init__.py b/lib/spack/spack/__init__.py index eb891e3d57..053c4036d8 100644 --- a/lib/spack/spack/__init__.py +++ b/lib/spack/spack/__init__.py @@ -146,9 +146,9 @@ import llnl.util.filesystem from llnl.util.filesystem import * __all__ += llnl.util.filesystem.__all__ -import spack.relations -from spack.relations import * -__all__ += spack.relations.__all__ +import spack.directives +from spack.directives import * +__all__ += spack.directives.__all__ import spack.util.executable from spack.util.executable import * diff --git a/lib/spack/spack/relations.py b/lib/spack/spack/directives.py index a0c7723473..e1589c019f 100644 --- a/lib/spack/spack/relations.py +++ b/lib/spack/spack/directives.py @@ -22,51 +22,26 @@ # along with this program; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ############################################################################## -""" -This package contains relationships that can be defined among packages. -Relations are functions that can be called inside a package definition, -for example: +"""This package contains directives that can be used within a package. + +Directives are functions that can be called inside a package +definition to modify the package, for example: - class OpenMPI(Package): + class OpenMpi(Package): depends_on("hwloc") provides("mpi") ... -The available relations are: - -depends_on - Above, the OpenMPI package declares that it "depends on" hwloc. This means - that the hwloc package needs to be installed before OpenMPI can be - installed. When a user runs 'spack install openmpi', spack will fetch - hwloc and install it first. - -provides - This is useful when more than one package can satisfy a dependence. Above, - OpenMPI declares that it "provides" mpi. Other implementations of the MPI - interface, like mvapich and mpich, also provide mpi, e.g.: +``provides`` and ``depends_on`` are spack directives. - class Mvapich(Package): - provides("mpi") - ... +The available directives are: - class Mpich(Package): - provides("mpi") - ... + * ``version`` + * ``depends_on`` + * ``provides`` + * ``extends`` + * ``patch`` - Instead of depending on openmpi, mvapich, or mpich, another package can - declare that it depends on "mpi": - - class Mpileaks(Package): - depends_on("mpi") - ... - - Now the user can pick which MPI they would like to build with when they - install mpileaks. For example, the user could install 3 instances of - mpileaks, one for each MPI version, by issuing these three commands: - - spack install mpileaks ^openmpi - spack install mpileaks ^mvapich - spack install mpileaks ^mpich """ __all__ = [ 'depends_on', 'extends', 'provides', 'patch', 'version' ] @@ -84,14 +59,27 @@ from spack.patch import Patch from spack.spec import Spec, parse_anonymous_spec +def directive(fun): + """Decorator that allows a function to be called while a class is + being constructed, and to modify the class. -def version(ver, checksum=None, **kwargs): + Adds the class scope as an initial parameter when called, like + a class method would. + """ + def directive_function(*args, **kwargs): + pkg = DictWrapper(caller_locals()) + pkg.name = get_calling_module_name() + return fun(pkg, *args, **kwargs) + return directive_function + + +@directive +def version(pkg, ver, checksum=None, **kwargs): """Adds a version and metadata describing how to fetch it. Metadata is just stored as a dict in the package's versions dictionary. Package must turn it into a valid fetch strategy later. """ - pkg = caller_locals() versions = pkg.setdefault('versions', {}) # special case checksum for backward compatibility @@ -103,21 +91,21 @@ def version(ver, checksum=None, **kwargs): versions[Version(ver)] = kwargs -def depends_on(*specs): +@directive +def depends_on(pkg, *specs): """Adds a dependencies local variable in the locals of the calling class, based on args. """ - pkg = get_calling_package_name() - clocals = caller_locals() - dependencies = clocals.setdefault('dependencies', {}) + dependencies = pkg.setdefault('dependencies', {}) for string in specs: for spec in spack.spec.parse(string): - if pkg == spec.name: - raise CircularReferenceError('depends_on', pkg) + if pkg.name == spec.name: + raise CircularReferenceError('depends_on', pkg.name) dependencies[spec.name] = spec -def extends(spec, **kwargs): +@directive +def extends(pkg, spec, **kwargs): """Same as depends_on, but dependency is symlinked into parent prefix. This is for Python and other language modules where the module @@ -131,64 +119,54 @@ def extends(spec, **kwargs): mechanism. """ - pkg = get_calling_package_name() - clocals = caller_locals() - dependencies = clocals.setdefault('dependencies', {}) - extendees = clocals.setdefault('extendees', {}) + dependencies = pkg.setdefault('dependencies', {}) + extendees = pkg.setdefault('extendees', {}) if extendees: raise RelationError("Packages can extend at most one other package.") spec = Spec(spec) - if pkg == spec.name: - raise CircularReferenceError('extends', pkg) + if pkg.name == spec.name: + raise CircularReferenceError('extends', pkg.name) dependencies[spec.name] = spec extendees[spec.name] = (spec, kwargs) -def provides(*specs, **kwargs): +@directive +def provides(pkg, *specs, **kwargs): """Allows packages to provide a virtual dependency. If a package provides 'mpi', other packages can declare that they depend on "mpi", and spack can use the providing package to satisfy the dependency. """ - pkg = get_calling_package_name() - spec_string = kwargs.get('when', pkg) - provider_spec = parse_anonymous_spec(spec_string, pkg) + spec_string = kwargs.get('when', pkg.name) + provider_spec = parse_anonymous_spec(spec_string, pkg.name) - provided = caller_locals().setdefault("provided", {}) + provided = pkg.setdefault("provided", {}) for string in specs: for provided_spec in spack.spec.parse(string): - if pkg == provided_spec.name: - raise CircularReferenceError('depends_on', pkg) + if pkg.name == provided_spec.name: + raise CircularReferenceError('depends_on', pkg.name) provided[provided_spec] = provider_spec -def patch(url_or_filename, **kwargs): +@directive +def patch(pkg, url_or_filename, **kwargs): """Packages can declare patches to apply to source. You can optionally provide a when spec to indicate that a particular patch should only be applied when the package's spec meets certain conditions (e.g. a particular version). """ - pkg = get_calling_package_name() level = kwargs.get('level', 1) - when_spec = parse_anonymous_spec(kwargs.get('when', pkg), pkg) + when = kwargs.get('when', pkg.name) - patches = caller_locals().setdefault('patches', {}) + patches = pkg.setdefault('patches', {}) + + when_spec = parse_anonymous_spec(when, pkg.name) if when_spec not in patches: - patches[when_spec] = [Patch(pkg, url_or_filename, level)] + patches[when_spec] = [Patch(pkg.name, url_or_filename, level)] else: # if this spec is identical to some other, then append this # patch to the existing list. - patches[when_spec].append(Patch(pkg, url_or_filename, level)) - - -def conflicts(*specs): - """Packages can declare conflicts with other packages. - This can be as specific as you like: use regular spec syntax. - - NOT YET IMPLEMENTED. - """ - # TODO: implement conflicts - pass + patches[when_spec].append(Patch(pkg.name, url_or_filename, level)) class RelationError(spack.error.SpackError): diff --git a/lib/spack/spack/multimethod.py b/lib/spack/spack/multimethod.py index 974401e1aa..892619c6ac 100644 --- a/lib/spack/spack/multimethod.py +++ b/lib/spack/spack/multimethod.py @@ -195,7 +195,7 @@ class when(object): """ class when(object): def __init__(self, spec): - pkg = get_calling_package_name() + pkg = get_calling_module_name() self.spec = parse_anonymous_spec(spec, pkg) def __call__(self, method): diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py index 7d9eca5077..7f2b53ceed 100644 --- a/lib/spack/spack/package.py +++ b/lib/spack/spack/package.py @@ -303,7 +303,8 @@ class Package(object): """ # - # These variables are defaults for the various "relations". + # These variables are defaults for Spack's various package + # directives. # """Map of information about Versions of this package. Map goes: Version -> dict of attributes""" |