Commit 10f3763a authored by Kevin Modzelewski's avatar Kevin Modzelewski

Test and implement some weird multiple-inheritance behavior

in regards to how the metaclass gets picked.
parent f75e8ea3
......@@ -799,7 +799,7 @@ CMAKE_SETUP_GCC := $(CMAKE_DIR_GCC)/build.ninja
$(CMAKE_SETUP_GCC):
@$(MAKE) cmake_check
@mkdir -p $(CMAKE_DIR_GCC)
cd $(CMAKE_DIR_GCC); CC='gcc' CXX='g++' cmake -GNinja $(HOME)/pyston -DCMAKE_BUILD_TYPE=Debug
cd $(CMAKE_DIR_GCC); CC='$(GCC)' CXX='$(GPP)' cmake -GNinja $(HOME)/pyston -DCMAKE_BUILD_TYPE=Debug
.PHONY: pyston_gcc
pyston_gcc: $(CMAKE_SETUP_GCC)
$(NINJA) -C $(HOME)/pyston-build-gcc pyston copy_stdlib copy_libpyston $(NINJAFLAGS)
......
......@@ -3670,9 +3670,8 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) {
if (winner != metatype) {
if (getattr(winner, "__new__") != getattr(type_cls, "__new__")) {
RELEASE_ASSERT(0, "untested");
return callattr(winner, &new_str, CallattrFlags({.cls_only = true, .null_on_nonexistent = false }),
ArgPassSpec(3), arg1, arg2, arg3, _args + 1, NULL);
return callattr(winner, &new_str, CallattrFlags({.cls_only = false, .null_on_nonexistent = false }),
ArgPassSpec(4), winner, arg1, arg2, _args, NULL);
}
metatype = winner;
}
......
# Test a relatively-obscure corner case of multiple inheritance:
# the metaclass is normally the first base's metaclass, but type_new
# will specifically delegate to a later base's metaclass if it is more
# derived.
# First, test what I'm guessing is the common case, where a later
# class is the only one with a non-default metaclass:
class C(object):
pass
class M(type):
def __new__(cls, *args):
print "M.__new__", cls
return type.__new__(cls, *args)
def __init__(self, *args):
print "M.__init__"
return type.__init__(self, *args)
class D(object):
__metaclass__ = M
print type(D)
class E(C, D):
pass
print type(E)
# Then, test to make sure that it's actually type_new that's doing this, and not
# the class creation machinery. We can check this by using an initial metatype that
# doesn't defer to type_new
class GreedyMeta(type):
def __new__(cls, name, bases, attrs):
print "GreedyMeta.__new__", cls
if 'make_for_real' in attrs:
return type.__new__(cls, name, bases, attrs)
return 12345
class F(object):
__metaclass__ = GreedyMeta
make_for_real = True
print F, type(F)
class G(F, D):
pass
print G
# Constructing the class with the bases in the opposite order will fail,
# since this will end up calling M.__new__ -> type.__new__, and type_new
# does some extra checks, that we skipped with GreedyMeta.
try:
class H(D, F):
pass
except TypeError as e:
print e
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment