Fix the type value of 'bpy.types.*.bl_rna'

The type of an RNA types "bl_rna" should be `bpy.types.Struct`,
it was being set to the type it represented so:
`type(bpy.types.Object.bl_rna) == bpy.types.Object`
which wasn't correct.

Ref !126877

Co-authored-by: Bastien Montagne <bastien@blender.org>
This commit is contained in:
Campbell Barton
2024-08-28 15:10:46 +10:00
parent 25b2c5f170
commit 21b820cd33

View File

@@ -90,6 +90,11 @@
BPy_StructRNA *bpy_context_module = nullptr; /* for fast access */
static PyObject *pyrna_struct_CreatePyObject_from_type(PointerRNA *ptr,
PyTypeObject *tp,
void **instance);
static PyObject *pyrna_srna_Subtype(StructRNA *srna);
static PyObject *pyrna_struct_Subtype(PointerRNA *ptr);
static PyObject *pyrna_prop_collection_values(BPy_PropertyRNA *self);
@@ -7347,8 +7352,6 @@ static void pyrna_prop_collection_iter_dealloc(BPy_PropertyCollectionIterRNA *se
static void pyrna_subtype_set_rna(PyObject *newclass, StructRNA *srna)
{
PyObject *item;
Py_INCREF(newclass);
if (PyObject *oldclass = static_cast<PyObject *>(RNA_struct_py_type_get(srna))) {
@@ -7362,12 +7365,25 @@ static void pyrna_subtype_set_rna(PyObject *newclass, StructRNA *srna)
/* Python deals with the circular reference. */
PointerRNA ptr = RNA_pointer_create(nullptr, &RNA_Struct, srna);
item = pyrna_struct_CreatePyObject(&ptr);
/* NOTE: must set the class not the __dict__ else the internal slots are not updated correctly.
*/
PyObject_SetAttr(newclass, bpy_intern_str_bl_rna, item);
Py_DECREF(item);
/* NOTE: using `pyrna_struct_CreatePyObject(&ptr)` is close to what is needed,
* however the it isn't correct because the result of:
* `type(bpy.types.Object.bl_rna) == bpy.types.Object`.
* In this case the type of `bl_rna` should be `bpy.types.Struct`.
* This is passed in explicitly, while #pyrna_struct_CreatePyObject could
* take this as an argument it's such a corner case that using a lower level
* function that takes the type is preferable. */
{
BLI_assert(RNA_struct_instance(&ptr) == nullptr);
PyTypeObject *tp = (PyTypeObject *)pyrna_srna_Subtype(&RNA_Struct);
PyObject *item = pyrna_struct_CreatePyObject_from_type(&ptr, tp, nullptr);
Py_DECREF(tp); /* `srna` owns, can't hold a reference. */
/* NOTE: must set the class not the `__dict__`
* else the internal slots are not updated correctly. */
PyObject_SetAttr(newclass, bpy_intern_str_bl_rna, item);
Py_DECREF(item);
}
/* Add `staticmethod` and `classmethod` functions. */
{
@@ -7392,8 +7408,6 @@ static void pyrna_subtype_set_rna(PyObject *newclass, StructRNA *srna)
/* Done with RNA instance. */
}
static PyObject *pyrna_srna_Subtype(StructRNA *srna);
/* Return a borrowed reference. */
static PyObject *pyrna_srna_PyBase(StructRNA *srna) //, PyObject *bpy_types_dict)
{
@@ -7604,38 +7618,16 @@ static PyObject *pyrna_struct_Subtype(PointerRNA *ptr)
/*-----------------------CreatePyObject---------------------------------*/
PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr)
/**
* A lower level version of #pyrna_struct_CreatePyObject,
* use this when type (`tp`) needs to be set to a non-standard value.
*/
static PyObject *pyrna_struct_CreatePyObject_from_type(PointerRNA *ptr,
PyTypeObject *tp,
void **instance)
{
BPy_StructRNA *pyrna = nullptr;
/* NOTE: don't rely on this to return None since nullptr data with a valid type can often crash.
*/
if (ptr->data == nullptr && ptr->type == nullptr) { /* Operator RNA has nullptr data. */
Py_RETURN_NONE;
}
/* New in 2.8x, since not many types support instancing
* we may want to use a flag to avoid looping over all classes. - campbell */
void **instance = ptr->data ? RNA_struct_instance(ptr) : nullptr;
if (instance && *instance) {
pyrna = static_cast<BPy_StructRNA *>(*instance);
/* Refine may have changed types after the first instance was created. */
if (ptr->type == pyrna->ptr.type) {
Py_INCREF(pyrna);
return (PyObject *)pyrna;
}
/* Existing users will need to use 'type_recast' method. */
Py_DECREF(pyrna);
*instance = nullptr;
/* Continue as if no instance was made. */
#if 0 /* No need to assign, will be written to next... */
pyrna = nullptr;
#endif
}
if (PyTypeObject *tp = (PyTypeObject *)pyrna_struct_Subtype(ptr)) {
if (tp) {
pyrna = (BPy_StructRNA *)tp->tp_alloc(tp, 0);
#ifdef USE_PYRNA_STRUCT_REFERENCE
/* #PyType_GenericAlloc will have set tracking.
@@ -7644,7 +7636,6 @@ PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr)
PyObject_GC_UnTrack(pyrna);
}
#endif
Py_DECREF(tp); /* srna owns, can't hold a reference. */
}
else {
CLOG_WARN(BPY_LOG_RNA, "could not make type '%s'", RNA_struct_identifier(ptr->type));
@@ -7698,6 +7689,43 @@ PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr)
return (PyObject *)pyrna;
}
PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr)
{
BPy_StructRNA *pyrna = nullptr;
/* NOTE: don't rely on this to return None since nullptr data with a valid type can often crash.
*/
if (ptr->data == nullptr && ptr->type == nullptr) { /* Operator RNA has nullptr data. */
Py_RETURN_NONE;
}
/* New in 2.8x, since not many types support instancing
* we may want to use a flag to avoid looping over all classes. - campbell */
void **instance = ptr->data ? RNA_struct_instance(ptr) : nullptr;
if (instance && *instance) {
pyrna = static_cast<BPy_StructRNA *>(*instance);
/* Refine may have changed types after the first instance was created. */
if (ptr->type == pyrna->ptr.type) {
Py_INCREF(pyrna);
return (PyObject *)pyrna;
}
/* Existing users will need to use 'type_recast' method. */
Py_DECREF(pyrna);
*instance = nullptr;
/* Continue as if no instance was made. */
#if 0 /* No need to assign, will be written to next... */
pyrna = nullptr;
#endif
}
PyTypeObject *tp = (PyTypeObject *)pyrna_struct_Subtype(ptr);
pyrna = (BPy_StructRNA *)pyrna_struct_CreatePyObject_from_type(ptr, tp, instance);
Py_XDECREF(tp); /* `srna` owns, can't hold a reference. */
return (PyObject *)pyrna;
}
PyObject *pyrna_struct_CreatePyObject_with_primitive_support(PointerRNA *ptr)
{
if (ptr->type == &RNA_PrimitiveString) {