diff --git a/mypyc/lib-rt/pythonsupport.c b/mypyc/lib-rt/pythonsupport.c index 90fb69705a00..0a99f0ae2e29 100644 --- a/mypyc/lib-rt/pythonsupport.c +++ b/mypyc/lib-rt/pythonsupport.c @@ -5,6 +5,109 @@ #include "pythonsupport.h" +///////////////////////////////////////// +// Adapted from bltinmodule.c in Python 3.7.0 +PyObject* +update_bases(PyObject *bases) +{ + Py_ssize_t i, j; + PyObject *base, *meth, *new_base, *result, *new_bases = NULL; + PyObject *stack[1] = {bases}; + assert(PyTuple_Check(bases)); + + Py_ssize_t nargs = PyTuple_GET_SIZE(bases); + for (i = 0; i < nargs; i++) { + base = PyTuple_GET_ITEM(bases, i); + if (PyType_Check(base)) { + if (new_bases) { + /* If we already have made a replacement, then we append every normal base, + otherwise just skip it. */ + if (PyList_Append(new_bases, base) < 0) { + goto error; + } + } + continue; + } + if (PyObject_GetOptionalAttr(base, mypyc_interned_str.__mro_entries__, &meth) < 0) { + goto error; + } + if (!meth) { + if (new_bases) { + if (PyList_Append(new_bases, base) < 0) { + goto error; + } + } + continue; + } + new_base = PyObject_Vectorcall(meth, stack, 1, NULL); + Py_DECREF(meth); + if (!new_base) { + goto error; + } + if (!PyTuple_Check(new_base)) { + PyErr_SetString(PyExc_TypeError, + "__mro_entries__ must return a tuple"); + Py_DECREF(new_base); + goto error; + } + if (!new_bases) { + /* If this is a first successful replacement, create new_bases list and + copy previously encountered bases. */ + if (!(new_bases = PyList_New(i))) { + goto error; + } + for (j = 0; j < i; j++) { + base = PyTuple_GET_ITEM(bases, j); + PyList_SET_ITEM(new_bases, j, base); + Py_INCREF(base); + } + } + j = PyList_GET_SIZE(new_bases); + if (PyList_SetSlice(new_bases, j, j, new_base) < 0) { + goto error; + } + Py_DECREF(new_base); + } + if (!new_bases) { + return bases; + } + result = PyList_AsTuple(new_bases); + Py_DECREF(new_bases); + return result; + +error: + Py_XDECREF(new_bases); + return NULL; +} + +// From Python 3.7's typeobject.c +int +init_subclass(PyTypeObject *type, PyObject *kwds) +{ + PyObject *super, *func, *result; + PyObject *args[2] = {(PyObject *)type, (PyObject *)type}; + + super = PyObject_Vectorcall((PyObject *)&PySuper_Type, args, 2, NULL); + if (super == NULL) { + return -1; + } + + func = PyObject_GetAttr(super, mypyc_interned_str.__init_subclass__); + Py_DECREF(super); + if (func == NULL) { + return -1; + } + + result = _PyObject_FastCallDict(func, NULL, 0, kwds); + Py_DECREF(func); + if (result == NULL) { + return -1; + } + + Py_DECREF(result); + return 0; +} + #if CPY_3_12_FEATURES // Slow path of CPyLong_AsSsize_tAndOverflow (non-inlined) diff --git a/mypyc/lib-rt/pythonsupport.h b/mypyc/lib-rt/pythonsupport.h index 1d29bdb6ab77..4c82ff6a3c03 100644 --- a/mypyc/lib-rt/pythonsupport.h +++ b/mypyc/lib-rt/pythonsupport.h @@ -34,108 +34,8 @@ extern "C" { } // why isn't emacs smart enough to not indent this #endif -///////////////////////////////////////// -// Adapted from bltinmodule.c in Python 3.7.0 -static PyObject* -update_bases(PyObject *bases) -{ - Py_ssize_t i, j; - PyObject *base, *meth, *new_base, *result, *new_bases = NULL; - PyObject *stack[1] = {bases}; - assert(PyTuple_Check(bases)); - - Py_ssize_t nargs = PyTuple_GET_SIZE(bases); - for (i = 0; i < nargs; i++) { - base = PyTuple_GET_ITEM(bases, i); - if (PyType_Check(base)) { - if (new_bases) { - /* If we already have made a replacement, then we append every normal base, - otherwise just skip it. */ - if (PyList_Append(new_bases, base) < 0) { - goto error; - } - } - continue; - } - if (PyObject_GetOptionalAttrString(base, "__mro_entries__", &meth) < 0) { - goto error; - } - if (!meth) { - if (new_bases) { - if (PyList_Append(new_bases, base) < 0) { - goto error; - } - } - continue; - } - new_base = PyObject_Vectorcall(meth, stack, 1, NULL); - Py_DECREF(meth); - if (!new_base) { - goto error; - } - if (!PyTuple_Check(new_base)) { - PyErr_SetString(PyExc_TypeError, - "__mro_entries__ must return a tuple"); - Py_DECREF(new_base); - goto error; - } - if (!new_bases) { - /* If this is a first successful replacement, create new_bases list and - copy previously encountered bases. */ - if (!(new_bases = PyList_New(i))) { - goto error; - } - for (j = 0; j < i; j++) { - base = PyTuple_GET_ITEM(bases, j); - PyList_SET_ITEM(new_bases, j, base); - Py_INCREF(base); - } - } - j = PyList_GET_SIZE(new_bases); - if (PyList_SetSlice(new_bases, j, j, new_base) < 0) { - goto error; - } - Py_DECREF(new_base); - } - if (!new_bases) { - return bases; - } - result = PyList_AsTuple(new_bases); - Py_DECREF(new_bases); - return result; - -error: - Py_XDECREF(new_bases); - return NULL; -} - -// From Python 3.7's typeobject.c -static int -init_subclass(PyTypeObject *type, PyObject *kwds) -{ - PyObject *super, *func, *result; - PyObject *args[2] = {(PyObject *)type, (PyObject *)type}; - - super = PyObject_Vectorcall((PyObject *)&PySuper_Type, args, 2, NULL); - if (super == NULL) { - return -1; - } - - func = PyObject_GetAttrString(super, "__init_subclass__"); - Py_DECREF(super); - if (func == NULL) { - return -1; - } - - result = _PyObject_FastCallDict(func, NULL, 0, kwds); - Py_DECREF(func); - if (result == NULL) { - return -1; - } - - Py_DECREF(result); - return 0; -} +PyObject* update_bases(PyObject *bases); +int init_subclass(PyTypeObject *type, PyObject *kwds); Py_ssize_t CPyLong_AsSsize_tAndOverflow_(PyObject *vv, int *overflow);