[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [31856] trunk/blender: rewrote python IDProperty metaclass in C, this was a quick hack to get it working.
Campbell Barton
ideasman42 at gmail.com
Fri Sep 10 16:54:53 CEST 2010
Revision: 31856
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=31856
Author: campbellbarton
Date: 2010-09-10 16:54:50 +0200 (Fri, 10 Sep 2010)
Log Message:
-----------
rewrote python IDProperty metaclass in C, this was a quick hack to get it working.
The reason this didnt work is all sibclasses of pythons type() or PyType_Type in C, have to have their size set to sizeof(PyHeapTypeObject) rather then sizeof(PyTypeObject) as you might expect.
This is strange since its not a heap-class (defined in pythons runtime), but a static C type, so Im not sure about this, and cant find any documentation but it seems to work ok.
Modified Paths:
--------------
trunk/blender/release/scripts/modules/bpy_types.py
trunk/blender/source/blender/python/intern/bpy.c
trunk/blender/source/blender/python/intern/bpy_rna.c
trunk/blender/source/blender/python/intern/bpy_rna.h
Modified: trunk/blender/release/scripts/modules/bpy_types.py
===================================================================
--- trunk/blender/release/scripts/modules/bpy_types.py 2010-09-10 12:46:43 UTC (rev 31855)
+++ trunk/blender/release/scripts/modules/bpy_types.py 2010-09-10 14:54:50 UTC (rev 31856)
@@ -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 @@
return new_context
-class ID(StructRNA, metaclass=RNA_IDProp_Meta):
- __slots__ = ()
-
-
class Library(bpy_types.ID):
__slots__ = ()
@@ -123,7 +61,7 @@
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 @@
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 @@
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):
Modified: trunk/blender/source/blender/python/intern/bpy.c
===================================================================
--- trunk/blender/source/blender/python/intern/bpy.c 2010-09-10 12:46:43 UTC (rev 31855)
+++ trunk/blender/source/blender/python/intern/bpy.c 2010-09-10 14:54:50 UTC (rev 31856)
@@ -167,6 +167,8 @@
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");
Modified: trunk/blender/source/blender/python/intern/bpy_rna.c
===================================================================
--- trunk/blender/source/blender/python/intern/bpy_rna.c 2010-09-10 12:46:43 UTC (rev 31855)
+++ trunk/blender/source/blender/python/intern/bpy_rna.c 2010-09-10 14:54:50 UTC (rev 31856)
@@ -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 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 @@
#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 @@
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 @@
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 @@
/*** 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 @@
/* 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 @@
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);
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list