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.
This commit is contained in:
parent
4b6de78062
commit
4f9131fdc2
4 changed files with 51 additions and 1 deletions
|
@ -6,6 +6,7 @@
|
||||||
import hashlib
|
import hashlib
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
|
import inspect
|
||||||
|
|
||||||
import llnl.util.filesystem
|
import llnl.util.filesystem
|
||||||
import llnl.util.lang
|
import llnl.util.lang
|
||||||
|
@ -110,7 +111,30 @@ class FilePatch(Patch):
|
||||||
def __init__(self, pkg, relative_path, level, working_dir,
|
def __init__(self, pkg, relative_path, level, working_dir,
|
||||||
ordering_key=None):
|
ordering_key=None):
|
||||||
self.relative_path = relative_path
|
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)
|
super(FilePatch, self).__init__(pkg, abs_path, level, working_dir)
|
||||||
self.path = abs_path
|
self.path = abs_path
|
||||||
self._sha256 = None
|
self._sha256 = None
|
||||||
|
|
|
@ -123,6 +123,12 @@ def test_inheritance_of_diretives(self):
|
||||||
assert '~openblas' in s
|
assert '~openblas' in s
|
||||||
assert 'mpi' 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):
|
def test_dependency_extensions(self):
|
||||||
s = Spec('extension2')
|
s = Spec('extension2')
|
||||||
s.concretize()
|
s.concretize()
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
import os
|
import os
|
||||||
import filecmp
|
import filecmp
|
||||||
import pytest
|
import pytest
|
||||||
|
import collections
|
||||||
|
|
||||||
from llnl.util.filesystem import working_dir, mkdirp
|
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,
|
libelf, libdwarf, fake,
|
||||||
'builtin.mock.patch-several-dependencies',
|
'builtin.mock.patch-several-dependencies',
|
||||||
spec.package.package_dir)
|
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, '')
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
# Copyright 2013-2019 Lawrence Livermore National Security, LLC and other
|
||||||
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
|
||||||
|
from spack.pkg.builtin.mock.patch import Patch
|
||||||
|
|
||||||
|
|
||||||
|
class PatchInheritance(Patch):
|
||||||
|
def install(self, spec, prefix):
|
||||||
|
Patch.install(self, spec, prefix)
|
Loading…
Reference in a new issue