Commit d5bc8147 authored by Robert Bradshaw's avatar Robert Bradshaw Committed by GitHub

Merge pull request #4107 from robertwb/cdef-mixin

Allow inheriting from cimported multiply inherited class.
parents 6d348059 b68f2585
...@@ -5248,13 +5248,13 @@ class CClassDefNode(ClassDefNode): ...@@ -5248,13 +5248,13 @@ class CClassDefNode(ClassDefNode):
self.type_init_args.generate_disposal_code(code) self.type_init_args.generate_disposal_code(code)
self.type_init_args.free_temps(code) self.type_init_args.free_temps(code)
self.generate_type_ready_code(self.entry, code, True) self.generate_type_ready_code(self.entry, code)
if self.body: if self.body:
self.body.generate_execution_code(code) self.body.generate_execution_code(code)
# Also called from ModuleNode for early init types. # Also called from ModuleNode for early init types.
@staticmethod @staticmethod
def generate_type_ready_code(entry, code, heap_type_bases=False): def generate_type_ready_code(entry, code):
# Generate a call to PyType_Ready for an extension # Generate a call to PyType_Ready for an extension
# type defined in this module. # type defined in this module.
type = entry.type type = entry.type
...@@ -5290,15 +5290,10 @@ class CClassDefNode(ClassDefNode): ...@@ -5290,15 +5290,10 @@ class CClassDefNode(ClassDefNode):
code.putln("#else") code.putln("#else")
for slot in TypeSlots.slot_table: for slot in TypeSlots.slot_table:
slot.generate_dynamic_init_code(scope, code) slot.generate_dynamic_init_code(scope, code)
if heap_type_bases: code.globalstate.use_utility_code(
code.globalstate.use_utility_code( UtilityCode.load_cached('PyType_Ready', 'ExtensionTypes.c'))
UtilityCode.load_cached('PyType_Ready', 'ExtensionTypes.c'))
readyfunc = "__Pyx_PyType_Ready"
else:
readyfunc = "PyType_Ready"
code.putln( code.putln(
"if (%s(&%s) < 0) %s" % ( "if (__Pyx_PyType_Ready(&%s) < 0) %s" % (
readyfunc,
typeobj_cname, typeobj_cname,
code.error_goto(entry.pos))) code.error_goto(entry.pos)))
# Don't inherit tp_print from builtin types in Python 2, restoring the # Don't inherit tp_print from builtin types in Python 2, restoring the
...@@ -5377,12 +5372,11 @@ class CClassDefNode(ClassDefNode): ...@@ -5377,12 +5372,11 @@ class CClassDefNode(ClassDefNode):
type.vtabptr_cname, type.vtabptr_cname,
code.error_goto(entry.pos))) code.error_goto(entry.pos)))
code.putln("#endif") code.putln("#endif")
if heap_type_bases: code.globalstate.use_utility_code(
code.globalstate.use_utility_code( UtilityCode.load_cached('MergeVTables', 'ImportExport.c'))
UtilityCode.load_cached('MergeVTables', 'ImportExport.c')) code.putln("if (__Pyx_MergeVtables(&%s) < 0) %s" % (
code.putln("if (__Pyx_MergeVtables(&%s) < 0) %s" % ( typeobj_cname,
typeobj_cname, code.error_goto(entry.pos)))
code.error_goto(entry.pos)))
if not type.scope.is_internal and not type.scope.directives.get('internal'): if not type.scope.is_internal and not type.scope.directives.get('internal'):
# scope.is_internal is set for types defined by # scope.is_internal is set for types defined by
# Cython (such as closures), the 'internal' # Cython (such as closures), the 'internal'
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
static int __Pyx_PyType_Ready(PyTypeObject *t); static int __Pyx_PyType_Ready(PyTypeObject *t);
/////////////// PyType_Ready /////////////// /////////////// PyType_Ready ///////////////
//@requires: ObjectHandling.c::PyObjectCallNoArg
// Wrapper around PyType_Ready() with some runtime checks and fixes // Wrapper around PyType_Ready() with some runtime checks and fixes
// to deal with multiple inheritance. // to deal with multiple inheritance.
...@@ -67,24 +68,35 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) { ...@@ -67,24 +68,35 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) {
// For details, see https://github.com/cython/cython/issues/3603 // For details, see https://github.com/cython/cython/issues/3603
PyObject *ret, *py_status; PyObject *ret, *py_status;
int gc_was_enabled; int gc_was_enabled;
PyObject *gc = PyImport_Import(PYUNICODE("gc")); static PyObject *gc = NULL;
if (unlikely(!gc)) return -1; static PyObject *gc_isenabled = NULL, *gc_enable = NULL, *gc_disable = NULL;
py_status = PyObject_CallMethodObjArgs(gc, PYUNICODE("isenabled"), NULL); if (unlikely(!gc)) {
gc = PyImport_Import(PYUNICODE("gc"));
if (unlikely(!gc)) return -1;
gc_isenabled = PyObject_GetAttr(gc, PYUNICODE("isenabled"));
gc_enable = PyObject_GetAttr(gc, PYUNICODE("enable"));
gc_disable = PyObject_GetAttr(gc, PYUNICODE("disable"));
if (unlikely(!gc_isenabled || !gc_enable || !gc_disable)) {
Py_XDECREF(gc_isenabled); gc_isenabled = NULL;
Py_XDECREF(gc_enable); gc_enable = NULL;
Py_XDECREF(gc_disable); gc_disable = NULL;
Py_XDECREF(gc); gc = NULL;
return -1;
}
}
py_status = __Pyx_PyObject_CallNoArg(gc_isenabled);
if (unlikely(!py_status)) { if (unlikely(!py_status)) {
Py_DECREF(gc);
return -1; return -1;
} }
gc_was_enabled = __Pyx_PyObject_IsTrue(py_status); gc_was_enabled = __Pyx_PyObject_IsTrue(py_status);
Py_DECREF(py_status); Py_DECREF(py_status);
if (gc_was_enabled > 0) { if (gc_was_enabled > 0) {
ret = PyObject_CallMethodObjArgs(gc, PYUNICODE("disable"), NULL); ret = __Pyx_PyObject_CallNoArg(gc_disable);
if (unlikely(!ret)) { if (unlikely(!ret)) {
Py_DECREF(gc);
return -1; return -1;
} }
Py_DECREF(ret); Py_DECREF(ret);
} else if (unlikely(gc_was_enabled == -1)) { } else if (unlikely(gc_was_enabled == -1)) {
Py_DECREF(gc);
return -1; return -1;
} }
...@@ -106,7 +118,7 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) { ...@@ -106,7 +118,7 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) {
if (gc_was_enabled) { if (gc_was_enabled) {
PyObject *t, *v, *tb; PyObject *t, *v, *tb;
PyErr_Fetch(&t, &v, &tb); PyErr_Fetch(&t, &v, &tb);
ret = PyObject_CallMethodObjArgs(gc, PYUNICODE("enable"), NULL); ret = __Pyx_PyObject_CallNoArg(gc_enable);
if (likely(ret || r == -1)) { if (likely(ret || r == -1)) {
Py_XDECREF(ret); Py_XDECREF(ret);
// do not overwrite exceptions raised by PyType_Ready() above // do not overwrite exceptions raised by PyType_Ready() above
...@@ -119,7 +131,6 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) { ...@@ -119,7 +131,6 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) {
r = -1; r = -1;
} }
} }
Py_DECREF(gc);
} }
#endif #endif
......
# Test for https://github.com/cython/cython/issues/4106
PYTHON setup.py build_ext --inplace
PYTHON -c "import sub"
######## setup.py ########
from Cython.Build import cythonize
from distutils.core import setup
setup(
ext_modules = cythonize("*.pyx"),
)
######## base.pxd ########
cdef class A:
cdef dict __dict__
cdef int a(self)
cdef class B(A):
cdef int b(self)
######## base.pyx ########
cdef class A:
cdef int a(self):
return 1
class PyA:
pass
cdef class B(A, PyA):
cdef int b(self):
return 2
######## sub.pyx ########
from base cimport B
print(B)
cdef class C(B):
cdef int c(self):
return 3
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