From a1c8ce82f2ac46278a5716fa92d4d06df6f49caf Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Mon, 12 Mar 2018 09:07:08 +0100 Subject: Constructing a SpecBuildInterface from another gives no inconsistent MRO (#7457) fixes #7239 --- lib/spack/llnl/util/lang.py | 14 +++++++++++++- lib/spack/spack/test/concretize.py | 21 +++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/spack/llnl/util/lang.py b/lib/spack/llnl/util/lang.py index 7189b6c0f3..e586bc268d 100644 --- a/lib/spack/llnl/util/lang.py +++ b/lib/spack/llnl/util/lang.py @@ -458,5 +458,17 @@ class ObjectWrapper(object): def __init__(self, wrapped_object): wrapped_cls = type(wrapped_object) wrapped_name = wrapped_cls.__name__ - self.__class__ = type(wrapped_name, (type(self), wrapped_cls), {}) + + # If the wrapped object is already an ObjectWrapper, or a derived class + # of it, adding type(self) in front of type(wrapped_object) + # results in an inconsistent MRO. + # + # TODO: the implementation below doesn't account for the case where we + # TODO: have different base classes of ObjectWrapper, say A and B, and + # TODO: we want to wrap an instance of A with B. + if type(self) not in wrapped_cls.__mro__: + self.__class__ = type(wrapped_name, (type(self), wrapped_cls), {}) + else: + self.__class__ = type(wrapped_name, (wrapped_cls,), {}) + self.__dict__ = wrapped_object.__dict__ diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py index 2611c91f87..2482452208 100644 --- a/lib/spack/spack/test/concretize.py +++ b/lib/spack/spack/test/concretize.py @@ -23,8 +23,10 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ############################################################################## import pytest +import llnl.util.lang import spack import spack.architecture + from spack.concretize import find_spec from spack.spec import Spec, CompilerSpec from spack.spec import ConflictsInSpecError, SpecError @@ -444,3 +446,22 @@ class TestConcretize(object): s._concrete = False assert not s.concrete + + @pytest.mark.regression('7239') + def test_regression_issue_7239(self): + # Constructing a SpecBuildInterface from another SpecBuildInterface + # results in an inconsistent MRO + + # Normal Spec + s = Spec('mpileaks') + s.concretize() + + assert llnl.util.lang.ObjectWrapper not in type(s).__mro__ + + # Spec wrapped in a build interface + build_interface = s['mpileaks'] + assert llnl.util.lang.ObjectWrapper in type(build_interface).__mro__ + + # Mimics asking the build interface from a build interface + build_interface = s['mpileaks']['mpileaks'] + assert llnl.util.lang.ObjectWrapper in type(build_interface).__mro__ -- cgit v1.2.3-70-g09d2