aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sources/shiboken6/libshiboken/sbktypefactory.cpp266
1 files changed, 261 insertions, 5 deletions
diff --git a/sources/shiboken6/libshiboken/sbktypefactory.cpp b/sources/shiboken6/libshiboken/sbktypefactory.cpp
index b560cdb95..08d6775f4 100644
--- a/sources/shiboken6/libshiboken/sbktypefactory.cpp
+++ b/sources/shiboken6/libshiboken/sbktypefactory.cpp
@@ -68,6 +68,16 @@ PyTypeObject *SbkType_FromSpecBasesMeta(PyType_Spec *spec, PyObject *bases, PyTy
return SbkType_FromSpec_BMDWBD(spec, bases, meta, 0, 0, nullptr, nullptr);
}
+#ifdef PYPY_VERSION
+
+static PyObject *_PyType_FromSpecWithBases(PyType_Spec *, PyObject *);
+
+#else
+
+#define _PyType_FromSpecWithBases PyType_FromSpecWithBases
+
+#endif // PYPY_VERSION
+
PyTypeObject *SbkType_FromSpec_BMDWBD(PyType_Spec *spec,
PyObject *bases,
PyTypeObject *meta,
@@ -93,7 +103,7 @@ PyTypeObject *SbkType_FromSpec_BMDWBD(PyType_Spec *spec,
int package_level = atoi(spec->name);
const char *mod = new_spec.name = colon + 1;
- PyObject *obType = PyType_FromSpecWithBases(&new_spec, bases);
+ PyObject *obType = _PyType_FromSpecWithBases(&new_spec, bases);
if (obType == nullptr)
return nullptr;
@@ -107,10 +117,6 @@ PyTypeObject *SbkType_FromSpec_BMDWBD(PyType_Spec *spec,
int mlen = qual - mod - 1;
Shiboken::AutoDecRef module(Shiboken::String::fromCString(mod, mlen));
Shiboken::AutoDecRef qualname(Shiboken::String::fromCString(qual));
- if (PyObject_SetAttr(obType, Shiboken::PyMagicName::module(), module) < 0)
- return nullptr;
- if (PyObject_SetAttr(obType, Shiboken::PyMagicName::qualname(), qualname) < 0)
- return nullptr;
auto *type = reinterpret_cast<PyTypeObject *>(obType);
@@ -131,8 +137,258 @@ PyTypeObject *SbkType_FromSpec_BMDWBD(PyType_Spec *spec,
if (dict_add)
PyDict_Update(reinterpret_cast<PyObject *>(type->tp_dict), dict_add);
+#ifdef PYPY_VERSION
+ // PYSIDE-535: Careful: Using PyObject_SetAttr would have the side-effect of calling
+ // PyType_Ready too early. (at least in PyPy, which caused pretty long debugging.)
+ auto *ht = reinterpret_cast<PyHeapTypeObject *>(type);
+ ht->ht_qualname = qualname;
+ if (PyDict_SetItem(type->tp_dict, Shiboken::PyMagicName::qualname(), qualname))
+ return nullptr;
+ if (PyDict_SetItem(type->tp_dict, Shiboken::PyMagicName::module(), module))
+ return nullptr;
+ PyType_Ready(type);
+#else
+ if (PyObject_SetAttr(obType, Shiboken::PyMagicName::module(), module) < 0)
+ return nullptr;
+ if (PyObject_SetAttr(obType, Shiboken::PyMagicName::qualname(), qualname) < 0)
+ return nullptr;
PyType_Modified(type);
+#endif
return type;
}
+#ifdef PYPY_VERSION
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Reimplementation of `PyType_FromSpecWithBases`
+//
+// This is almost the original code from Python 3.7 with a few changes.
+// Especially the call to `PyType_Ready` is deferred until the needed
+// post-actions are carried out in `SbkType_FromSpec_BMDWBD`.
+//
+// FIXME remove ASAP.
+// Version is not clear, yet. Current version == 7.3.6
+//
+
+static const short slotoffsets[] = {
+ -1, /* invalid slot */
+/* Generated by typeslots.py */
+0,
+0,
+offsetof(PyHeapTypeObject, as_mapping.mp_ass_subscript),
+offsetof(PyHeapTypeObject, as_mapping.mp_length),
+offsetof(PyHeapTypeObject, as_mapping.mp_subscript),
+offsetof(PyHeapTypeObject, as_number.nb_absolute),
+offsetof(PyHeapTypeObject, as_number.nb_add),
+offsetof(PyHeapTypeObject, as_number.nb_and),
+offsetof(PyHeapTypeObject, as_number.nb_bool),
+offsetof(PyHeapTypeObject, as_number.nb_divmod),
+offsetof(PyHeapTypeObject, as_number.nb_float),
+offsetof(PyHeapTypeObject, as_number.nb_floor_divide),
+offsetof(PyHeapTypeObject, as_number.nb_index),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_add),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_and),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_floor_divide),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_lshift),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_multiply),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_or),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_power),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_remainder),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_rshift),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_subtract),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_true_divide),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_xor),
+offsetof(PyHeapTypeObject, as_number.nb_int),
+offsetof(PyHeapTypeObject, as_number.nb_invert),
+offsetof(PyHeapTypeObject, as_number.nb_lshift),
+offsetof(PyHeapTypeObject, as_number.nb_multiply),
+offsetof(PyHeapTypeObject, as_number.nb_negative),
+offsetof(PyHeapTypeObject, as_number.nb_or),
+offsetof(PyHeapTypeObject, as_number.nb_positive),
+offsetof(PyHeapTypeObject, as_number.nb_power),
+offsetof(PyHeapTypeObject, as_number.nb_remainder),
+offsetof(PyHeapTypeObject, as_number.nb_rshift),
+offsetof(PyHeapTypeObject, as_number.nb_subtract),
+offsetof(PyHeapTypeObject, as_number.nb_true_divide),
+offsetof(PyHeapTypeObject, as_number.nb_xor),
+offsetof(PyHeapTypeObject, as_sequence.sq_ass_item),
+offsetof(PyHeapTypeObject, as_sequence.sq_concat),
+offsetof(PyHeapTypeObject, as_sequence.sq_contains),
+offsetof(PyHeapTypeObject, as_sequence.sq_inplace_concat),
+offsetof(PyHeapTypeObject, as_sequence.sq_inplace_repeat),
+offsetof(PyHeapTypeObject, as_sequence.sq_item),
+offsetof(PyHeapTypeObject, as_sequence.sq_length),
+offsetof(PyHeapTypeObject, as_sequence.sq_repeat),
+offsetof(PyHeapTypeObject, ht_type.tp_alloc),
+offsetof(PyHeapTypeObject, ht_type.tp_base),
+offsetof(PyHeapTypeObject, ht_type.tp_bases),
+offsetof(PyHeapTypeObject, ht_type.tp_call),
+offsetof(PyHeapTypeObject, ht_type.tp_clear),
+offsetof(PyHeapTypeObject, ht_type.tp_dealloc),
+offsetof(PyHeapTypeObject, ht_type.tp_del),
+offsetof(PyHeapTypeObject, ht_type.tp_descr_get),
+offsetof(PyHeapTypeObject, ht_type.tp_descr_set),
+offsetof(PyHeapTypeObject, ht_type.tp_doc),
+offsetof(PyHeapTypeObject, ht_type.tp_getattr),
+offsetof(PyHeapTypeObject, ht_type.tp_getattro),
+offsetof(PyHeapTypeObject, ht_type.tp_hash),
+offsetof(PyHeapTypeObject, ht_type.tp_init),
+offsetof(PyHeapTypeObject, ht_type.tp_is_gc),
+offsetof(PyHeapTypeObject, ht_type.tp_iter),
+offsetof(PyHeapTypeObject, ht_type.tp_iternext),
+offsetof(PyHeapTypeObject, ht_type.tp_methods),
+offsetof(PyHeapTypeObject, ht_type.tp_new),
+offsetof(PyHeapTypeObject, ht_type.tp_repr),
+offsetof(PyHeapTypeObject, ht_type.tp_richcompare),
+offsetof(PyHeapTypeObject, ht_type.tp_setattr),
+offsetof(PyHeapTypeObject, ht_type.tp_setattro),
+offsetof(PyHeapTypeObject, ht_type.tp_str),
+offsetof(PyHeapTypeObject, ht_type.tp_traverse),
+offsetof(PyHeapTypeObject, ht_type.tp_members),
+offsetof(PyHeapTypeObject, ht_type.tp_getset),
+offsetof(PyHeapTypeObject, ht_type.tp_free),
+offsetof(PyHeapTypeObject, as_number.nb_matrix_multiply),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_matrix_multiply),
+offsetof(PyHeapTypeObject, as_async.am_await),
+offsetof(PyHeapTypeObject, as_async.am_aiter),
+offsetof(PyHeapTypeObject, as_async.am_anext),
+offsetof(PyHeapTypeObject, ht_type.tp_finalize),
+};
+
+static PyTypeObject *
+best_base(PyObject *bases)
+{
+ // We always have only one base
+ return reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(bases, 0));
+}
+
+static PyObject *
+_PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases)
+{
+ PyHeapTypeObject *res = reinterpret_cast<PyHeapTypeObject *>(
+ PyType_GenericAlloc(&PyType_Type, 0));
+ PyTypeObject *type, *base;
+ PyObject *modname;
+ char *s;
+ char *res_start = reinterpret_cast<char *>(res);
+ PyType_Slot *slot;
+
+ if (res == nullptr)
+ return nullptr;
+
+ if (spec->name == nullptr) {
+ PyErr_SetString(PyExc_SystemError,
+ "Type spec does not define the name field.");
+ goto fail;
+ }
+
+ /* Set the type name and qualname */
+ s = strrchr(const_cast<char *>(spec->name), '.');
+ if (s == nullptr)
+ s = (char*)spec->name;
+ else
+ s++;
+
+ type = &res->ht_type;
+ /* The flags must be initialized early, before the GC traverses us */
+ type->tp_flags = spec->flags | Py_TPFLAGS_HEAPTYPE;
+ res->ht_name = PyUnicode_FromString(s);
+ if (!res->ht_name)
+ goto fail;
+ res->ht_qualname = res->ht_name;
+ Py_INCREF(res->ht_qualname);
+ type->tp_name = spec->name;
+
+ /* Adjust for empty tuple bases */
+ if (!bases) {
+ base = &PyBaseObject_Type;
+ /* See whether Py_tp_base(s) was specified */
+ for (slot = spec->slots; slot->slot; slot++) {
+ if (slot->slot == Py_tp_base)
+ base = reinterpret_cast<PyTypeObject *>(slot->pfunc);
+ else if (slot->slot == Py_tp_bases) {
+ bases = reinterpret_cast<PyObject *>(slot->pfunc);
+ Py_INCREF(bases);
+ }
+ }
+ if (!bases)
+ bases = PyTuple_Pack(1, base);
+ if (!bases)
+ goto fail;
+ }
+ else
+ Py_INCREF(bases);
+
+ /* Calculate best base, and check that all bases are type objects */
+ base = best_base(bases);
+ if (base == nullptr) {
+ goto fail;
+ }
+
+ /* Initialize essential fields */
+ type->tp_as_async = &res->as_async;
+ type->tp_as_number = &res->as_number;
+ type->tp_as_sequence = &res->as_sequence;
+ type->tp_as_mapping = &res->as_mapping;
+ type->tp_as_buffer = &res->as_buffer;
+ /* Set tp_base and tp_bases */
+ type->tp_bases = bases;
+ bases = nullptr;
+ Py_INCREF(base);
+ type->tp_base = base;
+
+ type->tp_basicsize = spec->basicsize;
+ type->tp_itemsize = spec->itemsize;
+
+ for (slot = spec->slots; slot->slot; slot++) {
+ if (slot->slot == Py_tp_base || slot->slot == Py_tp_bases)
+ /* Processed above */
+ continue;
+ *reinterpret_cast<void **>(res_start + slotoffsets[slot->slot]) = slot->pfunc;
+
+ /* need to make a copy of the docstring slot, which usually
+ points to a static string literal */
+ if (slot->slot == Py_tp_doc) {
+ const char *old_doc = reinterpret_cast<char *>(slot->pfunc);
+ //_PyType_DocWithoutSignature(type->tp_name, slot->pfunc);
+ size_t len = strlen(old_doc)+1;
+ char *tp_doc = reinterpret_cast<char *>(PyObject_MALLOC(len));
+ if (tp_doc == nullptr) {
+ type->tp_doc = nullptr;
+ PyErr_NoMemory();
+ goto fail;
+ }
+ memcpy(tp_doc, old_doc, len);
+ type->tp_doc = tp_doc;
+ }
+ }
+ if (type->tp_dealloc == nullptr) {
+ /* It's a heap type, so needs the heap types' dealloc.
+ subtype_dealloc will call the base type's tp_dealloc, if
+ necessary. */
+ type->tp_dealloc = _PyPy_subtype_dealloc;
+ }
+
+ /// Here is the only change needed: Do not finalize type creation.
+ // if (PyType_Ready(type) < 0)
+ // goto fail;
+ type->tp_dict = PyDict_New();
+ /// This is not found in PyPy:
+ // if (type->tp_dictoffset) {
+ // res->ht_cached_keys = _PyDict_NewKeysForClass();
+ // }
+
+ /* Set type.__module__ */
+ /// Removed __module__ handling, already implemented.
+
+ return (PyObject*)res;
+
+ fail:
+ Py_DECREF(res);
+ return nullptr;
+}
+
+#endif // PYPY_VERSION
+
} //extern "C"