diff options
author | Xiao Xiangquan <xiaoxiangquan@gmail.com> | 2011-09-01 19:08:32 +0400 |
---|---|---|
committer | Xiao Xiangquan <xiaoxiangquan@gmail.com> | 2011-09-01 19:08:32 +0400 |
commit | 981f7fcd0d315abb425bf34dd37f7cd4d9e8d55e (patch) | |
tree | 70800c93ec1a12579c32874e2a72eaf3290eba8e /source/blender/python | |
parent | 5b91a783cf0ec132398a2767d3419d675e5126b5 (diff) | |
parent | 2365c64014b3e067bb212b2061f1d14c1f944090 (diff) |
merge with trunk r39834
Diffstat (limited to 'source/blender/python')
-rw-r--r-- | source/blender/python/generic/bgl.c | 6 | ||||
-rw-r--r-- | source/blender/python/generic/noise_py_api.c | 20 | ||||
-rw-r--r--[-rwxr-xr-x] | source/blender/python/intern/bpy_app_handlers.c | 5 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_interface.c | 25 | ||||
-rwxr-xr-x | source/blender/python/intern/bpy_intern_string.c | 5 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_operator.c | 17 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_props.c | 4 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.c | 250 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna_anim.c | 2 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna_array.c | 9 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_traceback.c | 11 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_util.h | 1 | ||||
-rwxr-xr-x | source/blender/python/mathutils/mathutils_Vector.c | 117 |
13 files changed, 291 insertions, 181 deletions
diff --git a/source/blender/python/generic/bgl.c b/source/blender/python/generic/bgl.c index 09432e0b316..ae8069cf3c5 100644 --- a/source/blender/python/generic/bgl.c +++ b/source/blender/python/generic/bgl.c @@ -52,11 +52,9 @@ static int Buffer_len(Buffer *self); static PyObject *Buffer_item(Buffer *self, int i); static PyObject *Buffer_slice(Buffer *self, int begin, int end); static int Buffer_ass_item(Buffer *self, int i, PyObject *v); -static int Buffer_ass_slice(Buffer *self, int begin, int end, - PyObject *seq); +static int Buffer_ass_slice(Buffer *self, int begin, int end, PyObject *seq); static PyObject *Buffer_subscript(Buffer *self, PyObject *item); -static int Buffer_ass_subscript(Buffer *self, PyObject *item, - PyObject *value); +static int Buffer_ass_subscript(Buffer *self, PyObject *item, PyObject *value); static PySequenceMethods Buffer_SeqMethods = { (lenfunc) Buffer_len, /*sq_length */ diff --git a/source/blender/python/generic/noise_py_api.c b/source/blender/python/generic/noise_py_api.c index f5761f713a6..7be0998c0a1 100644 --- a/source/blender/python/generic/noise_py_api.c +++ b/source/blender/python/generic/noise_py_api.c @@ -210,8 +210,8 @@ static void randuvec(float v[3]) if((r = 1.f - v[2] * v[2]) > 0.f) { float a = (float)(6.283185307f * frand()); r = (float)sqrt(r); - v[0] = (float)(r * cos(a)); - v[1] = (float)(r * sin(a)); + v[0] = (float)(r * cosf(a)); + v[1] = (float)(r * sinf(a)); } else { v[2] = 1.f; @@ -254,7 +254,7 @@ static PyObject *Noise_noise(PyObject *UNUSED(self), PyObject *args) if(!PyArg_ParseTuple(args, "(fff)|i:noise", &x, &y, &z, &nb)) return NULL; - return PyFloat_FromDouble((2.0 * BLI_gNoise(1.0, x, y, z, 0, nb) - 1.0)); + return PyFloat_FromDouble((2.0f * BLI_gNoise(1.0f, x, y, z, 0, nb) - 1.0f)); } /*-------------------------------------------------------------------------*/ @@ -264,11 +264,11 @@ static PyObject *Noise_noise(PyObject *UNUSED(self), PyObject *args) static void noise_vector(float x, float y, float z, int nb, float v[3]) { /* Simply evaluate noise at 3 different positions */ - v[0] = (float)(2.0 * BLI_gNoise(1.f, x + 9.321f, y - 1.531f, z - 7.951f, 0, - nb) - 1.0); - v[1] = (float)(2.0 * BLI_gNoise(1.f, x, y, z, 0, nb) - 1.0); - v[2] = (float)(2.0 * BLI_gNoise(1.f, x + 6.327f, y + 0.1671f, z - 2.672f, 0, - nb) - 1.0); + v[0]= (float)(2.0f * BLI_gNoise(1.f, x + 9.321f, y - 1.531f, z - 7.951f, 0, + nb) - 1.0f); + v[1]= (float)(2.0f * BLI_gNoise(1.f, x, y, z, 0, nb) - 1.0f); + v[2]= (float)(2.0f * BLI_gNoise(1.f, x + 6.327f, y + 0.1671f, z - 2.672f, 0, + nb) - 1.0f); } static PyObject *Noise_vector(PyObject *UNUSED(self), PyObject *args) @@ -291,7 +291,7 @@ static float turb(float x, float y, float z, int oct, int hard, int nb, float amp, out, t; int i; amp = 1.f; - out = (float)(2.0 * BLI_gNoise(1.f, x, y, z, 0, nb) - 1.0); + out = (float)(2.0f * BLI_gNoise(1.f, x, y, z, 0, nb) - 1.0f); if(hard) out = (float)fabs(out); for(i = 1; i < oct; i++) { @@ -299,7 +299,7 @@ static float turb(float x, float y, float z, int oct, int hard, int nb, x *= freqscale; y *= freqscale; z *= freqscale; - t = (float)(amp * (2.0 * BLI_gNoise(1.f, x, y, z, 0, nb) - 1.0)); + t = (float)(amp * (2.0f * BLI_gNoise(1.f, x, y, z, 0, nb) - 1.0f)); if(hard) t = (float)fabs(t); out += t; diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c index 77ba6031da5..eeb2adb3cf2 100755..100644 --- a/source/blender/python/intern/bpy_app_handlers.c +++ b/source/blender/python/intern/bpy_app_handlers.c @@ -42,9 +42,10 @@ static PyTypeObject BlenderAppCbType; static PyStructSequence_Field app_cb_info_fields[]= { {(char *)"render_pre", NULL}, {(char *)"render_post", NULL}, - {(char *)"load_pre", NULL}, + {(char *)"render_stats", NULL}, + {(char *)"load_pre", NULL}, {(char *)"load_post", NULL}, - {(char *)"save_pre", NULL}, + {(char *)"save_pre", NULL}, {(char *)"save_post", NULL}, {NULL} }; diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 8bd6e6c611c..e5e90380d61 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -87,6 +87,14 @@ static double bpy_timer_run; /* time for each python script run */ static double bpy_timer_run_tot; /* accumulate python runs */ #endif +/* use for updating while a python script runs - in case of file load */ +void bpy_context_update(bContext *C) +{ + BPy_SetContext(C); + bpy_import_main_set(CTX_data_main(C)); + BPY_modules_update(C); /* can give really bad results if this isnt here */ +} + void bpy_context_set(bContext *C, PyGILState_STATE *gilstate) { py_call_level++; @@ -95,16 +103,7 @@ void bpy_context_set(bContext *C, PyGILState_STATE *gilstate) *gilstate= PyGILState_Ensure(); if(py_call_level==1) { - - if(C) { // XXX - should always be true. - BPy_SetContext(C); - bpy_import_main_set(CTX_data_main(C)); - } - else { - fprintf(stderr, "ERROR: Python context called with a NULL Context. this should not happen!\n"); - } - - BPY_modules_update(C); /* can give really bad results if this isnt here */ + bpy_context_update(C); #ifdef TIME_PY_RUN if(bpy_timer_count==0) { @@ -570,6 +569,12 @@ void BPY_modules_load_user(bContext *C) if(bmain==NULL) return; + /* update pointers since this can run from a nested script + * on file load */ + if(py_call_level) { + bpy_context_update(C); + } + bpy_context_set(C, &gilstate); for(text=CTX_data_main(C)->text.first; text; text= text->id.next) { diff --git a/source/blender/python/intern/bpy_intern_string.c b/source/blender/python/intern/bpy_intern_string.c index 963c3469847..7a61637eb81 100755 --- a/source/blender/python/intern/bpy_intern_string.c +++ b/source/blender/python/intern/bpy_intern_string.c @@ -28,18 +28,19 @@ #include <Python.h> +#include "bpy_intern_string.h" + PyObject *bpy_intern_str_register; PyObject *bpy_intern_str_unregister; PyObject *bpy_intern_str_bl_rna; PyObject *bpy_intern_str_order; PyObject *bpy_intern_str_attr; PyObject *bpy_intern_str___slots__; -PyObject *bpy_intern_str___bases__; void bpy_intern_string_init(void) { bpy_intern_str_register= PyUnicode_FromString("register"); - bpy_intern_str_unregister= PyUnicode_FromString("unregister");; + bpy_intern_str_unregister= PyUnicode_FromString("unregister"); bpy_intern_str_bl_rna= PyUnicode_FromString("bl_rna"); bpy_intern_str_order= PyUnicode_FromString("order"); bpy_intern_str_attr= PyUnicode_FromString("attr"); diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index 4b05a9c0c72..7327679cc7e 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -52,6 +52,9 @@ #include "WM_types.h" #include "MEM_guardedalloc.h" + +#include "BLI_ghash.h" + #include "BKE_report.h" #include "BKE_context.h" @@ -114,7 +117,6 @@ static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args) } context_dict_back= CTX_py_dict_get(C); - CTX_py_dict_set(C, (void *)context_dict); Py_XINCREF(context_dict); /* so we done loose it */ @@ -290,7 +292,7 @@ static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args) * function corrects bpy.data (internal Main pointer) */ BPY_modules_update(C); - /* needed for when WM_OT_read_factory_settings us called fro within a script */ + /* needed for when WM_OT_read_factory_settings us called from within a script */ bpy_import_main_set(CTX_data_main(C)); /* return operator_ret as a bpy enum */ @@ -359,15 +361,18 @@ static PyObject *pyop_as_string(PyObject *UNUSED(self), PyObject *args) static PyObject *pyop_dir(PyObject *UNUSED(self)) { + GHashIterator *iter= WM_operatortype_iter(); PyObject *list= PyList_New(0), *name; - wmOperatorType *ot; - - for(ot= WM_operatortype_first(); ot; ot= ot->next) { + + for( ; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) { + wmOperatorType *ot= BLI_ghashIterator_getValue(iter); + name= PyUnicode_FromString(ot->idname); PyList_Append(list, name); Py_DECREF(name); } - + BLI_ghashIterator_free(iter); + return list; } diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index a0ad1ff7850..5da142aeea7 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -117,7 +117,7 @@ static PyObject *pymeth_PointerProperty= NULL; static PyObject *pymeth_CollectionProperty= NULL; static PyObject *pymeth_RemoveProperty= NULL; -PyObject *pyrna_struct_as_instance(PointerRNA *ptr) +static PyObject *pyrna_struct_as_instance(PointerRNA *ptr) { PyObject *self= NULL; /* first get self */ @@ -177,7 +177,7 @@ static PyObject *bpy_prop_deferred_return(PyObject *func, PyObject *kw) } /* callbacks */ -void bpy_prop_update_cb(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop) +static void bpy_prop_update_cb(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop) { PyGILState_STATE gilstate; PyObject **py_data= (PyObject **)RNA_property_py_data_get(prop); diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 4447a0476f4..e1c38a82142 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -84,7 +84,9 @@ int pyrna_struct_validity_check(BPy_StructRNA *pysrna) { if(pysrna->ptr.type) return 0; - PyErr_Format(PyExc_ReferenceError, "StructRNA of type %.200s has been removed", Py_TYPE(pysrna)->tp_name); + PyErr_Format(PyExc_ReferenceError, + "StructRNA of type %.200s has been removed", + Py_TYPE(pysrna)->tp_name); return -1; } @@ -790,43 +792,62 @@ static PyObject *pyrna_struct_str(BPy_StructRNA *self) const char *name; if(!PYRNA_STRUCT_IS_VALID(self)) { - return PyUnicode_FromFormat("<bpy_struct, %.200s dead>", Py_TYPE(self)->tp_name); + return PyUnicode_FromFormat("<bpy_struct, %.200s dead>", + Py_TYPE(self)->tp_name); } /* print name if available */ name= RNA_struct_name_get_alloc(&self->ptr, NULL, FALSE); if(name) { - ret= PyUnicode_FromFormat("<bpy_struct, %.200s(\"%.200s\")>", RNA_struct_identifier(self->ptr.type), name); + ret= PyUnicode_FromFormat("<bpy_struct, %.200s(\"%.200s\")>", + RNA_struct_identifier(self->ptr.type), + name); 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>", + RNA_struct_identifier(self->ptr.type), + self->ptr.data); } static PyObject *pyrna_struct_repr(BPy_StructRNA *self) { ID *id= self->ptr.id.data; + PyObject *tmp_str; + PyObject *ret; + if(id == NULL || !PYRNA_STRUCT_IS_VALID(self)) return pyrna_struct_str(self); /* fallback */ + tmp_str= PyUnicode_FromString(id->name+2); + if(RNA_struct_is_ID(self->ptr.type)) { - return PyUnicode_FromFormat("bpy.data.%s[\"%s\"]", BKE_idcode_to_name_plural(GS(id->name)), id->name+2); + ret= PyUnicode_FromFormat("bpy.data.%s[%R]", + BKE_idcode_to_name_plural(GS(id->name)), + tmp_str); } else { - PyObject *ret; const char *path; path= RNA_path_from_ID_to_struct(&self->ptr); if(path) { - ret= PyUnicode_FromFormat("bpy.data.%s[\"%s\"].%s", BKE_idcode_to_name_plural(GS(id->name)), id->name+2, path); + ret= PyUnicode_FromFormat("bpy.data.%s[%R].%s", + BKE_idcode_to_name_plural(GS(id->name)), + tmp_str, + path); MEM_freeN((void *)path); } else { /* cant find, print something sane */ - ret= PyUnicode_FromFormat("bpy.data.%s[\"%s\"]...%s", BKE_idcode_to_name_plural(GS(id->name)), id->name+2, RNA_struct_identifier(self->ptr.type)); + ret= PyUnicode_FromFormat("bpy.data.%s[%R]...%s", + BKE_idcode_to_name_plural(GS(id->name)), + tmp_str, + RNA_struct_identifier(self->ptr.type)); } - - return ret; } + + Py_DECREF(tmp_str); + + return ret; } static PyObject *pyrna_prop_str(BPy_PropertyRNA *self) @@ -856,7 +877,7 @@ static PyObject *pyrna_prop_str(BPy_PropertyRNA *self) if(type==PROP_COLLECTION) { len= pyrna_prop_collection_length(self); } - else if (RNA_property_array_check(&self->ptr, self->prop)) { + else if (RNA_property_array_check(self->prop)) { len= pyrna_prop_array_length((BPy_PropertyArrayRNA *)self); } @@ -870,7 +891,11 @@ static PyObject *pyrna_prop_str(BPy_PropertyRNA *self) name= RNA_struct_name_get_alloc(&ptr, NULL, FALSE); if(name) { - ret= PyUnicode_FromFormat("<bpy_%.200s, %.200s.%.200s(\"%.200s\")>", type_fmt, RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop), name); + ret= PyUnicode_FromFormat("<bpy_%.200s, %.200s.%.200s(\"%.200s\")>", + type_fmt, + RNA_struct_identifier(self->ptr.type), + RNA_property_identifier(self->prop), + name); MEM_freeN((void *)name); return ret; } @@ -878,40 +903,59 @@ static PyObject *pyrna_prop_str(BPy_PropertyRNA *self) if(RNA_property_type(self->prop) == PROP_COLLECTION) { PointerRNA r_ptr; if(RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) { - return PyUnicode_FromFormat("<bpy_%.200s, %.200s>", type_fmt, RNA_struct_identifier(r_ptr.type)); + return PyUnicode_FromFormat("<bpy_%.200s, %.200s>", + type_fmt, + RNA_struct_identifier(r_ptr.type)); } } - return PyUnicode_FromFormat("<bpy_%.200s, %.200s.%.200s>", type_fmt, RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop)); + return PyUnicode_FromFormat("<bpy_%.200s, %.200s.%.200s>", + type_fmt, + RNA_struct_identifier(self->ptr.type), + RNA_property_identifier(self->prop)); } static PyObject *pyrna_prop_repr(BPy_PropertyRNA *self) { - ID *id; + ID *id= self->ptr.id.data; + PyObject *tmp_str; PyObject *ret; const char *path; PYRNA_PROP_CHECK_OBJ(self) - if((id= self->ptr.id.data) == NULL) + if(id == NULL) return pyrna_prop_str(self); /* fallback */ + tmp_str= PyUnicode_FromString(id->name+2); + path= RNA_path_from_ID_to_property(&self->ptr, self->prop); if(path) { - ret= PyUnicode_FromFormat("bpy.data.%s[\"%s\"].%s", BKE_idcode_to_name_plural(GS(id->name)), id->name+2, path); + ret= PyUnicode_FromFormat("bpy.data.%s[%R].%s", + BKE_idcode_to_name_plural(GS(id->name)), + tmp_str, + path); MEM_freeN((void *)path); } else { /* cant find, print something sane */ - ret= PyUnicode_FromFormat("bpy.data.%s[\"%s\"]...%s", BKE_idcode_to_name_plural(GS(id->name)), id->name+2, RNA_property_identifier(self->prop)); + ret= PyUnicode_FromFormat("bpy.data.%s[%R]...%s", + BKE_idcode_to_name_plural(GS(id->name)), + tmp_str, + RNA_property_identifier(self->prop)); } + Py_DECREF(tmp_str); + return ret; } static PyObject *pyrna_func_repr(BPy_FunctionRNA *self) { - return PyUnicode_FromFormat("<%.200s %.200s.%.200s()>", Py_TYPE(self)->tp_name, RNA_struct_identifier(self->ptr.type), RNA_function_identifier(self->func)); + return PyUnicode_FromFormat("<%.200s %.200s.%.200s()>", + Py_TYPE(self)->tp_name, + RNA_struct_identifier(self->ptr.type), + RNA_function_identifier(self->func)); } @@ -1073,6 +1117,7 @@ static int pyrna_string_to_enum(PyObject *item, PointerRNA *ptr, PropertyRNA *pr return 1; } +/* 'value' _must_ be a set type, error check before calling */ int pyrna_set_to_enum_bitfield(EnumPropertyItem *items, PyObject *value, int *r_value, const char *error_prefix) { /* set of enum items, concatenate all values with OR */ @@ -1094,8 +1139,10 @@ int pyrna_set_to_enum_bitfield(EnumPropertyItem *items, PyObject *value, int *r_ error_prefix, Py_TYPE(key)->tp_name); return -1; } - if(pyrna_enum_value_from_id(items, param, &ret, error_prefix) < 0) + + if(pyrna_enum_value_from_id(items, param, &ret, error_prefix) < 0) { return -1; + } flag |= ret; } @@ -1112,6 +1159,14 @@ static int pyrna_prop_to_enum_bitfield(PointerRNA *ptr, PropertyRNA *prop, PyObj *r_value= 0; + if (!PyAnySet_Check(value)) { + PyErr_Format(PyExc_TypeError, + "%.200s, %.200s.%.200s expected a set, not a %.200s", + error_prefix, RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), Py_TYPE(value)->tp_name); + return -1; + } + RNA_property_enum_items(BPy_GetContext(), ptr, prop, &item, NULL, &free); if(item) { @@ -1196,7 +1251,7 @@ static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val) #if 0 // gives python decoding errors while generating docs :( char error_str[256]; - snprintf(error_str, sizeof(error_str), "RNA Warning: Current value \"%d\" matches no enum in '%s', '%s', '%s'", val, RNA_struct_identifier(ptr->type), ptr_name, RNA_property_identifier(prop)); + BLI_snprintf(error_str, sizeof(error_str), "RNA Warning: Current value \"%d\" matches no enum in '%s', '%s', '%s'", val, RNA_struct_identifier(ptr->type), ptr_name, RNA_property_identifier(prop)); PyErr_Warn(PyExc_RuntimeWarning, error_str); #endif @@ -1224,7 +1279,7 @@ PyObject *pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) PyObject *ret; int type= RNA_property_type(prop); - if (RNA_property_array_check(ptr, prop)) { + if (RNA_property_array_check(prop)) { return pyrna_py_from_array(ptr, prop); } @@ -1369,7 +1424,7 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb int type= RNA_property_type(prop); - if (RNA_property_array_check(ptr, prop)) { + if (RNA_property_array_check(prop)) { /* done getting the length */ if(pyrna_py_to_array(ptr, prop, data, value, error_prefix) == -1) { return -1; @@ -1485,33 +1540,18 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb { int val= 0; - if (PyUnicode_Check(value)) { - if (!pyrna_string_to_enum(value, ptr, prop, &val, error_prefix)) - return -1; - } - else if (PyAnySet_Check(value)) { - if(RNA_property_flag(prop) & PROP_ENUM_FLAG) { - /* set of enum items, concatenate all values with OR */ - if(pyrna_prop_to_enum_bitfield(ptr, prop, value, &val, error_prefix) < 0) - return -1; - } - else { - PyErr_Format(PyExc_TypeError, - "%.200s, %.200s.%.200s is not a bitflag enum type", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop)); + /* type checkins is done by each function */ + if(RNA_property_flag(prop) & PROP_ENUM_FLAG) { + /* set of enum items, concatenate all values with OR */ + if(pyrna_prop_to_enum_bitfield(ptr, prop, value, &val, error_prefix) < 0) { return -1; } } else { - const char *enum_str= pyrna_enum_as_string(ptr, prop); - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s expected a string enum or a set of strings in (%.2000s), not %.200s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), enum_str, - Py_TYPE(value)->tp_name); - MEM_freeN((void *)enum_str); - return -1; + /* simple enum string */ + if (!pyrna_string_to_enum(value, ptr, prop, &val, error_prefix) < 0) { + return -1; + } } if(data) *((int*)data)= val; @@ -2995,7 +3035,9 @@ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname) else if (self->ptr.type == &RNA_Context) { bContext *C= self->ptr.data; if(C==NULL) { - PyErr_Format(PyExc_AttributeError, "bpy_struct: Context is 'NULL', can't get \"%.200s\" from context", name); + PyErr_Format(PyExc_AttributeError, + "bpy_struct: Context is 'NULL', can't get \"%.200s\" from context", + name); ret= NULL; } else { @@ -3054,7 +3096,9 @@ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname) } else { #if 0 - PyErr_Format(PyExc_AttributeError, "bpy_struct: attribute \"%.200s\" not found", name); + PyErr_Format(PyExc_AttributeError, + "bpy_struct: attribute \"%.200s\" not found", + name); ret= NULL; #endif /* Include this incase this instance is a subtype of a python class @@ -3170,7 +3214,9 @@ static int pyrna_struct_meta_idprop_setattro(PyObject *cls, PyObject *attr, PyOb const 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); + PyErr_Format(PyExc_TypeError, + "struct_meta_idprop.detattr(): '%s' not a dynamic property", + attr_str); return -1; } } @@ -3208,7 +3254,9 @@ static int pyrna_struct_setattro(BPy_StructRNA *self, PyObject *pyname, PyObject /* code just raises correct error, context prop's cant be set, unless its apart of the py class */ bContext *C= self->ptr.data; if(C==NULL) { - PyErr_Format(PyExc_AttributeError, "bpy_struct: Context is 'NULL', can't set \"%.200s\" from context", name); + PyErr_Format(PyExc_AttributeError, + "bpy_struct: Context is 'NULL', can't set \"%.200s\" from context", + name); return -1; } else { @@ -3219,7 +3267,9 @@ static int pyrna_struct_setattro(BPy_StructRNA *self, PyObject *pyname, PyObject int done= CTX_data_get(C, name, &newptr, &newlb, &newtype); if(done==1) { - PyErr_Format(PyExc_AttributeError, "bpy_struct: Context property \"%.200s\" is read-only", name); + PyErr_Format(PyExc_AttributeError, + "bpy_struct: Context property \"%.200s\" is read-only", + name); BLI_freelistN(&newlb); return -1; } @@ -3363,7 +3413,9 @@ static int pyrna_prop_collection_setattro(BPy_PropertyRNA *self, PyObject *pynam } } - PyErr_Format(PyExc_AttributeError, "bpy_prop_collection: attribute \"%.200s\" not found", name); + PyErr_Format(PyExc_AttributeError, + "bpy_prop_collection: attribute \"%.200s\" not found", + name); return -1; } @@ -4048,11 +4100,14 @@ static PyObject *pyrna_struct_new(PyTypeObject *type, PyObject *args, PyObject * } /* error, invalid type given */ - PyErr_Format(PyExc_TypeError, "bpy_struct.__new__(type): type '%.200s' is not a subtype of bpy_struct", type->tp_name); + PyErr_Format(PyExc_TypeError, + "bpy_struct.__new__(type): type '%.200s' is not a subtype of bpy_struct", + type->tp_name); return NULL; } else { - PyErr_Format(PyExc_TypeError, "bpy_struct.__new__(type): expected a single argument"); + PyErr_Format(PyExc_TypeError, + "bpy_struct.__new__(type): expected a single argument"); return NULL; } } @@ -4077,7 +4132,9 @@ static PyObject *pyrna_prop_new(PyTypeObject *type, PyObject *args, PyObject *UN return (PyObject *)ret; } else { - PyErr_Format(PyExc_TypeError, "bpy_prop.__new__(type): type '%.200s' is not a subtype of bpy_prop", type->tp_name); + PyErr_Format(PyExc_TypeError, + "bpy_prop.__new__(type): type '%.200s' is not a subtype of bpy_prop", + type->tp_name); return NULL; } } @@ -4088,7 +4145,7 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat int type= RNA_property_type(prop); int flag= RNA_property_flag(prop); - if(RNA_property_array_check(ptr, prop)) { + if(RNA_property_array_check(prop)) { int a, len; if (flag & PROP_DYNAMIC) { @@ -4139,7 +4196,9 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat } break; default: - PyErr_Format(PyExc_TypeError, "RNA Error: unknown array type \"%d\" (pyrna_param_to_py)", type); + PyErr_Format(PyExc_TypeError, + "RNA Error: unknown array type \"%d\" (pyrna_param_to_py)", + type); ret= NULL; break; } @@ -4237,7 +4296,9 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat break; } default: - PyErr_Format(PyExc_TypeError, "RNA Error: unknown type \"%d\" (pyrna_param_to_py)", type); + PyErr_Format(PyExc_TypeError, + "RNA Error: unknown type \"%d\" (pyrna_param_to_py)", + type); ret= NULL; break; } @@ -4246,6 +4307,26 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat return ret; } +/* Use to replace PyDict_GetItemString() when the overhead of converting a + * string into a python unicode is higher than a non hash lookup. + * works on small dict's such as keyword args. */ +static PyObject *small_dict_get_item_string(PyObject *dict, const char *key_lookup) +{ + PyObject *key= NULL; + Py_ssize_t pos = 0; + PyObject *value = NULL; + + while (PyDict_Next(dict, &pos, &key, &value)) { + if(PyUnicode_Check(key)) { + if(strcmp(key_lookup, _PyUnicode_AsString(key))==0) { + return value; + } + } + } + + return NULL; +} + static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject *kw) { /* Note, both BPy_StructRNA and BPy_PropertyRNA can be used here */ @@ -4258,7 +4339,6 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject PropertyRNA *parm; PyObject *ret, *item; int i, pyargs_len, pykw_len, parms_len, ret_len, flag, err= 0, kw_tot= 0, kw_arg; - const char *parm_id; PropertyRNA *pret_single= NULL; void *retdata_single= NULL; @@ -4334,28 +4414,33 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject continue; } - parm_id= RNA_property_identifier(parm); item= NULL; if (i < pyargs_len) { item= PyTuple_GET_ITEM(args, i); - i++; - kw_arg= FALSE; } else if (kw != NULL) { - item= PyDict_GetItemString(kw, parm_id); /* borrow ref */ +#if 0 + item= PyDict_GetItemString(kw, RNA_property_identifier(parm)); /* borrow ref */ +#else + item= small_dict_get_item_string(kw, RNA_property_identifier(parm)); /* borrow ref */ +#endif if(item) kw_tot++; /* make sure invalid keywords are not given */ kw_arg= TRUE; } + i++; /* current argument */ + if (item==NULL) { if(flag & PROP_REQUIRED) { PyErr_Format(PyExc_TypeError, "%.200s.%.200s(): required parameter \"%.200s\" not specified", - RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func), parm_id); + RNA_struct_identifier(self_ptr->type), + RNA_function_identifier(self_func), + RNA_property_identifier(parm)); err= -1; break; } @@ -4382,9 +4467,18 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject PyErr_Clear(); /* re-raise */ if(kw_arg==TRUE) - snprintf(error_prefix, sizeof(error_prefix), "%s.%s(): error with keyword argument \"%s\" - ", RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func), parm_id); + BLI_snprintf(error_prefix, sizeof(error_prefix), + "%.200s.%.200s(): error with keyword argument \"%.200s\" - ", + RNA_struct_identifier(self_ptr->type), + RNA_function_identifier(self_func), + RNA_property_identifier(parm)); else - snprintf(error_prefix, sizeof(error_prefix), "%s.%s(): error with argument %d, \"%s\" - ", RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func), i, parm_id); + BLI_snprintf(error_prefix, sizeof(error_prefix), + "%.200s.%.200s(): error with argument %d, \"%.200s\" - ", + RNA_struct_identifier(self_ptr->type), + RNA_function_identifier(self_func), + i, + RNA_property_identifier(parm)); pyrna_py_to_prop(&funcptr, parm, iter.data, item, error_prefix); @@ -5519,7 +5613,7 @@ PyObject *pyrna_prop_CreatePyObject(PointerRNA *ptr, PropertyRNA *prop) { BPy_PropertyRNA *pyrna; - if (RNA_property_array_check(ptr, prop) == 0) { + if (RNA_property_array_check(prop) == 0) { PyTypeObject *type; if (RNA_property_type(prop) != PROP_COLLECTION) { @@ -6323,7 +6417,21 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param err= -1; } else if(ret_len==1) { - err= pyrna_py_to_prop(&funcptr, pret_single, retdata_single, ret, "calling class function:"); + err= pyrna_py_to_prop(&funcptr, pret_single, retdata_single, ret, ""); + + /* when calling operator funcs only gives Function.result with + * no line number since the func has finished calling on error, + * re-raise the exception with more info since it would be slow to + * create prefix on every call (when there are no errors) */ + if(err == -1 && PyErr_Occurred()) { + PyObject *error_type, *error_value, *error_traceback; + PyErr_Fetch(&error_type, &error_value, &error_traceback); + + PyErr_Format(error_type, + "class %.200s, function %.200s: incompatible return value%S", + RNA_struct_identifier(ptr->type), RNA_function_identifier(func), + error_value); + } } else if (ret_len > 1) { @@ -6483,9 +6591,9 @@ 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:`Panel`,\n" -" :class:`Menu`, :class:`Header`, :class:`Operator`,\n" -" :class:`KeyingSetInfo`, :class:`RenderEngine`).\n" +" Register a subclass of a blender type in (:class:`bpy.types.Panel`,\n" +" :class:`bpy.types.Menu`, :class:`bpy.types.Header`, :class:`bpy.types.Operator`,\n" +" :class:`bpy.types.KeyingSetInfo`, :class:`bpy.types.RenderEngine`).\n" "\n" " If the class has a *register* class method it will be called\n" " before registration.\n" diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c index 30d83e196ba..8bde1db96ca 100644 --- a/source/blender/python/intern/bpy_rna_anim.c +++ b/source/blender/python/intern/bpy_rna_anim.c @@ -107,7 +107,7 @@ static int pyrna_struct_anim_args_parse(PointerRNA *ptr, const char *error_prefi return -1; } - if(RNA_property_array_check(&r_ptr, prop) == 0) { + if(RNA_property_array_check(prop) == 0) { if((*index) == -1) { *index= 0; } diff --git a/source/blender/python/intern/bpy_rna_array.c b/source/blender/python/intern/bpy_rna_array.c index 9843a57e0f2..e50ce233671 100644 --- a/source/blender/python/intern/bpy_rna_array.c +++ b/source/blender/python/intern/bpy_rna_array.c @@ -285,17 +285,20 @@ static char *copy_values(PyObject *seq, PointerRNA *ptr, PropertyRNA *prop, int int totdim= RNA_property_array_dimension(ptr, prop, NULL); const int seq_size= PySequence_Size(seq); - /* General note for 'data' being NULL or PySequence_GetItem() failing. + /* Regarding PySequence_GetItem() failing. * * This should never be NULL since we validated it, _but_ some triky python * developer could write their own sequence type which succeeds on - * validating but fails later somehow, so include checks for safety. */ + * validating but fails later somehow, so include checks for safety. + */ + + /* Note that 'data can be NULL' */ if(seq_size == -1) { return NULL; } - for (i= 0; (i < seq_size) && data; i++) { + for (i= 0; i < seq_size; i++) { PyObject *item= PySequence_GetItem(seq, i); if(item) { if (dim + 1 < totdim) { diff --git a/source/blender/python/intern/bpy_traceback.c b/source/blender/python/intern/bpy_traceback.c index 17f082b79dc..747a876d6df 100644 --- a/source/blender/python/intern/bpy_traceback.c +++ b/source/blender/python/intern/bpy_traceback.c @@ -30,9 +30,9 @@ #include "bpy_traceback.h" -static const char *traceback_filepath(PyTracebackObject *tb) +static const char *traceback_filepath(PyTracebackObject *tb, PyObject **coerce) { - return _PyUnicode_AsString(tb->tb_frame->f_code->co_filename); + return PyBytes_AS_STRING((*coerce= PyUnicode_EncodeFSDefault(tb->tb_frame->f_code->co_filename))); } /* copied from pythonrun.c, 3.2.0 */ @@ -146,7 +146,12 @@ void python_script_error_jump(const char *filepath, int *lineno, int *offset) PyErr_Print(); for(tb= (PyTracebackObject *)PySys_GetObject("last_traceback"); tb && (PyObject *)tb != Py_None; tb= tb->tb_next) { - if(strcmp(traceback_filepath(tb), filepath) != 0) { + PyObject *coerce; + const char *tb_filepath= traceback_filepath(tb, &coerce); + const int match= strcmp(tb_filepath, filepath) != 0; + Py_DECREF(coerce); + + if(match) { *lineno= tb->tb_lineno; break; } diff --git a/source/blender/python/intern/bpy_util.h b/source/blender/python/intern/bpy_util.h index b16c8fe2e8c..09fbdf96ed2 100644 --- a/source/blender/python/intern/bpy_util.h +++ b/source/blender/python/intern/bpy_util.h @@ -51,6 +51,7 @@ short BPy_errors_to_report(struct ReportList *reports); struct bContext *BPy_GetContext(void); void BPy_SetContext(struct bContext *C); +extern void bpy_context_update(struct bContext *C); extern void bpy_context_set(struct bContext *C, PyGILState_STATE *gilstate); extern void bpy_context_clear(struct bContext *C, PyGILState_STATE *gilstate); #endif diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index 5d0e467f6e8..d0c1d6ae200 100755 --- a/source/blender/python/mathutils/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -37,8 +37,6 @@ #include "BLI_math.h" #include "BLI_utildefines.h" -extern void PyC_LineSpit(void); - #define MAX_DIMENSIONS 4 /* Swizzle axes get packed into a single value that is used as a closure. Each @@ -1161,28 +1159,18 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2) } else if (vec1) { if (MatrixObject_Check(v2)) { - extern void PyC_LineSpit(void); - - /* VEC * MATRIX */ - /* this is deprecated!, use the reverse instead */ - float tvec[MAX_DIMENSIONS]; - /* ------ to be removed ------*/ -#ifndef MATH_STANDALONE -#ifdef WITH_ASSERT_ABORT +#if 1 PyErr_SetString(PyExc_ValueError, "(Vector * Matrix) is now removed, reverse the " "order (promoted to an Error for Debug builds)"); return NULL; #else - printf("Warning: (Vector * Matrix) is now deprecated, " - "reverse the multiplication order in the script.\n"); - PyC_LineSpit(); -#endif -#endif /* ifndef MATH_STANDALONE */ -/* ------ to be removed ------*/ + /* VEC * MATRIX */ + /* this is deprecated!, use the reverse instead */ + float tvec[MAX_DIMENSIONS]; if(BaseMath_ReadCallback((MatrixObject *)v2) == -1) return NULL; @@ -1191,9 +1179,18 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2) } return newVectorObject(tvec, vec1->size, Py_NEW, Py_TYPE(vec1)); +#endif +/* ------ to be removed ------*/ } else if (QuaternionObject_Check(v2)) { /* VEC * QUAT */ +/* ------ to be removed ------*/ +#if 1 + PyErr_SetString(PyExc_ValueError, + "(Vector * Quat) is now removed, reverse the " + "order (promoted to an Error for Debug builds)"); + return NULL; +#else QuaternionObject *quat2 = (QuaternionObject*)v2; float tvec[3]; @@ -1207,26 +1204,11 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2) return NULL; } - -/* ------ to be removed ------*/ -#ifndef MATH_STANDALONE -#ifdef WITH_ASSERT_ABORT - PyErr_SetString(PyExc_ValueError, - "(Vector * Quat) is now removed, reverse the " - "order (promoted to an Error for Debug builds)"); - return NULL; -#else - printf("Warning: (Vector * Quat) is now deprecated, " - "reverse the multiplication order in the script.\n"); - PyC_LineSpit(); -#endif -#endif /* ifndef MATH_STANDALONE */ -/* ------ to be removed ------*/ - - copy_v3_v3(tvec, vec1->vec); mul_qt_v3(quat2->quat, tvec); return newVectorObject(tvec, 3, Py_NEW, Py_TYPE(vec1)); +#endif +/* ------ to be removed ------*/ } else if (((scalar= PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred())==0) { /* VEC * FLOAT */ return vector_mul_float(vec1, scalar); @@ -1260,6 +1242,14 @@ static PyObject *Vector_imul(PyObject *v1, PyObject *v2) /* only support vec*=float and vec*=mat vec*=vec result is a float so that wont work */ if (MatrixObject_Check(v2)) { +/* ------ to be removed ------*/ +#if 1 + PyErr_SetString(PyExc_ValueError, + "(Vector *= Matrix) is now removed, reverse the " + "order (promoted to an Error for Debug builds) " + "and uses the non in-place multiplication."); + return NULL; +#else float rvec[MAX_DIMENSIONS]; if(BaseMath_ReadCallback((MatrixObject *)v2) == -1) return NULL; @@ -1267,28 +1257,21 @@ static PyObject *Vector_imul(PyObject *v1, PyObject *v2) if(column_vector_multiplication(rvec, vec, (MatrixObject*)v2) == -1) return NULL; - -/* ------ to be removed ------*/ -#ifndef MATH_STANDALONE -#ifdef WITH_ASSERT_ABORT - PyErr_SetString(PyExc_ValueError, - "(Vector *= Matrix) is now removed, reverse the " - "order (promoted to an Error for Debug builds) " - "and uses the non in-place multiplication."); - return NULL; -#else - printf("Warning: (Vector *= Matrix) is now deprecated, " - "reverse the (non in-place) multiplication order in the script.\n"); - PyC_LineSpit(); + memcpy(vec->vec, rvec, sizeof(float) * vec->size); #endif -#endif /* ifndef MATH_STANDALONE */ /* ------ to be removed ------*/ - - - memcpy(vec->vec, rvec, sizeof(float) * vec->size); } else if (QuaternionObject_Check(v2)) { /* VEC *= QUAT */ + +/* ------ to be removed ------*/ +#if 1 + PyErr_SetString(PyExc_ValueError, + "(Vector *= Quat) is now removed, reverse the " + "order (promoted to an Error for Debug builds) " + "and uses the non in-place multiplication."); + return NULL; +#else QuaternionObject *quat2 = (QuaternionObject*)v2; if(vec->size != 3) { @@ -1302,25 +1285,9 @@ static PyObject *Vector_imul(PyObject *v1, PyObject *v2) return NULL; } - -/* ------ to be removed ------*/ -#ifndef MATH_STANDALONE -#ifdef WITH_ASSERT_ABORT - PyErr_SetString(PyExc_ValueError, - "(Vector *= Quat) is now removed, reverse the " - "order (promoted to an Error for Debug builds) " - "and uses the non in-place multiplication."); - return NULL; -#else - printf("Warning: (Vector *= Quat) is now deprecated, " - "reverse the (non in-place) multiplication order in the script.\n"); - PyC_LineSpit(); + mul_qt_v3(quat2->quat, vec->vec); #endif -#endif /* ifndef MATH_STANDALONE */ /* ------ to be removed ------*/ - - - mul_qt_v3(quat2->quat, vec->vec); } else if (((scalar= PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred())==0) { /* VEC *= FLOAT */ mul_vn_fl(vec->vec, vec->size, scalar); @@ -1728,6 +1695,21 @@ static int Vector_setLength(VectorObject *self, PyObject *value) return 0; } +/* vector.length_squared */ +static PyObject *Vector_getLengthSquared(VectorObject *self, void *UNUSED(closure)) +{ + double dot = 0.0f; + int i; + + if(BaseMath_ReadCallback(self) == -1) + return NULL; + + for(i = 0; i < self->size; i++){ + dot += (double)(self->vec[i] * self->vec[i]); + } + return PyFloat_FromDouble(dot); +} + /* Get a new Vector according to the provided swizzle. This function has little error checking, as we are in control of the inputs: the closure is set by us in Vector_createSwizzleGetSeter. */ @@ -1851,6 +1833,7 @@ static PyGetSetDef Vector_getseters[] = { {(char *)"z", (getter)Vector_getAxis, (setter)Vector_setAxis, (char *)"Vector Z axis (3D Vectors only).\n\n:type: float", (void *)2}, {(char *)"w", (getter)Vector_getAxis, (setter)Vector_setAxis, (char *)"Vector W axis (4D Vectors only).\n\n:type: float", (void *)3}, {(char *)"length", (getter)Vector_getLength, (setter)Vector_setLength, (char *)"Vector Length.\n\n:type: float", NULL}, + {(char *)"length_squared", (getter)Vector_getLengthSquared, (setter)NULL, (char *)"Vector length squared (v.dot(v)).\n\n:type: float", NULL}, {(char *)"magnitude", (getter)Vector_getLength, (setter)Vector_setLength, (char *)"Vector Length.\n\n:type: float", NULL}, {(char *)"is_wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, (char *)BaseMathObject_Wrapped_doc, NULL}, {(char *)"owner", (getter)BaseMathObject_getOwner, (setter)NULL, (char *)BaseMathObject_Owner_doc, NULL}, |