diff options
author | Greg Becker <becker33@llnl.gov> | 2019-07-19 20:08:05 -0500 |
---|---|---|
committer | Tamara Dahlgren <35777542+tldahlgren@users.noreply.github.com> | 2019-07-19 18:08:05 -0700 |
commit | 4f9131fdc2ff2d9e6c62da15f82ce7384e70895b (patch) | |
tree | 124431c02894216297beb796aa4ff03d32684d41 /lib | |
parent | 4b6de7806218d4ee19ab5a40ed781a44032b80c7 (diff) | |
download | spack-4f9131fdc2ff2d9e6c62da15f82ce7384e70895b.tar.gz spack-4f9131fdc2ff2d9e6c62da15f82ce7384e70895b.tar.bz2 spack-4f9131fdc2ff2d9e6c62da15f82ce7384e70895b.tar.xz spack-4f9131fdc2ff2d9e6c62da15f82ce7384e70895b.zip |
Package inheritance: Find patch files defined in parent classes using MRO (#12051)
Fixes #8908, 11844
Use Python MRO to find patch files from parent classes.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/spack/spack/patch.py | 26 | ||||
-rw-r--r-- | lib/spack/spack/test/packages.py | 6 | ||||
-rw-r--r-- | lib/spack/spack/test/patch.py | 9 |
3 files changed, 40 insertions, 1 deletions
diff --git a/lib/spack/spack/patch.py b/lib/spack/spack/patch.py index ef03c54f45..09aa48d9da 100644 --- a/lib/spack/spack/patch.py +++ b/lib/spack/spack/patch.py @@ -6,6 +6,7 @@ import hashlib import os import os.path +import inspect import llnl.util.filesystem import llnl.util.lang @@ -110,7 +111,30 @@ class FilePatch(Patch): def __init__(self, pkg, relative_path, level, working_dir, ordering_key=None): self.relative_path = relative_path - abs_path = os.path.join(pkg.package_dir, self.relative_path) + + # patches may be defined by relative paths to parent classes + # search mro to look for the file + abs_path = None + # At different times we call FilePatch on instances and classes + pkg_cls = pkg if inspect.isclass(pkg) else pkg.__class__ + for cls in inspect.getmro(pkg_cls): + if not hasattr(cls, 'module'): + # We've gone too far up the MRO + break + + # Cannot use pkg.package_dir because it's a property and we have + # classes, not instances. + pkg_dir = os.path.abspath(os.path.dirname(cls.module.__file__)) + path = os.path.join(pkg_dir, self.relative_path) + if os.path.exists(path): + abs_path = path + break + + if abs_path is None: + msg = 'FilePatch: Patch file %s for ' % relative_path + msg += 'package %s.%s does not exist.' % (pkg.namespace, pkg.name) + raise ValueError(msg) + super(FilePatch, self).__init__(pkg, abs_path, level, working_dir) self.path = abs_path self._sha256 = None diff --git a/lib/spack/spack/test/packages.py b/lib/spack/spack/test/packages.py index 43f1719ca3..145c8fb2aa 100644 --- a/lib/spack/spack/test/packages.py +++ b/lib/spack/spack/test/packages.py @@ -123,6 +123,12 @@ class TestPackage(object): assert '~openblas' in s assert 'mpi' in s + @pytest.mark.regression('11844') + def test_inheritance_of_patches(self): + s = Spec('patch-inheritance') + # Will error if inheritor package cannot find inherited patch files + s.concretize() + def test_dependency_extensions(self): s = Spec('extension2') s.concretize() diff --git a/lib/spack/spack/test/patch.py b/lib/spack/spack/test/patch.py index 13a0233fb1..5ea3ba65bc 100644 --- a/lib/spack/spack/test/patch.py +++ b/lib/spack/spack/test/patch.py @@ -6,6 +6,7 @@ import os import filecmp import pytest +import collections from llnl.util.filesystem import working_dir, mkdirp @@ -314,3 +315,11 @@ def test_write_and_read_sub_dags_with_patched_deps(mock_packages, config): libelf, libdwarf, fake, 'builtin.mock.patch-several-dependencies', spec.package.package_dir) + + +def test_file_patch_no_file(): + # Give it the attributes we need to construct the error message + FakePackage = collections.namedtuple('FakePackage', ['name', 'namespace']) + fp = FakePackage('fake-package', 'test') + with pytest.raises(ValueError, match=r'FilePatch:.*'): + spack.patch.FilePatch(fp, 'nonexistent_file', 0, '') |