Merged changes in the trunk up to revision 37799.

Note for VS2008 plus CMake users:
I had to remove OpenEXR debug libs from the "blender" project properties >
Linker > Additional Dependencies.  Otherwise I got a number of linker errors
concerning duplicated symbols between libcmt.lib and libcmtd.lib.
This commit is contained in:
2011-06-25 00:49:53 +00:00
207 changed files with 16803 additions and 15630 deletions

View File

@@ -34,7 +34,6 @@ set(INC
../../editors/include
../../freestyle/intern/python
../../../../intern/guardedalloc
../../../../intern/audaspace/intern
)
set(INC_SYS
@@ -44,8 +43,10 @@ set(INC_SYS
set(SRC
bpy.c
bpy_app.c
bpy_app_handlers.c
bpy_driver.c
bpy_interface.c
bpy_intern_string.c
bpy_library.c
bpy_operator.c
bpy_operator_wrap.c
@@ -60,7 +61,9 @@ set(SRC
bpy.h
bpy_app.h
bpy_app_handlers.h
bpy_driver.h
bpy_intern_string.h
bpy_operator.h
bpy_operator_wrap.h
bpy_props.h
@@ -85,4 +88,11 @@ if(WITH_PYTHON_SAFETY)
add_definitions(-DWITH_PYTHON_SAFETY)
endif()
if(WITH_AUDASPACE)
list(APPEND INC
../../../intern/audaspace/intern
)
add_definitions(-DWITH_AUDASPACE)
endif()
blender_add_lib(bf_python "${SRC}" "${INC}" "${INC_SYS}")

View File

@@ -60,8 +60,6 @@
#include "../generic/blf_py_api.h"
#include "../generic/IDProp.h"
#include "AUD_PyInit.h"
#include "BPy_Freestyle.h"
PyObject *bpy_package_py= NULL;

View File

@@ -30,6 +30,7 @@
#include <Python.h>
#include "bpy_app.h"
#include "bpy_app_handlers.h"
#include "bpy_driver.h"
#include "BLI_path_util.h"
@@ -74,6 +75,9 @@ static PyStructSequence_Field app_info_fields[]= {
{(char *)"build_cxxflags", (char *)"C++ compiler flags"},
{(char *)"build_linkflags", (char *)"Binary linking flags"},
{(char *)"build_system", (char *)"Build system used"},
/* submodules */
{(char *)"handlers", (char *)"Application handler callbacks"},
{NULL}
};
@@ -140,6 +144,8 @@ static PyObject *make_app_info(void)
SetStrItem("Unknown");
#endif
SetObjItem(BPY_app_handlers_struct());
#undef SetIntItem
#undef SetStrItem
#undef SetObjItem

View File

@@ -0,0 +1,170 @@
/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/python/intern/bpy_app_handlers.c
* \ingroup pythonintern
*/
#include <Python.h>
#include "BLI_utildefines.h"
#include "BLI_callbacks.h"
#include "RNA_types.h"
#include "RNA_access.h"
#include "bpy_rna.h"
#include "bpy_app_handlers.h"
void bpy_app_generic_callback(struct Main *main, struct ID *id, void *arg);
static PyTypeObject BlenderAppCbType;
static PyStructSequence_Field app_cb_info_fields[]= {
{(char *)"render_pre", NULL},
{(char *)"render_post", NULL},
{(char *)"load_pre", NULL},
{(char *)"load_post", NULL},
{(char *)"save_pre", NULL},
{(char *)"save_post", NULL},
{NULL}
};
static PyStructSequence_Desc app_cb_info_desc= {
(char *)"bpy.app.handlers", /* name */
(char *)"This module contains callbacks", /* doc */
app_cb_info_fields, /* fields */
(sizeof(app_cb_info_fields)/sizeof(PyStructSequence_Field)) - 1
};
/*
#if (BLI_CB_EVT_TOT != ((sizeof(app_cb_info_fields)/sizeof(PyStructSequence_Field))))
# error "Callbacks are out of sync"
#endif
*/
static PyObject *py_cb_array[BLI_CB_EVT_TOT]= {0};
static PyObject *make_app_cb_info(void)
{
PyObject *app_cb_info;
int pos= 0;
app_cb_info= PyStructSequence_New(&BlenderAppCbType);
if (app_cb_info == NULL) {
return NULL;
}
for(pos= 0; pos < BLI_CB_EVT_TOT; pos++) {
if(app_cb_info_fields[pos].name == NULL) {
Py_FatalError("invalid callback slots 1");
}
PyStructSequence_SET_ITEM(app_cb_info, pos, (py_cb_array[pos]= PyList_New(0)));
}
if(app_cb_info_fields[pos].name != NULL) {
Py_FatalError("invalid callback slots 2");
}
return app_cb_info;
}
PyObject *BPY_app_handlers_struct(void)
{
PyObject *ret;
PyStructSequence_InitType(&BlenderAppCbType, &app_cb_info_desc);
ret= make_app_cb_info();
/* prevent user from creating new instances */
BlenderAppCbType.tp_init= NULL;
BlenderAppCbType.tp_new= NULL;
/* assign the C callbacks */
if(ret) {
static bCallbackFuncStore funcstore_array[BLI_CB_EVT_TOT]= {{0}};
bCallbackFuncStore *funcstore;
int pos= 0;
for(pos= 0; pos < BLI_CB_EVT_TOT; pos++) {
funcstore= &funcstore_array[pos];
funcstore->func= bpy_app_generic_callback;
funcstore->alloc= 0;
funcstore->arg= SET_INT_IN_POINTER(pos);
BLI_add_cb(funcstore, pos);
}
}
return ret;
}
void BPY_app_handlers_reset(void)
{
int pos= 0;
for(pos= 0; pos < BLI_CB_EVT_TOT; pos++) {
PyList_SetSlice(py_cb_array[pos], 0, PY_SSIZE_T_MAX, NULL);
}
}
/* the actual callback - not necessarily called from py */
void bpy_app_generic_callback(struct Main *UNUSED(main), struct ID *id, void *arg)
{
PyObject *cb_list= py_cb_array[GET_INT_FROM_POINTER(arg)];
Py_ssize_t cb_list_len;
if((cb_list_len= PyList_GET_SIZE(cb_list)) > 0) {
PyGILState_STATE gilstate= PyGILState_Ensure();
PyObject* args= PyTuple_New(1); // save python creating each call
PyObject* func;
PyObject* ret;
Py_ssize_t pos;
/* setup arguments */
if(id) {
PointerRNA id_ptr;
RNA_id_pointer_create(id, &id_ptr);
PyTuple_SET_ITEM(args, 0, pyrna_struct_CreatePyObject(&id_ptr));
}
else {
PyTuple_SET_ITEM(args, 0, Py_None);
Py_INCREF(Py_None);
}
// Iterate the list and run the callbacks
for (pos=0; pos < cb_list_len; pos++) {
func= PyList_GET_ITEM(cb_list, pos);
ret= PyObject_Call(func, args, NULL);
if (ret==NULL) {
PyErr_Print();
PyErr_Clear();
}
else {
Py_DECREF(ret);
}
}
Py_DECREF(args);
PyGILState_Release(gilstate);
}
}

View File

@@ -0,0 +1,35 @@
/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/python/intern/bpy_app_handlers.h
* \ingroup pythonintern
*/
#ifndef BPY_APP_HANDLERS_H
#define BPY_APP_HANDLERS_H
PyObject *BPY_app_handlers_struct(void);
void BPY_app_handlers_clear(void);
#endif // BPY_APP_HANDLERS_H

View File

@@ -43,6 +43,7 @@
#include "bpy_rna.h"
#include "bpy_util.h"
#include "bpy_traceback.h"
#include "bpy_intern_string.h"
#include "DNA_space_types.h"
#include "DNA_text_types.h"
@@ -178,7 +179,9 @@ static struct _inittab bpy_internal_modules[]= {
// {(char *)"mathutils.geometry", BPyInit_mathutils_geometry},
{(char *)"bgl", BPyInit_bgl},
{(char *)"blf", BPyInit_blf},
#ifdef WITH_AUDASPACE
{(char *)"aud", AUD_initPython},
#endif
{NULL, NULL}
};
@@ -199,13 +202,15 @@ void BPY_python_start(int argc, const char **argv)
/* allow to use our own included python */
PyC_SetHomePath(BLI_get_folder(BLENDER_SYSTEM_PYTHON, NULL));
/* Python 3.2 now looks for '2.57/python/include/python3.2d/pyconfig.h' to parse
/* Python 3.2 now looks for '2.58/python/include/python3.2d/pyconfig.h' to parse
* from the 'sysconfig' module which is used by 'site', so for now disable site.
* alternatively we could copy the file. */
Py_NoSiteFlag= 1;
Py_Initialize();
bpy_intern_string_init();
// PySys_SetArgv(argc, argv); // broken in py3, not a huge deal
/* sigh, why do python guys not have a char** version anymore? :( */
{
@@ -251,7 +256,9 @@ void BPY_python_end(void)
pyrna_free_types();
/* clear all python data from structs */
bpy_intern_string_exit();
Py_Finalize();
#ifdef TIME_PY_RUN

View File

@@ -0,0 +1,57 @@
/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/python/intern/bpy_intern_string.c
* \ingroup pythonintern
*/
#include <Python.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_bl_rna= PyUnicode_FromString("bl_rna");
bpy_intern_str_order= PyUnicode_FromString("order");
bpy_intern_str_attr= PyUnicode_FromString("attr");
bpy_intern_str___slots__= PyUnicode_FromString("__slots__");
}
void bpy_intern_string_exit(void)
{
Py_DECREF(bpy_intern_str_register);
Py_DECREF(bpy_intern_str_unregister);
Py_DECREF(bpy_intern_str_bl_rna);
Py_DECREF(bpy_intern_str_order);
Py_DECREF(bpy_intern_str_attr);
Py_DECREF(bpy_intern_str___slots__);
}

View File

@@ -0,0 +1,37 @@
/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/python/intern/bpy_intern_string.h
* \ingroup pythonintern
*/
void bpy_intern_string_init(void);
void bpy_intern_string_exit(void);
extern PyObject *bpy_intern_str_register;
extern PyObject *bpy_intern_str_unregister;
extern PyObject *bpy_intern_str_bl_rna;
extern PyObject *bpy_intern_str_order;
extern PyObject *bpy_intern_str_attr;
extern PyObject *bpy_intern_str___slots__;

View File

@@ -459,7 +459,7 @@ static PyObject *BPy_BoolVectorProperty(PyObject *self, PyObject *args, PyObject
return NULL;
}
if(pydef && PyC_AsArray(def, pydef, size, &PyBool_Type, "BoolVectorProperty(default=sequence)") < 0)
if(pydef && PyC_AsArray(def, pydef, size, &PyBool_Type, FALSE, "BoolVectorProperty(default=sequence)") < 0)
return NULL;
if (bpy_prop_callback_check(update_cb, 2) == -1) {
@@ -603,7 +603,7 @@ static PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject
return NULL;
}
if(pydef && PyC_AsArray(def, pydef, size, &PyLong_Type, "IntVectorProperty(default=sequence)") < 0)
if(pydef && PyC_AsArray(def, pydef, size, &PyLong_Type, FALSE, "IntVectorProperty(default=sequence)") < 0)
return NULL;
if (bpy_prop_callback_check(update_cb, 2) == -1) {
@@ -759,7 +759,7 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec
return NULL;
}
if(pydef && PyC_AsArray(def, pydef, size, &PyFloat_Type, "FloatVectorProperty(default=sequence)") < 0)
if(pydef && PyC_AsArray(def, pydef, size, &PyFloat_Type, FALSE, "FloatVectorProperty(default=sequence)") < 0)
return NULL;
if (bpy_prop_callback_check(update_cb, 2) == -1) {

View File

@@ -39,6 +39,7 @@
#include "bpy_props.h"
#include "bpy_util.h"
#include "bpy_rna_callback.h"
#include "bpy_intern_string.h"
#ifdef USE_PYRNA_INVALIDATE_WEAKREF
#include "MEM_guardedalloc.h"
@@ -1380,12 +1381,8 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb
if (RNA_property_array_check(ptr, prop)) {
int ok= 1;
/* done getting the length */
ok= pyrna_py_to_array(ptr, prop, data, value, error_prefix);
if (!ok) {
if(pyrna_py_to_array(ptr, prop, data, value, error_prefix) == -1) {
return -1;
}
}
@@ -1476,7 +1473,7 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb
param= _PyUnicode_AsString(value);
}
#else // USE_STRING_COERCE
param= _PyUnicode_AsStringSize(value);
param= _PyUnicode_AsString(value);
#endif // USE_STRING_COERCE
if (param==NULL) {
@@ -1767,8 +1764,8 @@ static int pyrna_py_to_prop_array_index(BPy_PropertyArrayRNA *self, int index, P
if (totdim > 1) {
/* char error_str[512]; */
if (!pyrna_py_to_array_index(&self->ptr, self->prop, self->arraydim, self->arrayoffset, index, value, "")) {
/* PyErr_SetString(PyExc_AttributeError, error_str); */
if (pyrna_py_to_array_index(&self->ptr, self->prop, self->arraydim, self->arrayoffset, index, value, "") == -1) {
/* error is set */
ret= -1;
}
}
@@ -5221,7 +5218,7 @@ static void pyrna_subtype_set_rna(PyObject *newclass, StructRNA *srna)
item= pyrna_struct_CreatePyObject(&ptr);
/* note, must set the class not the __dict__ else the internal slots are not updated correctly */
PyObject_SetAttrString(newclass, "bl_rna", item);
PyObject_SetAttr(newclass, bpy_intern_str_bl_rna, item);
Py_DECREF(item);
/* done with rna instance */
@@ -5283,7 +5280,7 @@ static PyObject* pyrna_srna_ExternalType(StructRNA *srna)
//PyObject *slots= PyObject_GetAttrString(newclass, "__slots__"); // cant do this because it gets superclasses values!
//PyObject *bases= PyObject_GetAttrString(newclass, "__bases__"); // can do this but faster not to.
PyObject *bases= ((PyTypeObject *)newclass)->tp_bases;
PyObject *slots= PyDict_GetItemString(((PyTypeObject *)newclass)->tp_dict, "__slots__");
PyObject *slots= PyDict_GetItem(((PyTypeObject *)newclass)->tp_dict, bpy_intern_str___slots__);
if(slots==NULL) {
fprintf(stderr, "pyrna_srna_ExternalType: expected class '%s' to have __slots__ defined\n\nSee bpy_types.py\n", idname);
@@ -5653,7 +5650,7 @@ StructRNA *pyrna_struct_as_srna(PyObject *self, int parent, const char *error_pr
/* ack, PyObject_GetAttrString wont look up this types tp_dict first :/ */
if(PyType_Check(self)) {
py_srna= (BPy_StructRNA *)PyDict_GetItemString(((PyTypeObject *)self)->tp_dict, "bl_rna");
py_srna= (BPy_StructRNA *)PyDict_GetItem(((PyTypeObject *)self)->tp_dict, bpy_intern_str_bl_rna);
Py_XINCREF(py_srna);
}
@@ -5661,7 +5658,7 @@ StructRNA *pyrna_struct_as_srna(PyObject *self, int parent, const char *error_pr
/* be very careful with this since it will return a parent classes srna.
* modifying this will do confusing stuff! */
if(py_srna==NULL)
py_srna= (BPy_StructRNA*)PyObject_GetAttrString(self, "bl_rna");
py_srna= (BPy_StructRNA*)PyObject_GetAttr(self, bpy_intern_str_bl_rna);
}
if(py_srna==NULL) {
@@ -5751,7 +5748,7 @@ static int deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item
py_srna_cobject= PyCapsule_New(srna, NULL, NULL);
/* not 100% nice :/, modifies the dict passed, should be ok */
PyDict_SetItemString(py_kw, "attr", key);
PyDict_SetItem(py_kw, bpy_intern_str_attr, key);
args_fake= PyTuple_New(1);
PyTuple_SET_ITEM(args_fake, 0, py_srna_cobject);
@@ -5798,7 +5795,7 @@ static int pyrna_deferred_register_props(StructRNA *srna, PyObject *class_dict)
/* in both cases PyDict_CheckExact(class_dict) will be true even
* though Operators have a metaclass dict namespace */
if((order= PyDict_GetItemString(class_dict, "order")) && PyList_CheckExact(order)) {
if((order= PyDict_GetItem(class_dict, bpy_intern_str_order)) && PyList_CheckExact(order)) {
for(pos= 0; pos<PyList_GET_SIZE(order); pos++) {
key= PyList_GET_ITEM(order, pos);
item= PyDict_GetItem(class_dict, key);
@@ -6044,9 +6041,10 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
PyGILState_STATE gilstate;
#ifdef USE_PEDANTIC_WRITE
const int is_operator= RNA_struct_is_a(ptr->type, &RNA_Operator);
const char *func_id= RNA_function_identifier(func);
/* testing, for correctness, not operator and not draw function */
const short is_readonly= strstr("draw", func_id) || /*strstr("render", func_id) ||*/ !RNA_struct_is_a(ptr->type, &RNA_Operator);
const short is_readonly= strstr("draw", func_id) || /*strstr("render", func_id) ||*/ !is_operator;
#endif
py_class= RNA_struct_py_type_get(ptr->type);
@@ -6102,6 +6100,11 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
* Although this is annoying to have to impliment a part of pythons typeobject.c:type_call().
*/
if(py_class->tp_init) {
#ifdef USE_PEDANTIC_WRITE
const int prev_write= rna_disallow_writes;
rna_disallow_writes= is_operator ? FALSE : TRUE; /* only operators can write on __init__ */
#endif
/* true in most cases even when the class its self doesn't define an __init__ function. */
args= PyTuple_New(0);
if (py_class->tp_init(py_srna, args, NULL) < 0) {
@@ -6110,11 +6113,16 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
/* err set below */
}
Py_DECREF(args);
#ifdef USE_PEDANTIC_WRITE
rna_disallow_writes= prev_write;
#endif
}
py_class_instance= py_srna;
#else
const int prev_write= rna_disallow_writes;
rna_disallow_writes= TRUE;
/* 'almost' all the time calling the class isn't needed.
* We could just do...
py_class_instance= py_srna;
@@ -6128,7 +6136,10 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
py_class_instance= PyObject_Call(py_class, args, NULL);
Py_DECREF(args);
rna_disallow_writes= prev_write;
#endif
if(py_class_instance == NULL) {
err= -1; /* so the error is not overridden below */
}
@@ -6303,7 +6314,7 @@ static void bpy_class_free(void *pyob_ptr)
// PyDict_Clear(((PyTypeObject*)self)->tp_dict);
//
// remove the rna attribute instead.
PyDict_DelItemString(((PyTypeObject *)self)->tp_dict, "bl_rna");
PyDict_DelItem(((PyTypeObject *)self)->tp_dict, bpy_intern_str_bl_rna);
if(PyErr_Occurred())
PyErr_Clear();
@@ -6409,7 +6420,7 @@ static PyObject *pyrna_register_class(PyObject *UNUSED(self), PyObject *py_class
const char *identifier;
PyObject *py_cls_meth;
if(PyDict_GetItemString(((PyTypeObject*)py_class)->tp_dict, "bl_rna")) {
if(PyDict_GetItem(((PyTypeObject*)py_class)->tp_dict, bpy_intern_str_bl_rna)) {
PyErr_SetString(PyExc_AttributeError, "register_class(...): already registered as a subclass");
return NULL;
}
@@ -6474,7 +6485,7 @@ static PyObject *pyrna_register_class(PyObject *UNUSED(self), PyObject *py_class
return NULL;
/* call classed register method () */
py_cls_meth= PyObject_GetAttrString(py_class, "register");
py_cls_meth= PyObject_GetAttr(py_class, bpy_intern_str_register);
if(py_cls_meth == NULL) {
PyErr_Clear();
}
@@ -6532,7 +6543,7 @@ static PyObject *pyrna_unregister_class(PyObject *UNUSED(self), PyObject *py_cla
StructRNA *srna;
PyObject *py_cls_meth;
/*if(PyDict_GetItemString(((PyTypeObject*)py_class)->tp_dict, "bl_rna")==NULL) {
/*if(PyDict_GetItem(((PyTypeObject*)py_class)->tp_dict, bpy_intern_str_bl_rna)==NULL) {
PWM_cursor_wait(0);
PyErr_SetString(PyExc_ValueError, "unregister_class(): not a registered as a subclass");
return NULL;
@@ -6551,7 +6562,7 @@ static PyObject *pyrna_unregister_class(PyObject *UNUSED(self), PyObject *py_cla
}
/* call classed unregister method */
py_cls_meth= PyObject_GetAttrString(py_class, "unregister");
py_cls_meth= PyObject_GetAttr(py_class, bpy_intern_str_unregister);
if(py_cls_meth == NULL) {
PyErr_Clear();
}
@@ -6601,7 +6612,7 @@ static PyObject *pyrna_unregister_class(PyObject *UNUSED(self), PyObject *py_cla
/* call unregister */
unreg(CTX_data_main(C), srna); /* calls bpy_class_free, this decref's py_class */
PyDict_DelItemString(((PyTypeObject *)py_class)->tp_dict, "bl_rna");
PyDict_DelItem(((PyTypeObject *)py_class)->tp_dict, bpy_intern_str_bl_rna);
if(PyErr_Occurred())
PyErr_Clear(); //return NULL;

View File

@@ -68,17 +68,24 @@ static int validate_array_type(PyObject *seq, int dim, int totdim, int dimsize[]
/* check that a sequence contains dimsize[dim] items */
const int seq_size= PySequence_Size(seq);
if(seq_size == -1) {
PyErr_Format(PyExc_ValueError, "%s sequence expected at dimension %d, not %s", error_prefix, (int)dim + 1, Py_TYPE(seq)->tp_name);
return 0;
PyErr_Format(PyExc_ValueError, "%s sequence expected at dimension %d, not '%s'",
error_prefix, (int)dim + 1, Py_TYPE(seq)->tp_name);
return -1;
}
for (i= 0; i < seq_size; i++) {
PyObject *item;
int ok= 1;
item= PySequence_GetItem(seq, i);
if (!PySequence_Check(item)) {
if(item == NULL) {
PyErr_Format(PyExc_TypeError, "%s sequence type '%s' failed to retrieve index %d",
error_prefix, Py_TYPE(seq)->tp_name, i);
ok= 0;
}
else if (!PySequence_Check(item)) {
/* BLI_snprintf(error_str, error_str_size, "expected a sequence of %s", item_type_str); */
PyErr_Format(PyExc_TypeError, "%s expected a sequence of %s, not %s", error_prefix, item_type_str, Py_TYPE(item)->tp_name);
PyErr_Format(PyExc_TypeError, "%s expected a sequence of %s, not %s",
error_prefix, item_type_str, Py_TYPE(item)->tp_name);
ok= 0;
}
/* arr[3][4][5]
@@ -88,42 +95,50 @@ static int validate_array_type(PyObject *seq, int dim, int totdim, int dimsize[]
dim=0 */
else if (PySequence_Size(item) != dimsize[dim + 1]) {
/* BLI_snprintf(error_str, error_str_size, "sequences of dimension %d should contain %d items", (int)dim + 1, (int)dimsize[dim + 1]); */
PyErr_Format(PyExc_ValueError, "%s sequences of dimension %d should contain %d items", error_prefix, (int)dim + 1, (int)dimsize[dim + 1]);
PyErr_Format(PyExc_ValueError, "%s sequences of dimension %d should contain %d items",
error_prefix, (int)dim + 1, (int)dimsize[dim + 1]);
ok= 0;
}
else if (!validate_array_type(item, dim + 1, totdim, dimsize, check_item_type, item_type_str, error_prefix)) {
else if (validate_array_type(item, dim + 1, totdim, dimsize, check_item_type, item_type_str, error_prefix) == -1) {
ok= 0;
}
Py_DECREF(item);
Py_XDECREF(item);
if (!ok)
return 0;
return -1;
}
}
else {
/* check that items are of correct type */
const int seq_size= PySequence_Size(seq);
if(seq_size == -1) {
PyErr_Format(PyExc_ValueError, "%s sequence expected at dimension %d, not %s", error_prefix, (int)dim + 1, Py_TYPE(seq)->tp_name);
return 0;
PyErr_Format(PyExc_ValueError, "%s sequence expected at dimension %d, not '%s'",
error_prefix, (int)dim + 1, Py_TYPE(seq)->tp_name);
return -1;
}
for (i= 0; i < seq_size; i++) {
PyObject *item= PySequence_GetItem(seq, i);
if (!check_item_type(item)) {
if(item == NULL) {
PyErr_Format(PyExc_TypeError, "%s sequence type '%s' failed to retrieve index %d",
error_prefix, Py_TYPE(seq)->tp_name, i);
return -1;
}
else if (!check_item_type(item)) {
Py_DECREF(item);
/* BLI_snprintf(error_str, error_str_size, "sequence items should be of type %s", item_type_str); */
PyErr_Format(PyExc_TypeError, "%s expected sequence items of type %s, not %s", error_prefix, item_type_str, Py_TYPE(item)->tp_name);
return 0;
PyErr_Format(PyExc_TypeError, "%s expected sequence items of type %s, not %s",
error_prefix, item_type_str, Py_TYPE(item)->tp_name);
return -1;
}
Py_DECREF(item);
}
}
return 1;
return 0; /* ok */
}
/* Returns the number of items in a single- or multi-dimensional sequence. */
@@ -136,8 +151,21 @@ static int count_items(PyObject *seq, int dim)
int i;
for (i= 0; i < seq_size; i++) {
PyObject *item= PySequence_GetItem(seq, i);
totitem += count_items(item, dim - 1);
Py_DECREF(item);
if(item) {
const int tot= count_items(item, dim - 1);
Py_DECREF(item);
if(tot != -1) {
totitem += tot;
}
else {
totitem= -1;
break;
}
}
else {
totitem= -1;
break;
}
}
}
else {
@@ -156,18 +184,24 @@ static int validate_array_length(PyObject *rvalue, PointerRNA *ptr, PropertyRNA
totdim= RNA_property_array_dimension(ptr, prop, dimsize);
tot= count_items(rvalue, totdim - lvalue_dim);
if ((RNA_property_flag(prop) & PROP_DYNAMIC) && lvalue_dim == 0) {
if(tot == -1) {
PyErr_Format(PyExc_ValueError, "%s %.200s.%.200s, error validating the sequence length",
error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop));
return -1;
}
else if ((RNA_property_flag(prop) & PROP_DYNAMIC) && lvalue_dim == 0) {
if (RNA_property_array_length(ptr, prop) != tot) {
#if 0
/* length is flexible */
if (!RNA_property_dynamic_array_set_length(ptr, prop, tot)) {
/* BLI_snprintf(error_str, error_str_size, "%s.%s: array length cannot be changed to %d", RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), tot); */
PyErr_Format(PyExc_ValueError, "%s %s.%s: array length cannot be changed to %d", error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), tot);
return 0;
PyErr_Format(PyExc_ValueError, "%s %s.%s: array length cannot be changed to %d",
error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), tot);
return -1;
}
#else
*totitem= tot;
return 1;
return 0;
#endif
}
@@ -204,14 +238,15 @@ static int validate_array_length(PyObject *rvalue, PointerRNA *ptr, PropertyRNA
if (tot != len) {
/* BLI_snprintf(error_str, error_str_size, "sequence must have length of %d", len); */
PyErr_Format(PyExc_ValueError, "%s %.200s.%.200s, sequence must have %d items total, not %d", error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), len, tot);
return 0;
PyErr_Format(PyExc_ValueError, "%s %.200s.%.200s, sequence must have %d items total, not %d",
error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), len, tot);
return -1;
}
}
*totitem= len;
return 1;
return 0;
}
static int validate_array(PyObject *rvalue, PointerRNA *ptr, PropertyRNA *prop, int lvalue_dim, ItemTypeCheckFunc check_item_type, const char *item_type_str, int *totitem, const char *error_prefix)
@@ -221,8 +256,8 @@ static int validate_array(PyObject *rvalue, PointerRNA *ptr, PropertyRNA *prop,
/* validate type first because length validation may modify property array length */
if (!validate_array_type(rvalue, lvalue_dim, totdim, dimsize, check_item_type, item_type_str, error_prefix))
return 0;
if (validate_array_type(rvalue, lvalue_dim, totdim, dimsize, check_item_type, item_type_str, error_prefix) == -1)
return -1;
return validate_array_length(rvalue, ptr, prop, lvalue_dim, totitem, error_prefix);
}
@@ -250,25 +285,39 @@ 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);
assert(seq_size != -1);
/* General note for 'data' being NULL or 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. */
for (i= 0; i < seq_size; i++) {
if(seq_size == -1) {
return NULL;
}
for (i= 0; (i < seq_size) && data; i++) {
PyObject *item= PySequence_GetItem(seq, i);
if(item) {
if (dim + 1 < totdim) {
data= copy_values(item, ptr, prop, dim + 1, data, item_size, index, convert_item, rna_set_index);
}
else {
data= copy_value_single(item, ptr, prop, data, item_size, index, convert_item, rna_set_index);
}
if (dim + 1 < totdim) {
data= copy_values(item, ptr, prop, dim + 1, data, item_size, index, convert_item, rna_set_index);
Py_DECREF(item);
/* data may be NULL, but the for loop checks */
}
else {
data= copy_value_single(item, ptr, prop, data, item_size, index, convert_item, rna_set_index);
return NULL;
}
Py_DECREF(item);
}
return data;
}
static int py_to_array(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, char *param_data, ItemTypeCheckFunc check_item_type, const char *item_type_str, int item_size, ItemConvertFunc convert_item, RNA_SetArrayFunc rna_set_array, const char *error_prefix)
static int py_to_array(PyObject *seq, PointerRNA *ptr, PropertyRNA *prop, char *param_data, ItemTypeCheckFunc check_item_type, const char *item_type_str, int item_size, ItemConvertFunc convert_item, RNA_SetArrayFunc rna_set_array, const char *error_prefix)
{
/*int totdim, dim_size[MAX_ARRAY_DIMENSION];*/
int totitem;
@@ -276,8 +325,8 @@ static int py_to_array(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, char *p
/*totdim= RNA_property_array_dimension(ptr, prop, dim_size);*/ /*UNUSED*/
if (!validate_array(py, ptr, prop, 0, check_item_type, item_type_str, &totitem, error_prefix)) {
return 0;
if (validate_array(seq, ptr, prop, 0, check_item_type, item_type_str, &totitem, error_prefix) == -1) {
return -1;
}
if (totitem) {
@@ -297,16 +346,27 @@ static int py_to_array(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, char *p
data= PyMem_MALLOC(item_size * totitem);
}
copy_values(py, ptr, prop, 0, data, item_size, NULL, convert_item, NULL);
/* will only fail in very rare cases since we already validated the
* python data, the check here is mainly for completeness. */
if(copy_values(seq, ptr, prop, 0, data, item_size, NULL, convert_item, NULL) != NULL) {
if (param_data==NULL) {
/* NULL can only pass through in case RNA property arraylength is 0 (impossible?) */
rna_set_array(ptr, prop, data);
PyMem_FREE(data);
}
}
else {
if (param_data==NULL) {
PyMem_FREE(data);
}
if (param_data==NULL) {
/* NULL can only pass through in case RNA property arraylength is 0 (impossible?) */
rna_set_array(ptr, prop, data);
PyMem_FREE(data);
PyErr_Format(PyExc_TypeError, "%s internal error parsing sequence of type '%s' after successful validation",
error_prefix, Py_TYPE(seq)->tp_name);
return -1;
}
}
return 1;
return 0;
}
static int py_to_array_index(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, int lvalue_dim, int arrayoffset, int index, ItemTypeCheckFunc check_item_type, const char *item_type_str, ItemConvertFunc convert_item, RNA_SetIndexFunc rna_set_index, const char *error_prefix)
@@ -335,21 +395,24 @@ static int py_to_array_index(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, i
if(lvalue_dim == totdim) { /* single item, assign directly */
if(!check_item_type(py)) {
PyErr_Format(PyExc_TypeError, "%s %.200s.%.200s, expected a %s type, not %s", error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), item_type_str, Py_TYPE(py)->tp_name);
return 0;
PyErr_Format(PyExc_TypeError, "%s %.200s.%.200s, expected a %s type, not %s",
error_prefix, RNA_struct_identifier(ptr->type),
RNA_property_identifier(prop), item_type_str,
Py_TYPE(py)->tp_name);
return -1;
}
copy_value_single(py, ptr, prop, NULL, 0, &index, convert_item, rna_set_index);
}
else {
if (!validate_array(py, ptr, prop, lvalue_dim, check_item_type, item_type_str, &totitem, error_prefix)) {
return 0;
if (validate_array(py, ptr, prop, lvalue_dim, check_item_type, item_type_str, &totitem, error_prefix) == -1) {
return -1;
}
if (totitem) {
copy_values(py, ptr, prop, lvalue_dim, NULL, 0, &index, convert_item, rna_set_index);
}
}
return 1;
return 0;
}
static void py_to_float(PyObject *py, char *data)
@@ -414,7 +477,7 @@ int pyrna_py_to_array(PointerRNA *ptr, PropertyRNA *prop, char *param_data, PyOb
break;
default:
PyErr_SetString(PyExc_TypeError, "not an array type");
ret= 0;
ret= -1;
}
return ret;
@@ -435,7 +498,7 @@ int pyrna_py_to_array_index(PointerRNA *ptr, PropertyRNA *prop, int arraydim, in
break;
default:
PyErr_SetString(PyExc_TypeError, "not an array type");
ret= 0;
ret= -1;
}
return ret;

View File

@@ -122,63 +122,3 @@ short BPy_errors_to_report(ReportList *reports)
Py_DECREF(pystring_format); // workaround
return 1;
}
/* array utility function */
int PyC_AsArray(void *array, PyObject *value, int length, PyTypeObject *type, const char *error_prefix)
{
PyObject *value_fast;
int value_len;
int i;
if(!(value_fast=PySequence_Fast(value, error_prefix))) {
return -1;
}
value_len= PySequence_Fast_GET_SIZE(value_fast);
if(value_len != length) {
Py_DECREF(value);
PyErr_Format(PyExc_TypeError,
"%.200s: invalid sequence length. expected %d, got %d",
error_prefix, length, value_len);
return -1;
}
/* for each type */
if(type == &PyFloat_Type) {
float *array_float= array;
for(i=0; i<length; i++) {
array_float[i]= PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value_fast, i));
}
}
else if(type == &PyLong_Type) {
int *array_int= array;
for(i=0; i<length; i++) {
array_int[i]= PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value_fast, i));
}
}
else if(type == &PyBool_Type) {
int *array_bool= array;
for(i=0; i<length; i++) {
array_bool[i]= (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value_fast, i)) != 0);
}
}
else {
Py_DECREF(value_fast);
PyErr_Format(PyExc_TypeError,
"%s: internal error %s is invalid",
error_prefix, type->tp_name);
return -1;
}
Py_DECREF(value_fast);
if(PyErr_Occurred()) {
PyErr_Format(PyExc_TypeError,
"%s: one or more items could not be used as a %s",
error_prefix, type->tp_name);
return -1;
}
return 0;
}