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:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user