From ff9cb94f4f92112739f53881bcb0a9a19811684d Mon Sep 17 00:00:00 2001 From: Todd Gamblin Date: Tue, 20 Jan 2015 00:23:16 -0800 Subject: Add arguements to extends() and activate/deactivate. --- lib/spack/spack/package.py | 40 ++++++++++++++++++++++++++---------- lib/spack/spack/relations.py | 17 ++++++++------- var/spack/packages/python/package.py | 32 +++++++++++++++++++++++++++-- 3 files changed, 69 insertions(+), 20 deletions(-) diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py index ae34f8ae45..bd63c2e0c0 100644 --- a/lib/spack/spack/package.py +++ b/lib/spack/spack/package.py @@ -497,16 +497,26 @@ class Package(object): @property def extendee_spec(self): """Spec of the extendee of this package, or None if it is not an extension.""" - if not self.extendees: return None - + if not self.extendees: + return None name = next(iter(self.extendees)) if not name in self.spec: - return self.extendees[name] + spec, kwargs = self.extendees[name] + return spec # Need to do this to get the concrete version of the spec return self.spec[name] + @property + def extendee_args(self): + """Spec of the extendee of this package, or None if it is not an extension.""" + if not self.extendees: + return None + name = next(iter(self.extendees)) + return self.extendees[name][1] + + @property def is_extension(self): return len(self.extendees) > 0 @@ -949,6 +959,8 @@ class Package(object): def _sanity_check_extension(self): + if not self.is_extension: + raise ValueError("This package is not an extension.") extendee_package = self.extendee_spec.package extendee_package._check_extendable() @@ -967,14 +979,14 @@ class Package(object): activate() directly. """ self._sanity_check_extension() - self.extendee_spec.package.activate(self) + self.extendee_spec.package.activate(self, **self.extendee_args) spack.install_layout.add_extension(self.extendee_spec, self.spec) tty.msg("Activated extension %s for %s." % (self.spec.short_spec, self.extendee_spec.short_spec)) - def activate(self, extension): + def activate(self, extension, **kwargs): """Symlinks all files from the extension into extendee's install dir. Package authors can override this method to support other @@ -983,17 +995,20 @@ class Package(object): always executed. """ + ignore_files = set(spack.install_layout.hidden_file_paths) + ignore_files.update(kwargs.get('ignore', ())) + tree = LinkTree(extension.prefix) - conflict = tree.find_conflict( - self.prefix, ignore=spack.install_layout.hidden_file_paths) + conflict = tree.find_conflict(self.prefix, ignore=ignore_files) if conflict: raise ExtensionConflictError(conflict) - tree.merge(self.prefix, ignore=spack.install_layout.hidden_file_paths) + tree.merge(self.prefix, ignore=ignore_files) def do_deactivate(self): + """Called on the extension to invoke extendee's deactivate() method.""" self._sanity_check_extension() - self.extendee_spec.package.deactivate(self) + self.extendee_spec.package.deactivate(self, **self.extendee_args) if self.spec in spack.install_layout.get_extensions(self.extendee_spec): spack.install_layout.remove_extension(self.extendee_spec, self.spec) @@ -1002,7 +1017,7 @@ class Package(object): % (self.spec.short_spec, self.extendee_spec.short_spec)) - def deactivate(self, extension): + def deactivate(self, extension, **kwargs): """Unlinks all files from extension out of this package's install dir. Package authors can override this method to support other @@ -1011,8 +1026,11 @@ class Package(object): always executed. """ + ignore_files = set(spack.install_layout.hidden_file_paths) + ignore_files.update(kwargs.get('ignore', ())) + tree = LinkTree(extension.prefix) - tree.unmerge(self.prefix, ignore=spack.install_layout.hidden_file_paths) + tree.unmerge(self.prefix, ignore=ignore_files) def do_clean(self): diff --git a/lib/spack/spack/relations.py b/lib/spack/spack/relations.py index 60ff5bef34..a0c7723473 100644 --- a/lib/spack/spack/relations.py +++ b/lib/spack/spack/relations.py @@ -117,7 +117,7 @@ def depends_on(*specs): dependencies[spec.name] = spec -def extends(*specs): +def extends(spec, **kwargs): """Same as depends_on, but dependency is symlinked into parent prefix. This is for Python and other language modules where the module @@ -126,6 +126,10 @@ def extends(*specs): but allowing ONE module version to be symlinked into a parent Python install at a time. + keyword arguments can be passed to extends() so that extension + packages can pass parameters to the extendee's extension + mechanism. + """ pkg = get_calling_package_name() clocals = caller_locals() @@ -134,12 +138,11 @@ def extends(*specs): if extendees: raise RelationError("Packages can extend at most one other package.") - for string in specs: - for spec in spack.spec.parse(string): - if pkg == spec.name: - raise CircularReferenceError('extends', pkg) - dependencies[spec.name] = spec - extendees[spec.name] = spec + spec = Spec(spec) + if pkg == spec.name: + raise CircularReferenceError('extends', pkg) + dependencies[spec.name] = spec + extendees[spec.name] = (spec, kwargs) def provides(*specs, **kwargs): diff --git a/var/spack/packages/python/package.py b/var/spack/packages/python/package.py index 9700179ab8..86b903bc23 100644 --- a/var/spack/packages/python/package.py +++ b/var/spack/packages/python/package.py @@ -28,6 +28,16 @@ class Python(Package): make("install") + @property + def python_lib_dir(self): + return os.path.join('lib', 'python%d.%d' % self.version[:2]) + + + @property + def site_packages_dir(self): + return os.path.join(self.python_lib_dir, 'site-packages') + + def setup_extension_environment(self, module, spec, ext_spec): """Called before python modules' install() methods. @@ -39,11 +49,29 @@ class Python(Package): module.python = Executable(join_path(spec.prefix.bin, 'python')) # Add variables for lib/pythonX.Y and lib/pythonX.Y/site-packages dirs. - module.python_lib_dir = join_path(ext_spec.prefix.lib, 'python%d.%d' % self.version[:2]) - module.site_packages_dir = join_path(module.python_lib_dir, 'site-packages') + module.python_lib_dir = os.path.join(ext_spec.prefix, self.python_lib_dir) + module.site_packages_dir = os.path.join(ext_spec.prefix, self.site_packages_dir) # Add site packages directory to the PYTHONPATH os.environ['PYTHONPATH'] = module.site_packages_dir # Make the site packages directory if it does not exist already. mkdirp(module.site_packages_dir) + + + def add_ignore_files(self, args): + """Add some ignore files to activate/deactivate args.""" + ignore = set(args.get('ignore', ())) + ignore.add(os.path.join(self.site_packages_dir, 'site.py')) + ignore.add(os.path.join(self.site_packages_dir, 'site.pyc')) + args.update(ignore=ignore) + + + def activate(self, ext_pkg, **args): + self.add_ignore_files(args) + super(Python, self).activate(ext_pkg, **args) + + + def deactivate(self, ext_pkg, **args): + self.add_ignore_files(args) + super(Python, self).deactivate(ext_pkg, **args) -- cgit v1.2.3-70-g09d2