diff options
-rw-r--r-- | release/scripts/modules/bpy_types.py | 75 | ||||
-rw-r--r-- | source/blender/python/intern/bpy.c | 2 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.c | 91 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.h | 1 |
4 files changed, 64 insertions, 105 deletions
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py index d3a1a5544f5..358628c001e 100644 --- a/release/scripts/modules/bpy_types.py +++ b/release/scripts/modules/bpy_types.py @@ -18,70 +18,12 @@ # <pep8 compliant> - -class RNA_IDProp_Meta(type): - # metaclass for all structures which can have rna prop's defined. - # important this class is defined first. - - # setattr, so we can do this... - # bpy.types.Scene.myprop = bpy.props.BoolProperty() - def __setattr__(cls, attr, value): - if type(value) == tuple and len(value) == 2: - prop = cls.bl_rna.properties.get(attr) - if prop and prop.is_runtime: - _bpy.props.RemoveProperty(cls, attr=attr) - func, kw = value - kw["attr"] = attr - func(cls, **kw) - else: - # XXX, pure evil, need to find a better way - _setattr = RNA_IDProp_Meta.__setattr__ - del RNA_IDProp_Meta.__setattr__ - try: - setattr(cls, attr, value) - except Exception as exc: - RNA_IDProp_Meta.__setattr__ = _setattr - raise exc - - RNA_IDProp_Meta.__setattr__ = _setattr - - def __getattr__(cls, attr): - if attr in cls.bl_rna.properties: - return cls.bl_rna.properties[attr] - elif attr: - # XXX, pure evil, need to find a better way - _getattr = RNA_IDProp_Meta.__getattr__ - del RNA_IDProp_Meta.__getattr__ - try: - ret = getattr(cls, attr) - except Exception as exc: - RNA_IDProp_Meta.__getattr__ = _getattr - raise exc - - RNA_IDProp_Meta.__getattr__ = _getattr - return ret - - def __delattr__(cls, attr): - if attr in cls.bl_rna.properties: - _bpy.props.RemoveProperty(cls, attr=attr) - elif attr: - # XXX, pure evil, need to find a better way - _delattr = RNA_IDProp_Meta.__delattr__ - del RNA_IDProp_Meta.__delattr__ - try: - delattr(cls, attr, value) - except Exception as exc: - RNA_IDProp_Meta.__delattr__ = _delattr - raise exc - - RNA_IDProp_Meta.__delattr__ = _delattr - - from _bpy import types as bpy_types import _bpy from mathutils import Vector StructRNA = bpy_types.Struct.__bases__[0] +StructMetaIDProp = _bpy.StructMetaIDProp # StructRNA = bpy_types.Struct @@ -101,10 +43,6 @@ class Context(StructRNA): return new_context -class ID(StructRNA, metaclass=RNA_IDProp_Meta): - __slots__ = () - - class Library(bpy_types.ID): __slots__ = () @@ -123,7 +61,7 @@ class Library(bpy_types.ID): return tuple(id_block for attr in attr_links for id_block in getattr(bpy.data, attr) if id_block.library == self) -class Texture(bpy_types.ID, metaclass=RNA_IDProp_Meta): +class Texture(bpy_types.ID): __slots__ = () @property @@ -320,15 +258,15 @@ class _GenericBone: return bones -class PoseBone(StructRNA, _GenericBone, metaclass=RNA_IDProp_Meta): +class PoseBone(StructRNA, _GenericBone): __slots__ = () -class Bone(StructRNA, _GenericBone, metaclass=RNA_IDProp_Meta): +class Bone(StructRNA, _GenericBone): __slots__ = () -class EditBone(StructRNA, _GenericBone, metaclass=RNA_IDProp_Meta): +class EditBone(StructRNA, _GenericBone): __slots__ = () def align_orientation(self, other): @@ -680,13 +618,12 @@ class RNAMeta(type): return result -class RNAMetaRegister(RNAMeta, RNA_IDProp_Meta): +class RNAMetaRegister(RNAMeta, StructMetaIDProp): @classmethod def _register_immediate(cls): return True - class OrderedMeta(RNAMeta): def __init__(cls, name, bases, attributes): diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index 03c1a012575..12a5221f76e 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -167,6 +167,8 @@ void BPy_init_modules( void ) BPY_rna_init(); PyModule_AddObject( mod, "types", BPY_rna_types() ); /* needs to be first so bpy_types can run */ + PyModule_AddObject(mod, "StructMetaIDProp", (PyObject *)&pyrna_struct_meta_idprop_Type); /* metaclass for idprop types, bpy_types.py needs access */ + bpy_import_test("bpy_types"); PyModule_AddObject( mod, "data", BPY_rna_module() ); /* imports bpy_types by running this */ bpy_import_test("bpy_types"); diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index e4d70478e94..c20bb3deaee 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -32,6 +32,7 @@ #include "float.h" /* FLT_MIN/MAX */ #include "RNA_enum_types.h" +#include "RNA_define.h" /* RNA_def_property_free_identifier */ #include "MEM_guardedalloc.h" #include "BKE_utildefines.h" @@ -50,7 +51,6 @@ #define USE_MATHUTILS #define USE_STRING_COERCE -#define USE_PY_METACLASS #ifdef USE_MATHUTILS #include "../generic/mathutils.h" /* so we can have mathutils callbacks */ @@ -62,7 +62,7 @@ static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, Po static Py_ssize_t pyrna_prop_array_length(BPy_PropertyArrayRNA *self); static Py_ssize_t pyrna_prop_collection_length(BPy_PropertyRNA *self); static short pyrna_rotation_euler_order_get(PointerRNA *ptr, PropertyRNA **prop_eul_order, short order_fallback); -static int deferred_register_prop(StructRNA *srna, PyObject *item, PyObject *key); +static int deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item); /* bpyrna vector/euler/quat callbacks */ static int mathutils_rna_array_cb_index= -1; /* index for our callbacks */ @@ -2587,23 +2587,58 @@ static int pyrna_struct_pydict_contains(PyObject *self, PyObject *pyname) #endif //--------------- setattr------------------------------------------- +static int pyrna_is_deferred_prop(PyObject *value) +{ + return PyTuple_CheckExact(value) && PyTuple_GET_SIZE(value)==2 && PyCallable_Check(PyTuple_GET_ITEM(value, 0)) && PyDict_CheckExact(PyTuple_GET_ITEM(value, 1)); +} -#ifndef USE_PY_METACLASS -static int pyrna_struct_meta_idprop_setattro(PyObject *cls, PyObject *pyname, PyObject *value) +static PyObject *pyrna_struct_meta_idprop_getattro(PyObject *cls, PyObject *pyname) { - /* check if the value is a property */ - if(PyTuple_CheckExact(value) && PyTuple_GET_SIZE(value)==2) { /* weak */ - StructRNA *srna= srna_from_self(cls, "struct_meta_idprop.setattr()"); - if(srna==NULL) { + return PyType_Type.tp_getattro(cls, pyname); +} + +static int pyrna_struct_meta_idprop_setattro(PyObject *cls, PyObject *attr, PyObject *value) +{ + StructRNA *srna= srna_from_self(cls, ""); + + if(srna == NULL) { + if(value && pyrna_is_deferred_prop(value)) { + PyErr_Format(PyExc_AttributeError, "pyrna_struct_meta_idprop_setattro() unable to get srna from class '%.200s'", ((PyTypeObject *)cls)->tp_name); return -1; } - return deferred_register_prop(srna, pyname, value); + + /* srna_from_self may set an error */ + PyErr_Clear(); + return PyType_Type.tp_setattro(cls, attr, value); } - else { - return PyType_Type.tp_setattro(cls, pyname, value); + + if(value) { + /* check if the value is a property */ + if(pyrna_is_deferred_prop(value)) { + int ret= deferred_register_prop(srna, attr, value); + if(ret < 0) + return ret; + /* pass through, when the value isn't assigned it still works but gets confusing from script writers POV */ + } + else { + /* remove existing property if its set or we also end up with confusement */ + char *attr_str= _PyUnicode_AsString(attr); + RNA_def_property_free_identifier(srna, attr_str); /* ignore on failier */ + } } + else { /* __delattr__ */ + /* first find if this is a registered property */ + char *attr_str= _PyUnicode_AsString(attr); + int ret= RNA_def_property_free_identifier(srna, attr_str); + if (ret == -1) { + PyErr_Format(PyExc_TypeError, "struct_meta_idprop.detattr(): '%s' not a dynamic property.", attr_str); + return -1; + } + } + + /* fallback to standard py, delattr/setattr */ + return PyType_Type.tp_setattro(cls, attr, value); } -#endif static int pyrna_struct_setattro( BPy_StructRNA *self, PyObject *pyname, PyObject *value ) { @@ -3750,13 +3785,13 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw) Py_RETURN_NONE; } -#ifndef USE_PY_METACLASS + /* subclasses of pyrna_struct_Type which support idprop definitions use this as a metaclass */ /* note: tp_base member is set to &PyType_Type on init */ PyTypeObject pyrna_struct_meta_idprop_Type = { PyVarObject_HEAD_INIT(NULL, 0) "bpy_struct_meta_idprop", /* tp_name */ - sizeof(PyTypeObject), /* tp_basicsize */ + sizeof(PyHeapTypeObject), /* tp_basicsize */ // XXX, would be PyTypeObject, but subtypes of Type must be PyHeapTypeObject's 0, /* tp_itemsize */ /* methods */ NULL, /* tp_dealloc */ @@ -3775,8 +3810,8 @@ PyTypeObject pyrna_struct_meta_idprop_Type = { NULL, /* hashfunc tp_hash; */ NULL, /* ternaryfunc tp_call; */ NULL, /* reprfunc tp_str; */ - NULL, /* pyrna_struct_meta_idprop_getattro*/ /* getattrofunc tp_getattro; */ - NULL /*( setattrofunc ) pyrna_struct_meta_idprop_setattro*/, /* setattrofunc tp_setattro; */ + (getattrofunc) pyrna_struct_meta_idprop_getattro, /* getattrofunc tp_getattro; */ + (setattrofunc) pyrna_struct_meta_idprop_setattro, /* setattrofunc tp_setattro; */ /* Functions to access object as input/output buffer */ NULL, /* PyBufferProcs *tp_as_buffer; */ @@ -3784,7 +3819,6 @@ PyTypeObject pyrna_struct_meta_idprop_Type = { /*** Flags to define presence of optional/expanded features ***/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */ }; -#endif /*-----------------------BPy_StructRNA method def------------------------------*/ @@ -4245,10 +4279,6 @@ static PyObject* pyrna_srna_PyBase(StructRNA *srna) //, PyObject *bpy_types_dict /* check if we have a native python subclass, use it when it exists * return a borrowed reference */ static PyObject *bpy_types_dict= NULL; -#ifdef USE_PY_METACLASS -#define BPY_SRNA_IDPROP_META "RNA_IDProp_Meta" -static PyObject *bpy_types_rna_meta_base= NULL; -#endif static PyObject* pyrna_srna_ExternalType(StructRNA *srna) { @@ -4265,9 +4295,6 @@ static PyObject* pyrna_srna_ExternalType(StructRNA *srna) return NULL; } bpy_types_dict = PyModule_GetDict(bpy_types); // borrow -#ifdef USE_PY_METACLASS - bpy_types_rna_meta_base = PyDict_GetItemString(bpy_types_dict, BPY_SRNA_IDPROP_META); -#endif Py_DECREF(bpy_types); // fairly safe to assume the dict is kept } @@ -4336,15 +4363,9 @@ static PyObject* pyrna_srna_Subtype(StructRNA *srna) // if(!descr) descr= "(no docs)"; // "__doc__",descr -#ifdef USE_PY_METACLASS - if(RNA_struct_idprops_check(srna) && !PyObject_IsSubclass(py_base, bpy_types_rna_meta_base)) { - metaclass= bpy_types_rna_meta_base; - } -#else if(RNA_struct_idprops_check(srna) && !PyObject_IsSubclass(py_base, (PyObject *)&pyrna_struct_meta_idprop_Type)) { metaclass= (PyObject *)&pyrna_struct_meta_idprop_Type; } -#endif else { metaclass= (PyObject *)&PyType_Type; } @@ -4471,12 +4492,10 @@ void BPY_rna_init(void) mathutils_rna_matrix_cb_index= Mathutils_RegisterCallback(&mathutils_rna_matrix_cb); #endif -#ifndef USE_PY_METACLASS /* metaclass */ pyrna_struct_meta_idprop_Type.tp_base= &PyType_Type; if( PyType_Ready( &pyrna_struct_meta_idprop_Type ) < 0 ) return; -#endif if( PyType_Ready( &pyrna_struct_Type ) < 0 ) return; @@ -4682,11 +4701,11 @@ StructRNA *srna_from_self(PyObject *self, const char *error_prefix) return pyrna_struct_as_srna(self, 0, error_prefix); } -static int deferred_register_prop(StructRNA *srna, PyObject *item, PyObject *key) +static int deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item) { /* We only care about results from C which * are for sure types, save some time with error */ - if(PyTuple_CheckExact(item) && PyTuple_GET_SIZE(item)==2) { + if(pyrna_is_deferred_prop(item)) { PyObject *py_func, *py_kw, *py_srna_cobject, *py_ret; @@ -4748,14 +4767,14 @@ static int pyrna_deferred_register_props(StructRNA *srna, PyObject *class_dict) for(pos= 0; pos<PyList_GET_SIZE(order); pos++) { key= PyList_GET_ITEM(order, pos); item= PyDict_GetItem(class_dict, key); - ret= deferred_register_prop(srna, item, key); + ret= deferred_register_prop(srna, key, item); if(ret==-1) break; } } else { while (PyDict_Next(class_dict, &pos, &key, &item)) { - ret= deferred_register_prop(srna, item, key); + ret= deferred_register_prop(srna, key, item); if(ret==-1) break; diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index 14c6ff4a1a3..4b8beb42930 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -30,6 +30,7 @@ #include "RNA_types.h" #include "BKE_idprop.h" +extern PyTypeObject pyrna_struct_meta_idprop_Type; extern PyTypeObject pyrna_struct_Type; extern PyTypeObject pyrna_prop_Type; extern PyTypeObject pyrna_prop_array_Type; |