diff options
author | Sergey Sharybin <sergey@blender.org> | 2020-11-12 11:26:20 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey@blender.org> | 2020-11-12 11:26:20 +0300 |
commit | de6cee4fc1913982b0b2bd786bfd813c935bbe73 (patch) | |
tree | a726c0c63bbd1d6c47c90c32119ce14c8048cddc /source/blender/python/intern/bpy_rna.c | |
parent | e4d432500a0e2f978fe019da43deb843da405032 (diff) | |
parent | 88bb29dea668df8cc46aa7f55895f229748bdbb4 (diff) |
Merge branch 'master' into codesign_error_tracker
Diffstat (limited to 'source/blender/python/intern/bpy_rna.c')
-rw-r--r-- | source/blender/python/intern/bpy_rna.c | 366 |
1 files changed, 215 insertions, 151 deletions
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 0980d9df762..6e41bc96eed 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -80,6 +80,11 @@ #define USE_MATHUTILS #define USE_STRING_COERCE +/* Unfortunately Python needs to hold a global reference to the context. + * If we remove this is means `bpy.context` won't be usable from some parts of the code: + * `bpy.app.handler` callbacks for example. + * Even though this is arguably "correct", it's going to cause problems for existing scripts, + * so accept having this for the time being. */ BPy_StructRNA *bpy_context_module = NULL; /* for fast access */ static PyObject *pyrna_struct_Subtype(PointerRNA *ptr); @@ -457,7 +462,7 @@ static int mathutils_rna_vector_set(BaseMathObject *bmo, int subtype) RNA_property_float_set_array(&self->ptr, self->prop, bmo->data); if (RNA_property_update_check(self->prop)) { - RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); + RNA_property_update(BPY_context_get(), &self->ptr, self->prop); } /* Euler order exception. */ @@ -468,7 +473,7 @@ static int mathutils_rna_vector_set(BaseMathObject *bmo, int subtype) if (order != eul->order) { RNA_property_enum_set(&self->ptr, prop_eul_order, eul->order); if (RNA_property_update_check(prop_eul_order)) { - RNA_property_update(BPy_GetContext(), &self->ptr, prop_eul_order); + RNA_property_update(BPY_context_get(), &self->ptr, prop_eul_order); } } } @@ -517,7 +522,7 @@ static int mathutils_rna_vector_set_index(BaseMathObject *bmo, int UNUSED(subtyp RNA_property_float_set_index(&self->ptr, self->prop, index, bmo->data[index]); if (RNA_property_update_check(self->prop)) { - RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); + RNA_property_update(BPY_context_get(), &self->ptr, self->prop); } return 0; @@ -576,7 +581,7 @@ static int mathutils_rna_matrix_set(BaseMathObject *bmo, int UNUSED(subtype)) RNA_property_float_set_array(&self->ptr, self->prop, bmo->data); if (RNA_property_update_check(self->prop)) { - RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); + RNA_property_update(BPY_context_get(), &self->ptr, self->prop); } return 0; } @@ -722,7 +727,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) } else { /* Order will be updated from callback on use. */ - // TODO, get order from RNA + /* TODO, get order from RNA. */ PyObject *eul_cb = Euler_CreatePyObject_cb( ret, EULER_ORDER_XYZ, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_EUL); Py_DECREF(ret); /* The euler owns 'ret' now. */ @@ -890,22 +895,36 @@ static PyObject *pyrna_struct_str(BPy_StructRNA *self) { PyObject *ret; const char *name; + const char *extra_info = ""; if (!PYRNA_STRUCT_IS_VALID(self)) { return PyUnicode_FromFormat("<bpy_struct, %.200s invalid>", Py_TYPE(self)->tp_name); } - /* Print name if available. */ + ID *id = self->ptr.owner_id; + if (id && id != DEG_get_original_id(id)) { + extra_info = ", evaluated"; + } + + /* Print name if available. + * + * Always include the pointer address since it can help identify unique data, + * or when data is re-allocated internally. */ name = RNA_struct_name_get_alloc(&self->ptr, NULL, 0, NULL); if (name) { - ret = PyUnicode_FromFormat( - "<bpy_struct, %.200s(\"%.200s\")>", RNA_struct_identifier(self->ptr.type), name); + ret = PyUnicode_FromFormat("<bpy_struct, %.200s(\"%.200s\") at %p%s>", + RNA_struct_identifier(self->ptr.type), + name, + self->ptr.data, + extra_info); MEM_freeN((void *)name); return ret; } - return PyUnicode_FromFormat( - "<bpy_struct, %.200s at %p>", RNA_struct_identifier(self->ptr.type), self->ptr.data); + return PyUnicode_FromFormat("<bpy_struct, %.200s at %p%s>", + RNA_struct_identifier(self->ptr.type), + self->ptr.data, + extra_info); } static PyObject *pyrna_struct_repr(BPy_StructRNA *self) @@ -914,18 +933,14 @@ static PyObject *pyrna_struct_repr(BPy_StructRNA *self) PyObject *tmp_str; PyObject *ret; - if (id == NULL || !PYRNA_STRUCT_IS_VALID(self)) { + if (id == NULL || !PYRNA_STRUCT_IS_VALID(self) || (DEG_get_original_id(id) != id)) { /* fallback */ return pyrna_struct_str(self); } tmp_str = PyUnicode_FromString(id->name + 2); - if (DEG_get_original_id(id) != id) { - ret = PyUnicode_FromFormat( - "Evaluated %s %R", BKE_idtype_idcode_to_name(GS(id->name)), tmp_str); - } - else if (RNA_struct_is_ID(self->ptr.type) && (id->flag & LIB_EMBEDDED_DATA) == 0) { + if (RNA_struct_is_ID(self->ptr.type) && (id->flag & LIB_EMBEDDED_DATA) == 0) { ret = PyUnicode_FromFormat( "bpy.data.%s[%R]", BKE_idtype_idcode_to_name_plural(GS(id->name)), tmp_str); } @@ -1219,7 +1234,7 @@ static const char *pyrna_enum_as_string(PointerRNA *ptr, PropertyRNA *prop) const char *result; bool free = false; - RNA_property_enum_items(BPy_GetContext(), ptr, prop, &item, NULL, &free); + RNA_property_enum_items(BPY_context_get(), ptr, prop, &item, NULL, &free); if (item) { result = BPy_enum_as_string(item); } @@ -1247,7 +1262,7 @@ static int pyrna_string_to_enum( return -1; } - if (!RNA_property_enum_value(BPy_GetContext(), ptr, prop, param, r_value)) { + if (!RNA_property_enum_value(BPY_context_get(), ptr, prop, param, r_value)) { const char *enum_str = pyrna_enum_as_string(ptr, prop); PyErr_Format(PyExc_TypeError, "%.200s enum \"%.200s\" not found in (%s)", @@ -1389,7 +1404,7 @@ static int pyrna_prop_to_enum_bitfield( return -1; } - RNA_property_enum_items(BPy_GetContext(), ptr, prop, &item, NULL, &free); + RNA_property_enum_items(BPY_context_get(), ptr, prop, &item, NULL, &free); if (item) { ret = pyrna_set_to_enum_bitfield(item, value, r_value, error_prefix); @@ -1441,7 +1456,7 @@ static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val) ret = PySet_New(NULL); - if (RNA_property_enum_bitflag_identifiers(BPy_GetContext(), ptr, prop, val, identifier)) { + if (RNA_property_enum_bitflag_identifiers(BPY_context_get(), ptr, prop, val, identifier)) { int index; for (index = 0; identifier[index]; index++) { @@ -1453,7 +1468,7 @@ static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val) } else { const char *identifier; - if (RNA_property_enum_identifier(BPy_GetContext(), ptr, prop, val, &identifier)) { + if (RNA_property_enum_identifier(BPY_context_get(), ptr, prop, val, &identifier)) { ret = PyUnicode_FromString(identifier); } else { @@ -2202,7 +2217,7 @@ static int pyrna_py_to_prop( /* Run RNA property functions. */ if (RNA_property_update_check(prop)) { - RNA_property_update(BPy_GetContext(), ptr, prop); + RNA_property_update(BPY_context_get(), ptr, prop); } return 0; @@ -2278,7 +2293,7 @@ static int pyrna_py_to_prop_array_index(BPy_PropertyArrayRNA *self, int index, P /* Run RNA property functions. */ if (RNA_property_update_check(prop)) { - RNA_property_update(BPy_GetContext(), ptr, prop); + RNA_property_update(BPY_context_get(), ptr, prop); } return ret; @@ -3282,7 +3297,7 @@ static int pyrna_prop_array_ass_subscript(BPy_PropertyArrayRNA *self, if (ret != -1) { if (RNA_property_update_check(self->prop)) { - RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); + RNA_property_update(BPY_context_get(), &self->ptr, self->prop); } } @@ -3589,20 +3604,30 @@ static PyObject *pyrna_struct_values(BPy_PropertyRNA *self) } PyDoc_STRVAR(pyrna_struct_is_property_set_doc, - ".. method:: is_property_set(property)\n" + ".. method:: is_property_set(property, ghost=True)\n" "\n" " Check if a property is set, use for testing operator properties.\n" "\n" + " :arg ghost: Used for operators that re-run with previous settings.\n" + " In this case the property is not marked as set,\n" + " yet the value from the previous execution is used.\n" + "\n" + " In rare cases you may want to set this option to false.\n" + "\n" + " :type ghost: boolean\n" " :return: True when the property has been set.\n" " :rtype: boolean\n"); -static PyObject *pyrna_struct_is_property_set(BPy_StructRNA *self, PyObject *args) +static PyObject *pyrna_struct_is_property_set(BPy_StructRNA *self, PyObject *args, PyObject *kw) { PropertyRNA *prop; const char *name; + bool use_ghost = true; PYRNA_STRUCT_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "s:is_property_set", &name)) { + static const char *_keywords[] = {"", "ghost", NULL}; + static _PyArg_Parser _parser = {"s|$O&:is_property_set", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &name, PyC_ParseBool, &use_ghost)) { return NULL; } @@ -3614,7 +3639,7 @@ static PyObject *pyrna_struct_is_property_set(BPy_StructRNA *self, PyObject *arg return NULL; } - return PyBool_FromLong(RNA_property_is_set(&self->ptr, prop)); + return PyBool_FromLong(RNA_property_is_set_ex(&self->ptr, prop, use_ghost)); } PyDoc_STRVAR(pyrna_struct_property_unset_doc, @@ -3952,7 +3977,7 @@ PyDoc_STRVAR(pyrna_prop_update_doc, " however in rare cases it's useful to call explicitly.\n"); static PyObject *pyrna_prop_update(BPy_PropertyRNA *self) { - RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); + RNA_property_update(BPY_context_get(), &self->ptr, self->prop); Py_RETURN_NONE; } @@ -4250,9 +4275,9 @@ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname) ListBase newlb; short newtype; - const int done = CTX_data_get(C, name, &newptr, &newlb, &newtype); + const eContextResult done = CTX_data_get(C, name, &newptr, &newlb, &newtype); - if (done == 1) { /* Found. */ + if (done == CTX_RESULT_OK) { switch (newtype) { case CTX_DATA_TYPE_POINTER: if (newptr.data == NULL) { @@ -4285,7 +4310,7 @@ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname) break; } } - else if (done == -1) { /* Found, but not set. */ + else if (done == CTX_RESULT_NO_DATA) { ret = Py_None; Py_INCREF(ret); } @@ -4472,9 +4497,9 @@ static int pyrna_struct_setattro(BPy_StructRNA *self, PyObject *pyname, PyObject ListBase newlb; short newtype; - const int done = CTX_data_get(C, name, &newptr, &newlb, &newtype); + const eContextResult done = CTX_data_get(C, name, &newptr, &newlb, &newtype); - if (done == 1) { + if (done == CTX_RESULT_OK) { PyErr_Format( PyExc_AttributeError, "bpy_struct: Context property \"%.200s\" is read-only", name); BLI_freelistN(&newlb); @@ -4829,7 +4854,7 @@ static PyObject *pyrna_prop_collection_items(BPy_PropertyRNA *self) } } else { - /* A bit strange, but better then returning an empty list. */ + /* A bit strange, but better than returning an empty list. */ PyTuple_SET_ITEM(item, 0, PyLong_FromLong(i)); } PyTuple_SET_ITEM(item, 1, pyrna_struct_CreatePyObject(&itemptr)); @@ -5406,7 +5431,7 @@ static PyObject *pyprop_array_foreach_getset(BPy_PropertyArrayRNA *self, /* Get/set both take the same args currently. */ PyObject *seq; - if (prop_type != PROP_INT && prop_type != PROP_FLOAT) { + if (!ELEM(prop_type, PROP_INT, PROP_FLOAT)) { PyErr_Format(PyExc_TypeError, "foreach_get/set available only for int and float"); return NULL; } @@ -5639,7 +5664,7 @@ static struct PyMethodDef pyrna_struct_methods[] = { {"is_property_set", (PyCFunction)pyrna_struct_is_property_set, - METH_VARARGS, + METH_VARARGS | METH_KEYWORDS, pyrna_struct_is_property_set_doc}, {"property_unset", (PyCFunction)pyrna_struct_property_unset, @@ -5845,7 +5870,7 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat /* Resolve the array from a new pytype. */ - /* TODO(Kazanbas) make multi-dimensional sequences here. */ + /* TODO(Kazanbas): make multi-dimensional sequences here. */ switch (type) { case PROP_BOOLEAN: @@ -6038,7 +6063,7 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject /* enable this so all strings are copied and freed after calling. * this exposes bugs where the pointer to the string is held and re-used */ - // #define DEBUG_STRING_FREE + /* #define DEBUG_STRING_FREE */ #ifdef DEBUG_STRING_FREE PyObject *string_free_ls = PyList_New(0); @@ -6204,7 +6229,7 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject /* Check if we gave args that don't exist in the function * Printing the error is slow, but it should only happen when developing. - * The "if" below is quick check to make sure less keyword args were passed then we gave. + * The "if" below is quick check to make sure less keyword args were passed than we gave. * (Don't overwrite the error if we have one, * otherwise can skip important messages and confuse with args). */ @@ -6284,7 +6309,7 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject if (err == 0) { /* Call function. */ ReportList reports; - bContext *C = BPy_GetContext(); + bContext *C = BPY_context_get(); BKE_reports_init(&reports, RPT_STORE); RNA_function_call(C, &reports, self_ptr, self_func, &parms); @@ -6378,10 +6403,14 @@ PyTypeObject pyrna_struct_meta_idprop_Type = { 0, /* tp_itemsize */ /* methods */ - NULL, /* tp_dealloc */ - (printfunc)NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ + NULL, /* tp_dealloc */ +#if PY_VERSION_HEX >= 0x03080000 + 0, /* tp_vectorcall_offset */ +#else + (printfunc)NULL, /* printfunc tp_print */ +#endif + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ NULL, /* tp_compare */ /* deprecated in Python 3.0! */ NULL, /* tp_repr */ @@ -6431,7 +6460,7 @@ PyTypeObject pyrna_struct_meta_idprop_Type = { #if defined(_MSC_VER) NULL, /* defer assignment */ #else - &PyType_Type, /* struct _typeobject *tp_base; */ + &PyType_Type, /* struct _typeobject *tp_base; */ #endif NULL, /* PyObject *tp_dict; */ NULL, /* descrgetfunc tp_descr_get; */ @@ -6460,9 +6489,13 @@ PyTypeObject pyrna_struct_Type = { 0, /* tp_itemsize */ /* methods */ (destructor)pyrna_struct_dealloc, /* tp_dealloc */ - (printfunc)NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ +#if PY_VERSION_HEX >= 0x03080000 + 0, /* tp_vectorcall_offset */ +#else + (printfunc)NULL, /* printfunc tp_print */ +#endif + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ NULL, /* tp_compare */ /* DEPRECATED in Python 3.0! */ (reprfunc)pyrna_struct_repr, /* tp_repr */ @@ -6496,7 +6529,7 @@ PyTypeObject pyrna_struct_Type = { /* delete references to contained objects */ (inquiry)pyrna_struct_clear, /* inquiry tp_clear; */ #else - NULL, /* traverseproc tp_traverse; */ + NULL, /* traverseproc tp_traverse; */ /* delete references to contained objects */ NULL, /* inquiry tp_clear; */ @@ -6549,9 +6582,13 @@ PyTypeObject pyrna_prop_Type = { 0, /* tp_itemsize */ /* methods */ (destructor)pyrna_prop_dealloc, /* tp_dealloc */ - (printfunc)NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ +#if PY_VERSION_HEX >= 0x03080000 + 0, /* tp_vectorcall_offset */ +#else + (printfunc)NULL, /* printfunc tp_print */ +#endif + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ NULL, /* tp_compare */ /* DEPRECATED in Python 3.0! */ (reprfunc)pyrna_prop_repr, /* tp_repr */ @@ -6633,9 +6670,13 @@ PyTypeObject pyrna_prop_array_Type = { 0, /* tp_itemsize */ /* methods */ (destructor)pyrna_prop_array_dealloc, /* tp_dealloc */ - (printfunc)NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ +#if PY_VERSION_HEX >= 0x03080000 + 0, /* tp_vectorcall_offset */ +#else + (printfunc)NULL, /* printfunc tp_print */ +#endif + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ NULL, /* tp_compare */ /* DEPRECATED in Python 3.0! */ (reprfunc)pyrna_prop_array_repr, /* tp_repr */ @@ -6716,9 +6757,13 @@ PyTypeObject pyrna_prop_collection_Type = { 0, /* tp_itemsize */ /* methods */ (destructor)pyrna_prop_dealloc, /* tp_dealloc */ - (printfunc)NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ +#if PY_VERSION_HEX >= 0x03080000 + 0, /* tp_vectorcall_offset */ +#else + (printfunc)NULL, /* printfunc tp_print */ +#endif + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ NULL, /* tp_compare */ /* DEPRECATED in Python 3.0! */ NULL, @@ -6802,9 +6847,13 @@ static PyTypeObject pyrna_prop_collection_idprop_Type = { 0, /* tp_itemsize */ /* methods */ (destructor)pyrna_prop_dealloc, /* tp_dealloc */ - (printfunc)NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ +#if PY_VERSION_HEX >= 0x03080000 + 0, /* tp_vectorcall_offset */ +#else + (printfunc)NULL, /* printfunc tp_print */ +#endif + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ NULL, /* tp_compare */ /* DEPRECATED in Python 3.0! */ NULL, @@ -6887,10 +6936,14 @@ PyTypeObject pyrna_func_Type = { sizeof(BPy_FunctionRNA), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - NULL, /* tp_dealloc */ - (printfunc)NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ + NULL, /* tp_dealloc */ +#if PY_VERSION_HEX >= 0x03080000 + 0, /* tp_vectorcall_offset */ +#else + (printfunc)NULL, /* printfunc tp_print */ +#endif + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ NULL, /* tp_compare */ /* DEPRECATED in Python 3.0! */ (reprfunc)pyrna_func_repr, /* tp_repr */ @@ -6984,9 +7037,13 @@ static PyTypeObject pyrna_prop_collection_iter_Type = { 0, /* tp_itemsize */ /* methods */ (destructor)pyrna_prop_collection_iter_dealloc, /* tp_dealloc */ - (printfunc)NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ +# if PY_VERSION_HEX >= 0x03080000 + 0, /* tp_vectorcall_offset */ +# else + (printfunc)NULL, /* printfunc tp_print */ +# endif + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ NULL, /* tp_compare */ /* DEPRECATED in Python 3.0! */ NULL, @@ -8093,18 +8150,11 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, for (link = lb->first; link; link = link->next) { FunctionRNA *func = (FunctionRNA *)link; const int flag = RNA_function_flag(func); - /* TODO(campbell): this is used for classmethod's too, - * even though class methods should have 'FUNC_USE_SELF_TYPE' set, see Operator.poll for eg. - * Keep this as-is since it's working, but we should be using - * 'FUNC_USE_SELF_TYPE' for many functions. */ - const bool is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE); - if (!(flag & FUNC_REGISTER)) { continue; } item = PyObject_GetAttrString(py_class, RNA_function_identifier(func)); - have_function[i] = (item != NULL); i++; @@ -8117,80 +8167,89 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, RNA_function_identifier(func)); return -1; } - PyErr_Clear(); + + continue; } - else { - /* No need to keep a ref, the class owns it - * (technically we should keep a reference, but...). */ - Py_DECREF(item); - if (is_staticmethod) { - if (PyMethod_Check(item) == 0) { - PyErr_Format(PyExc_TypeError, - "expected %.200s, %.200s class \"%.200s\" " - "attribute to be a static/class method, not a %.200s", - class_type, - py_class_name, - RNA_function_identifier(func), - Py_TYPE(item)->tp_name); - return -1; - } - item = ((PyMethodObject *)item)->im_func; + /* TODO(campbell): this is used for classmethod's too, + * even though class methods should have 'FUNC_USE_SELF_TYPE' set, see Operator.poll for eg. + * Keep this as-is since it's working, but we should be using + * 'FUNC_USE_SELF_TYPE' for many functions. */ + const bool is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE); + + /* Store original so we can decrement its reference before returning. */ + PyObject *item_orig = item; + + if (is_staticmethod) { + if (PyMethod_Check(item) == 0) { + PyErr_Format(PyExc_TypeError, + "expected %.200s, %.200s class \"%.200s\" " + "attribute to be a static/class method, not a %.200s", + class_type, + py_class_name, + RNA_function_identifier(func), + Py_TYPE(item)->tp_name); + Py_DECREF(item_orig); + return -1; } - else { - if (PyFunction_Check(item) == 0) { - PyErr_Format(PyExc_TypeError, - "expected %.200s, %.200s class \"%.200s\" " - "attribute to be a function, not a %.200s", - class_type, - py_class_name, - RNA_function_identifier(func), - Py_TYPE(item)->tp_name); - return -1; - } + item = ((PyMethodObject *)item)->im_func; + } + else { + if (PyFunction_Check(item) == 0) { + PyErr_Format(PyExc_TypeError, + "expected %.200s, %.200s class \"%.200s\" " + "attribute to be a function, not a %.200s", + class_type, + py_class_name, + RNA_function_identifier(func), + Py_TYPE(item)->tp_name); + Py_DECREF(item_orig); + return -1; } + } - func_arg_count = rna_function_arg_count(func, &func_arg_min_count); + func_arg_count = rna_function_arg_count(func, &func_arg_min_count); - if (func_arg_count >= 0) { /* -1 if we don't care. */ - arg_count = ((PyCodeObject *)PyFunction_GET_CODE(item))->co_argcount; + if (func_arg_count >= 0) { /* -1 if we don't care. */ + arg_count = ((PyCodeObject *)PyFunction_GET_CODE(item))->co_argcount; - /* note, the number of args we check for and the number of args we give to - * '@staticmethods' are different (quirk of Python), - * this is why rna_function_arg_count() doesn't return the value -1*/ - if (is_staticmethod) { - func_arg_count++; - func_arg_min_count++; - } + /* note, the number of args we check for and the number of args we give to + * '@staticmethods' are different (quirk of Python), + * this is why rna_function_arg_count() doesn't return the value -1*/ + if (is_staticmethod) { + func_arg_count++; + func_arg_min_count++; + } - if (arg_count < func_arg_min_count || arg_count > func_arg_count) { - if (func_arg_min_count != func_arg_count) { - PyErr_Format( - PyExc_ValueError, - "expected %.200s, %.200s class \"%.200s\" function to have between %d and %d " - "args, found %d", - class_type, - py_class_name, - RNA_function_identifier(func), - func_arg_count, - func_arg_min_count, - arg_count); - } - else { - PyErr_Format( - PyExc_ValueError, - "expected %.200s, %.200s class \"%.200s\" function to have %d args, found %d", - class_type, - py_class_name, - RNA_function_identifier(func), - func_arg_count, - arg_count); - } - return -1; + if (arg_count < func_arg_min_count || arg_count > func_arg_count) { + if (func_arg_min_count != func_arg_count) { + PyErr_Format( + PyExc_ValueError, + "expected %.200s, %.200s class \"%.200s\" function to have between %d and %d " + "args, found %d", + class_type, + py_class_name, + RNA_function_identifier(func), + func_arg_count, + func_arg_min_count, + arg_count); + } + else { + PyErr_Format( + PyExc_ValueError, + "expected %.200s, %.200s class \"%.200s\" function to have %d args, found %d", + class_type, + py_class_name, + RNA_function_identifier(func), + func_arg_count, + arg_count); } + Py_DECREF(item_orig); + return -1; } } + Py_DECREF(item_orig); } /* Verify properties. */ @@ -8303,7 +8362,7 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param /* XXX, this is needed because render engine calls without a context * this should be supported at some point, but at the moment it's not! */ if (C == NULL) { - C = BPy_GetContext(); + C = BPY_context_get(); } /* Annoying! We need to check if the screen gets set to NULL which is a @@ -8690,19 +8749,21 @@ void pyrna_free_types(void) PyDoc_STRVAR(pyrna_register_class_doc, ".. method:: register_class(cls)\n" "\n" - " Register a subclass of a blender type in (:class:`bpy.types.Panel`,\n" - " :class:`bpy.types.UIList`, :class:`bpy.types.Menu`, :class:`bpy.types.Header`,\n" - " :class:`bpy.types.Operator`, :class:`bpy.types.KeyingSetInfo`,\n" - " :class:`bpy.types.RenderEngine`).\n" + " Register a subclass of a Blender type class.\n" "\n" - " If the class has a *register* class method it will be called\n" - " before registration.\n" + " :arg cls: Blender type class in:\n" + " :class:`bpy.types.Panel`, :class:`bpy.types.UIList`,\n" + " :class:`bpy.types.Menu`, :class:`bpy.types.Header`,\n" + " :class:`bpy.types.Operator`, :class:`bpy.types.KeyingSetInfo`,\n" + " :class:`bpy.types.RenderEngine`\n" + " :type cls: class\n" + " :raises ValueError:\n" + " if the class is not a subclass of a registerable blender class.\n" "\n" " .. note::\n" "\n" - " :exc:`ValueError` exception is raised if the class is not a\n" - " subclass of a registerable blender class.\n" - "\n"); + " If the class has a *register* class method it will be called\n" + " before registration.\n"); PyMethodDef meth_bpy_register_class = { "register_class", pyrna_register_class, METH_O, pyrna_register_class_doc}; static PyObject *pyrna_register_class(PyObject *UNUSED(self), PyObject *py_class) @@ -8770,7 +8831,7 @@ static PyObject *pyrna_register_class(PyObject *UNUSED(self), PyObject *py_class } /* Get the context, so register callback can do necessary refreshes. */ - C = BPy_GetContext(); + C = BPY_context_get(); /* Call the register callback with reports & identifier. */ BKE_reports_init(&reports, RPT_STORE); @@ -8808,7 +8869,10 @@ static PyObject *pyrna_register_class(PyObject *UNUSED(self), PyObject *py_class /* Old srna still references us, keep the check in case registering somehow can free it. */ if (RNA_struct_py_type_get(srna)) { RNA_struct_py_type_set(srna, NULL); - // Py_DECREF(py_class); /* Should be able to do this XXX since the old RNA adds a new ref. */ +#if 0 + /* Should be able to do this XXX since the old RNA adds a new ref. */ + Py_DECREF(py_class); +#endif } /* Can't use this because it returns a dict proxy @@ -8978,7 +9042,7 @@ static PyObject *pyrna_unregister_class(PyObject *UNUSED(self), PyObject *py_cla } /* Get the context, so register callback can do necessary refreshes. */ - C = BPy_GetContext(); + C = BPY_context_get(); /* Call unregister. */ unreg(CTX_data_main(C), srna); /* Calls bpy_class_free, this decref's py_class. */ |