Commit 56ae2d97 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Improve multiple inheritance for oldstyle classes

In particular, subclassing from (oldstyle_cls, newstyle_cls)
results in a newstyle class, since ClassType.__new__ defers
to any of the bases that are not oldstyle classes.
parent 4d36e4c5
......@@ -1092,6 +1092,18 @@ Done:
Py_DECREF(it);
return n;
}
extern "C" int PySequence_Contains(PyObject* seq, PyObject* ob) noexcept {
Py_ssize_t result;
if (PyType_HasFeature(seq->cls, Py_TPFLAGS_HAVE_SEQUENCE_IN)) {
PySequenceMethods* sqm = seq->cls->tp_as_sequence;
if (sqm != NULL && sqm->sq_contains != NULL)
return (*sqm->sq_contains)(seq, ob);
}
result = _PySequence_IterSearch(seq, ob, PY_ITERSEARCH_CONTAINS);
return Py_SAFE_DOWNCAST(result, Py_ssize_t, int);
}
extern "C" PyObject* PyObject_CallFunction(PyObject* callable, const char* format, ...) noexcept {
va_list va;
PyObject* args;
......
......@@ -16,6 +16,7 @@
#include "capi/typeobject.h"
#include "capi/types.h"
#include "runtime/classobj.h"
#include "runtime/objmodel.h"
namespace pyston {
......@@ -1607,11 +1608,8 @@ static int fill_classic_mro(PyObject* mro, PyObject* cls) {
if (PyList_Append(mro, cls) < 0)
return -1;
}
Py_FatalError("unimplemented");
// We should add multiple inheritance for old-style classes
#if 0
bases = ((PyClassObject*)cls)->cl_bases;
bases = ((BoxedClassobj*)cls)->bases;
assert(bases && PyTuple_Check(bases));
n = PyTuple_GET_SIZE(bases);
for (i = 0; i < n; i++) {
......@@ -1620,7 +1618,6 @@ static int fill_classic_mro(PyObject* mro, PyObject* cls) {
return -1;
}
return 0;
#endif
}
static PyObject* classic_mro(PyObject* cls) {
......
......@@ -451,10 +451,6 @@ extern "C" Py_ssize_t PySequence_Count(PyObject* o, PyObject* value) noexcept {
Py_FatalError("unimplemented");
}
extern "C" int PySequence_Contains(PyObject* o, PyObject* value) noexcept {
Py_FatalError("unimplemented");
}
extern "C" Py_ssize_t PySequence_Index(PyObject* o, PyObject* value) noexcept {
Py_FatalError("unimplemented");
}
......
......@@ -84,6 +84,15 @@ Box* classobjNew(Box* _cls, Box* _name, Box* _bases, Box** _args) {
raiseExcHelper(TypeError, "PyClass_New: bases must be a tuple");
BoxedTuple* bases = static_cast<BoxedTuple*>(_bases);
for (auto base : bases->elts) {
if (!PyClass_Check(base) && PyCallable_Check(base->cls)) {
Box* r = PyObject_CallFunctionObjArgs(base->cls, name, bases, dict, NULL);
if (!r)
throwCAPIException();
return r;
}
}
BoxedClassobj* made = new (cls) BoxedClassobj(name, bases);
made->giveAttr("__module__", boxString(getCurrentModule()->name()));
......
# __bases__ and __name__ not supported yet -- need to add a custom getattr() method for old style classes
class C():
pass
......@@ -166,3 +164,35 @@ try:
C.doesnt_exist
except AttributeError as e:
print e
class C():
pass
print type(C) # classobj
class D(C):
pass
print type(D) # classobj
# Inheriting from old + new style classes gives a new-style class
class E(C, object):
pass
print type(E) # type
class F(object, C):
pass
print type(F) # type
print type("aoeu", (str, object), {})
# ClassType has to defer to calling type(b) for the first non-oldstyle base
print type(ClassType("aoeu", (str, object), {}))
# Even if that is not a new-style class!
class MyCustomClass(object):
def __init__(self, *args, **kw):
print "init", args[:-1], kw
def __repr__(self):
return "<MCC>"
# type(MyCustomClass()) is MyCustomClass, which is callable, leading to another call to __init__
print ClassType("aoeu", (MyCustomClass(), ), {})
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