Make multimethods work with inheritance. (#3411)
Previously, this would fail with a NoSuchMethodError: class Package(object): # this is the default implementation def some_method(self): ... class Foo(Package): @when('platform=cray') def some_method(self): ... @when('platform=linux') def some_method(self): ... This fixes the implementation of `@when` so that the superclass method will be invoked when no subclass method matches. Adds tests to ensure this works, as well.
This commit is contained in:
@@ -128,10 +128,16 @@ def __call__(self, package_self, *args, **kwargs):
|
||||
|
||||
if self.default:
|
||||
return self.default(package_self, *args, **kwargs)
|
||||
|
||||
else:
|
||||
raise NoSuchMethodError(
|
||||
type(package_self), self.__name__, spec,
|
||||
[m[0] for m in self.method_list])
|
||||
superclass = super(package_self.__class__, package_self)
|
||||
superclass_fn = getattr(superclass, self.__name__, None)
|
||||
if callable(superclass_fn):
|
||||
return superclass_fn(*args, **kwargs)
|
||||
else:
|
||||
raise NoSuchMethodError(
|
||||
type(package_self), self.__name__, spec,
|
||||
[m[0] for m in self.method_list])
|
||||
|
||||
def __str__(self):
|
||||
return "SpecMultiMethod {\n\tdefault: %s,\n\tspecs: %s\n}" % (
|
||||
|
@@ -118,3 +118,11 @@ def test_virtual_dep_match(builtin_mock):
|
||||
|
||||
pkg = spack.repo.get('multimethod^mpich@1.0')
|
||||
assert pkg.different_by_virtual_dep() == 1
|
||||
|
||||
|
||||
def test_multimethod_with_base_class(builtin_mock):
|
||||
pkg = spack.repo.get('multimethod@3')
|
||||
assert pkg.base_method() == "subclass_method"
|
||||
|
||||
pkg = spack.repo.get('multimethod@1')
|
||||
assert pkg.base_method() == "base_method"
|
||||
|
Reference in New Issue
Block a user