diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2011-11-05 00:21:40 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2011-11-05 00:21:40 +0400 |
commit | 942d2fe3b7b75facbf280271b1adc31882fc5693 (patch) | |
tree | d3bdbd3fd41aea01afb5ebdbb9240c8de18f1db7 /source/blender/python | |
parent | a620ec61ec173b7d9b753c9be443fdbdb1644c71 (diff) | |
parent | 7b47a4125fa4219a0f6c1a3e8c78047211caaa53 (diff) |
Cycles: svn merge -r41467:41531 ^/trunk/blender
Diffstat (limited to 'source/blender/python')
-rw-r--r-- | source/blender/python/BPY_extern.h | 2 | ||||
-rw-r--r-- | source/blender/python/generic/IDProp.c | 39 | ||||
-rw-r--r-- | source/blender/python/generic/IDProp.h | 2 | ||||
-rw-r--r-- | source/blender/python/generic/py_capi_utils.c | 2 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_app_handlers.c | 167 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_operator.c | 4 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_props.c | 2 |
7 files changed, 184 insertions, 34 deletions
diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index d8ddcd593a8..29e0185c2f2 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -71,7 +71,7 @@ void BPY_text_free_code(struct Text *text); void BPY_modules_update(struct bContext *C); // XXX - annoying, need this for pointers that get out of date void BPY_modules_load_user(struct bContext *C); -void BPY_app_handlers_reset(void); +void BPY_app_handlers_reset(const short do_all); void BPY_driver_reset(void); float BPY_driver_exec(struct ChannelDriver *driver); diff --git a/source/blender/python/generic/IDProp.c b/source/blender/python/generic/IDProp.c index 076b4811d07..6d869a7eb1f 100644 --- a/source/blender/python/generic/IDProp.c +++ b/source/blender/python/generic/IDProp.c @@ -195,19 +195,22 @@ static PyObject *BPy_IDGroup_GetName(BPy_IDProperty *self, void *UNUSED(closure) static int BPy_IDGroup_SetName(BPy_IDProperty *self, PyObject *value, void *UNUSED(closure)) { - char *st; + const char *name; + Py_ssize_t name_size; + if (!PyUnicode_Check(value)) { PyErr_SetString(PyExc_TypeError, "expected a string!"); return -1; } - st = _PyUnicode_AsString(value); - if (BLI_strnlen(st, MAX_IDPROP_NAME) == MAX_IDPROP_NAME) { + name = _PyUnicode_AsStringAndSize(value, &name_size); + + if (name_size > MAX_IDPROP_NAME) { PyErr_SetString(PyExc_TypeError, "string length cannot exceed 31 characters!"); return -1; } - BLI_strncpy(self->prop->name, st, sizeof(self->prop->name)); + memcpy(self->prop->name, name, name_size); return 0; } @@ -236,7 +239,7 @@ static Py_ssize_t BPy_IDGroup_Map_Len(BPy_IDProperty *self) static PyObject *BPy_IDGroup_Map_GetItem(BPy_IDProperty *self, PyObject *item) { IDProperty *idprop; - char *name; + const char *name; if (self->prop->type != IDP_GROUP) { PyErr_SetString(PyExc_TypeError, "unsubscriptable object"); @@ -301,14 +304,22 @@ static int idp_sequence_type(PyObject *seq) return type; } -/* note: group can be a pointer array or a group */ -const char *BPy_IDProperty_Map_ValidateAndCreate(const char *name, IDProperty *group, PyObject *ob) +/* note: group can be a pointer array or a group. + * assume we already checked key is a string. */ +const char *BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group, PyObject *ob) { IDProperty *prop = NULL; IDPropertyTemplate val = {0}; - if (strlen(name) >= sizeof(group->name)) - return "the length of IDProperty names is limited to 31 characters"; + const char *name= ""; + + if (name_obj) { + Py_ssize_t name_size; + name = _PyUnicode_AsStringAndSize(name_obj, &name_size); + if (name_size > MAX_IDPROP_NAME) { + return "the length of IDProperty names is limited to 31 characters"; + } + } if (PyFloat_Check(ob)) { val.d = PyFloat_AsDouble(ob); @@ -364,7 +375,7 @@ const char *BPy_IDProperty_Map_ValidateAndCreate(const char *name, IDProperty *g for (i=0; i<val.array.len; i++) { const char *error; item = PySequence_GetItem(ob, i); - error= BPy_IDProperty_Map_ValidateAndCreate("", prop, item); + error= BPy_IDProperty_Map_ValidateAndCreate(NULL, prop, item); Py_DECREF(item); if (error) @@ -396,7 +407,7 @@ const char *BPy_IDProperty_Map_ValidateAndCreate(const char *name, IDProperty *g Py_XDECREF(pval); return "invalid element in subgroup dict template!"; } - if (BPy_IDProperty_Map_ValidateAndCreate(_PyUnicode_AsString(key), prop, pval)) { + if (BPy_IDProperty_Map_ValidateAndCreate(key, prop, pval)) { IDP_FreeProperty(prop); MEM_freeN(prop); Py_XDECREF(keys); @@ -453,7 +464,7 @@ int BPy_Wrap_SetMapItem(IDProperty *prop, PyObject *key, PyObject *val) return -1; } - err = BPy_IDProperty_Map_ValidateAndCreate(_PyUnicode_AsString(key), prop, val); + err = BPy_IDProperty_Map_ValidateAndCreate(key, prop, val); if (err) { PyErr_SetString(PyExc_KeyError, err ); return -1; @@ -587,7 +598,7 @@ static PyObject *BPy_IDGroup_Pop(BPy_IDProperty *self, PyObject *value) { IDProperty *idprop; PyObject *pyform; - char *name = _PyUnicode_AsString(value); + const char *name = _PyUnicode_AsString(value); if (!name) { PyErr_SetString(PyExc_TypeError, "pop expected at least 1 argument, got 0"); @@ -724,7 +735,7 @@ static PyObject *BPy_IDGroup_GetItems(BPy_IDProperty *self) static int BPy_IDGroup_Contains(BPy_IDProperty *self, PyObject *value) { - char *name = _PyUnicode_AsString(value); + const char *name = _PyUnicode_AsString(value); if (!name) { PyErr_SetString(PyExc_TypeError, "expected a string"); diff --git a/source/blender/python/generic/IDProp.h b/source/blender/python/generic/IDProp.h index f71514f9df0..36cb4c76a5c 100644 --- a/source/blender/python/generic/IDProp.h +++ b/source/blender/python/generic/IDProp.h @@ -61,7 +61,7 @@ int BPy_Wrap_SetMapItem(struct IDProperty *prop, PyObject *key, PyObject *val); PyObject *BPy_IDGroup_WrapData(struct ID *id, struct IDProperty *prop ); -const char *BPy_IDProperty_Map_ValidateAndCreate(const char *name, struct IDProperty *group, PyObject *ob); +const char *BPy_IDProperty_Map_ValidateAndCreate(PyObject *key, struct IDProperty *group, PyObject *ob); void IDProp_Init_Types(void); diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index c6fb5133e33..eb4ecf79941 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -363,7 +363,7 @@ error_cleanup: /* string conversion, escape non-unicode chars, coerce must be set to NULL */ const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce) { - char *result; + const char *result; result= _PyUnicode_AsString(py_str); diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c index e7f74569f1a..f130a4bcc5c 100644 --- a/source/blender/python/intern/bpy_app_handlers.c +++ b/source/blender/python/intern/bpy_app_handlers.c @@ -38,17 +38,22 @@ void bpy_app_generic_callback(struct Main *main, struct ID *id, void *arg); static PyTypeObject BlenderAppCbType; static PyStructSequence_Field app_cb_info_fields[]= { - {(char *)"frame_change_pre", NULL}, - {(char *)"frame_change_post", NULL}, - {(char *)"render_pre", NULL}, - {(char *)"render_post", NULL}, - {(char *)"render_stats", NULL}, - {(char *)"load_pre", NULL}, - {(char *)"load_post", NULL}, - {(char *)"save_pre", NULL}, - {(char *)"save_post", NULL}, - {(char *)"scene_update_pre", NULL}, - {(char *)"scene_update_post", NULL}, + {(char *)"frame_change_pre", (char *)"Callback list - on frame change for playback and rendering (before)"}, + {(char *)"frame_change_post", (char *)"Callback list - on frame change for playback and rendering (after)"}, + {(char *)"render_pre", (char *)"Callback list - on render (before)"}, + {(char *)"render_post", (char *)"Callback list - on render (after)"}, + {(char *)"render_stats", (char *)"Callback list - on printing render statistics"}, + {(char *)"load_pre", (char *)"Callback list - on loading a new blend file (before)"}, + {(char *)"load_post", (char *)"Callback list - on loading a new blend file (after)"}, + {(char *)"save_pre", (char *)"Callback list - on saving a blend file (before)"}, + {(char *)"save_post", (char *)"Callback list - on saving a blend file (after)"}, + {(char *)"scene_update_pre", (char *)"Callback list - on updating the scenes data (before)"}, + {(char *)"scene_update_post", (char *)"Callback list - on updating the scenes data (after)"}, + + /* sets the permanent tag */ +# define APP_CB_OTHER_FIELDS 1 + {(char *)"persistent", (char *)"Function decorator for callback functions not to be removed when loading new files"}, + {NULL} }; @@ -65,6 +70,95 @@ static PyStructSequence_Desc app_cb_info_desc= { #endif */ +/* --------------------------------------------------------------------------*/ +/* permanent tagging code */ +#define PERMINENT_CB_ID "_bpy_persistent" + +static PyObject *bpy_app_handlers_persistent_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *UNUSED(kwds)) +{ + PyObject *value; + + if(!PyArg_ParseTuple(args, "O:bpy.app.handlers.persistent", &value)) + return NULL; + + if (PyFunction_Check(value)) { + PyObject **dict_ptr= _PyObject_GetDictPtr(value); + if (dict_ptr == NULL) { + PyErr_SetString(PyExc_ValueError, + "bpy.app.handlers.persistent wasn't able to " + "get the dictionary from the function passed"); + return NULL; + } + else { + /* set id */ + if (*dict_ptr == NULL) { + *dict_ptr= PyDict_New(); + } + + PyDict_SetItemString(*dict_ptr, PERMINENT_CB_ID, Py_None); + } + + Py_INCREF(value); + return value; + } + else { + PyErr_SetString(PyExc_ValueError, + "bpy.app.handlers.persistent expected a function"); + return NULL; + } +} + +/* dummy type because decorators can't be PyCFunctions */ +static PyTypeObject BPyPersistent_Type = { + +#if defined(_MSC_VER) || defined(FREE_WINDOWS) + PyVarObject_HEAD_INIT(NULL, 0) +#else + PyVarObject_HEAD_INIT(&PyType_Type, 0) +#endif + + "persistent", /* tp_name */ + 0, /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_BASETYPE, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + bpy_app_handlers_persistent_new, /* tp_new */ + 0, /* tp_free */ +}; + static PyObject *py_cb_array[BLI_CB_EVT_TOT]= {NULL}; static PyObject *make_app_cb_info(void) @@ -83,10 +177,13 @@ static PyObject *make_app_cb_info(void) } PyStructSequence_SET_ITEM(app_cb_info, pos, (py_cb_array[pos]= PyList_New(0))); } - if (app_cb_info_fields[pos].name != NULL) { + if (app_cb_info_fields[pos + APP_CB_OTHER_FIELDS].name != NULL) { Py_FatalError("invalid callback slots 2"); } + /* custom function */ + PyStructSequence_SET_ITEM(app_cb_info, pos++, (PyObject *)&BPyPersistent_Type); + return app_cb_info; } @@ -94,6 +191,14 @@ PyObject *BPY_app_handlers_struct(void) { PyObject *ret; +#if defined(_MSC_VER) || defined(FREE_WINDOWS) + BPyPersistent_Type.ob_base.ob_base.ob_type= &PyType_Type; +#endif + + if (PyType_Ready(&BPyPersistent_Type) < 0) { + BLI_assert(!"error initializing 'bpy.app.handlers.persistent'"); + } + PyStructSequence_InitType(&BlenderAppCbType, &app_cb_info_desc); ret= make_app_cb_info(); @@ -120,12 +225,46 @@ PyObject *BPY_app_handlers_struct(void) return ret; } -void BPY_app_handlers_reset(void) +void BPY_app_handlers_reset(const short do_all) { int pos= 0; + if (do_all) { for (pos= 0; pos < BLI_CB_EVT_TOT; pos++) { - PyList_SetSlice(py_cb_array[pos], 0, PY_SSIZE_T_MAX, NULL); + /* clear list */ + PyList_SetSlice(py_cb_array[pos], 0, PY_SSIZE_T_MAX, NULL); + } + } + else { + /* save string conversion thrashing */ + PyObject *perm_id_str= PyUnicode_FromString(PERMINENT_CB_ID); + + for (pos= 0; pos < BLI_CB_EVT_TOT; pos++) { + /* clear only items without PERMINENT_CB_ID */ + PyObject *ls= py_cb_array[pos]; + Py_ssize_t i; + + PyObject *item; + PyObject **dict_ptr; + + for(i= PyList_GET_SIZE(ls) - 1; i >= 0; i--) { + + if ( (PyFunction_Check((item= PyList_GET_ITEM(ls, i)))) && + (dict_ptr= _PyObject_GetDictPtr(item)) && + (*dict_ptr) && + (PyDict_GetItem(*dict_ptr, perm_id_str) != NULL)) + { + /* keep */ + } + else { + /* remove */ + /* PySequence_DelItem(ls, i); */ /* more obvious buw slower */ + PyList_SetSlice(ls, i, i + 1, NULL); + } + } + } + + Py_DECREF(perm_id_str); } } diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index 6f23c1e604f..70a5d79e9ac 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -380,7 +380,7 @@ static PyObject *pyop_getrna(PyObject *UNUSED(self), PyObject *value) { wmOperatorType *ot; PointerRNA ptr; - char *opname= _PyUnicode_AsString(value); + const char *opname= _PyUnicode_AsString(value); BPy_StructRNA *pyrna= NULL; if (opname==NULL) { @@ -413,7 +413,7 @@ static PyObject *pyop_getinstance(PyObject *UNUSED(self), PyObject *value) wmOperatorType *ot; wmOperator *op; PointerRNA ptr; - char *opname= _PyUnicode_AsString(value); + const char *opname= _PyUnicode_AsString(value); BPy_StructRNA *pyrna= NULL; if (opname==NULL) { diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index 4b30b4705f4..b10223207bf 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -1211,7 +1211,7 @@ static StructRNA *pointer_type_from_py(PyObject *value, const char *error_prefix if (!srna) { if (PyErr_Occurred()) { PyObject *msg= PyC_ExceptionBuffer(); - char *msg_char= _PyUnicode_AsString(msg); + const char *msg_char= _PyUnicode_AsString(msg); PyErr_Format(PyExc_TypeError, "%.200s expected an RNA type derived from PropertyGroup, failed with: %s", error_prefix, msg_char); |