Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2010-09-09 09:37:22 +0400
committerCampbell Barton <ideasman42@gmail.com>2010-09-09 09:37:22 +0400
commitf4be9a6393e76f1dc40488ab25c43763af2edcc2 (patch)
tree2043d45af4bd8a2af2f9e97e9c10ab8fa9a4cf47 /source/blender/python
parent4eaa10aa02994c4609e1c12e38d0eda6355f9077 (diff)
support for defining rna class properties as class attributes
eg: bpy.types.Scene.myprop = BoolProperty() note, this uses an ugly python metaclass, this should be replaced with a C implimentation which is included but commented out, causing crashes in pythons GC which gives no hint as to where the bug comes from.
Diffstat (limited to 'source/blender/python')
-rw-r--r--source/blender/python/intern/bpy_rna.c100
1 files changed, 93 insertions, 7 deletions
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 908cd25b024..46e02117e77 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -50,6 +50,7 @@
#define USE_MATHUTILS
#define USE_STRING_COERCE
+#define USE_PY_METACLASS
#ifdef USE_MATHUTILS
#include "../generic/mathutils.h" /* so we can have mathutils callbacks */
@@ -61,6 +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);
/* bpyrna vector/euler/quat callbacks */
static int mathutils_rna_array_cb_index= -1; /* index for our callbacks */
@@ -2583,6 +2585,24 @@ static int pyrna_struct_pydict_contains(PyObject *self, PyObject *pyname)
#endif
//--------------- setattr-------------------------------------------
+
+#ifndef USE_PY_METACLASS
+static int pyrna_struct_meta_idprop_setattro(PyObject *cls, PyObject *pyname, PyObject *value)
+{
+ /* 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 -1;
+ }
+ return deferred_register_prop(srna, pyname, value);
+ }
+ else {
+ return PyType_Type.tp_setattro(cls, pyname, value);
+ }
+}
+#endif
+
static int pyrna_struct_setattro( BPy_StructRNA *self, PyObject *pyname, PyObject *value )
{
char *name = _PyUnicode_AsString(pyname);
@@ -3742,6 +3762,43 @@ 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 */
+ 0, /* tp_itemsize */
+ /* methods */
+ NULL, /* tp_dealloc */
+ NULL, /* printfunc tp_print; */
+ NULL, /* getattrfunc tp_getattr; */
+ NULL, /* setattrfunc tp_setattr; */
+ NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */
+ NULL, /* tp_repr */
+
+ /* Method suites for standard classes */
+ NULL, /* PyNumberMethods *tp_as_number; */
+ NULL, /* PySequenceMethods *tp_as_sequence; */
+ NULL, /* PyMappingMethods *tp_as_mapping; */
+
+ /* More standard operations (here for binary compatibility) */
+ 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; */
+
+ /* Functions to access object as input/output buffer */
+ NULL, /* PyBufferProcs *tp_as_buffer; */
+
+ /*** Flags to define presence of optional/expanded features ***/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */
+};
+#endif
+
+
/*-----------------------BPy_StructRNA method def------------------------------*/
PyTypeObject pyrna_struct_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
@@ -4199,9 +4256,14 @@ 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)
{
- PyObject *bpy_types_dict= NULL;
const char *idname= RNA_struct_identifier(srna);
PyObject *newclass;
@@ -4214,8 +4276,10 @@ static PyObject* pyrna_srna_ExternalType(StructRNA *srna)
fprintf(stderr, "pyrna_srna_ExternalType: failed to find 'bpy_types' module\n");
return NULL;
}
-
+#ifdef USE_PY_METACLASS
bpy_types_dict = PyModule_GetDict(bpy_types); // borrow
+ 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
}
@@ -4276,16 +4340,30 @@ static PyObject* pyrna_srna_Subtype(StructRNA *srna)
/* Assume RNA_struct_py_type_get(srna) was already checked */
PyObject *py_base= pyrna_srna_PyBase(srna);
-
+ PyObject *metaclass;
const char *idname= RNA_struct_identifier(srna);
-
+
/* remove __doc__ for now */
// const char *descr= RNA_struct_ui_description(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, &pyrna_struct_meta_idprop_Type)) {
+ metaclass= (PyObject *)&pyrna_struct_meta_idprop_Type;
+ }
+#endif
+ else {
+ metaclass= (PyObject *)&PyType_Type;
+ }
+
/* always use O not N when calling, N causes refcount errors */
- newclass = PyObject_CallFunction((PyObject*)&PyType_Type, "s(O){sss()}", idname, py_base, "__module__","bpy.types", "__slots__");
+ newclass = PyObject_CallFunction(metaclass, "s(O){sss()}", idname, py_base, "__module__","bpy.types", "__slots__");
+
/* newclass will now have 2 ref's, ???, probably 1 is internal since decrefing here segfaults */
/* PyC_ObSpit("new class ref", newclass); */
@@ -4299,6 +4377,7 @@ static PyObject* pyrna_srna_Subtype(StructRNA *srna)
}
else {
/* this should not happen */
+ printf("Error registering '%s'\n", idname);
PyErr_Print();
PyErr_Clear();
}
@@ -4403,7 +4482,14 @@ void BPY_rna_init(void)
mathutils_rna_array_cb_index= Mathutils_RegisterCallback(&mathutils_rna_array_cb);
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;