diff options
author | Campbell Barton <ideasman42@gmail.com> | 2009-03-19 01:22:58 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2009-03-19 01:22:58 +0300 |
commit | 3aab50f775e4928d3ee525a999e2b4c995ae9ae4 (patch) | |
tree | 68c902e2336dd3e12f41e85cda9ade1f7025e9a0 | |
parent | 43d4e3fa7efca3ae2cedfd35fa344bf2ef298a7f (diff) |
* removed warnings and fixed some python refcount errors
* operator class names
- Changed 'name' to '__label__' (since __name__ is already used for the class name)
- Changed 'properties' to '__props__'
* added a PyObject_GetAttrStringArgs(), utility function which Id like to see in pythons C api.
PyObject_GetAttrStringArgs(pyob, "someattr", "foo", "bar") /* pyob.someattr.foo.bar */
-rw-r--r-- | source/blender/python/intern/bpy_interface.c | 1 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_operator.c | 2 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_opwrapper.c | 76 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.c | 10 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_ui.c | 1 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_util.c | 80 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_util.h | 3 |
7 files changed, 105 insertions, 68 deletions
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 54f7bb55cc0..8f01d60ad4b 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -264,6 +264,7 @@ int BPY_run_python_script_space(const char *modulename, const char *func) PyErr_SetFormat(PyExc_SystemError, "module has no function '%s.%s'\n", scpt->script.filename, func); } else { + Py_DECREF(py_func); if (!PyCallable_Check(py_func)) { PyErr_SetFormat(PyExc_SystemError, "module item is not callable '%s.%s'\n", scpt->script.filename, func); } diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index d2dbd6c91bb..a35c5ed2cb4 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -110,7 +110,7 @@ int PYOP_props_from_dict(PointerRNA *ptr, PyObject *kw) static PyObject *pyop_base_dir(PyObject *self); static struct PyMethodDef pyop_base_methods[] = { {"__dir__", (PyCFunction)pyop_base_dir, METH_NOARGS, ""}, - {"add", (PyCFunction)PYOP_wrap_add, METH_VARARGS, ""}, + {"add", (PyCFunction)PYOP_wrap_add, METH_O, ""}, {"remove", (PyCFunction)PYOP_wrap_remove, METH_O, ""}, {NULL, NULL, 0, NULL} }; diff --git a/source/blender/python/intern/bpy_opwrapper.c b/source/blender/python/intern/bpy_opwrapper.c index 328864ac8b8..379fda35bb6 100644 --- a/source/blender/python/intern/bpy_opwrapper.c +++ b/source/blender/python/intern/bpy_opwrapper.c @@ -40,6 +40,11 @@ #include "bpy_compat.h" #include "bpy_util.h" +#define PYOP_ATTR_PROP "__props__" +#define PYOP_ATTR_UINAME "__label__" +#define PYOP_ATTR_IDNAME "__name__" /* use pythons class name */ +#define PYOP_ATTR_DESCRIPTION "__doc__" /* use pythons docstring */ + typedef struct PyOperatorType { void *next, *prev; char idname[OP_MAX_TYPENAME]; @@ -316,17 +321,16 @@ void PYTHON_OT_wrapper(wmOperatorType *ot, void *userdata) ot->pyop_data= userdata; - // TODO - set properties - + props= PyObject_GetAttrString(py_class, PYOP_ATTR_PROP); - if ((props=PyObject_GetAttrString(py_class, "properties"))) { + if (props) { PyObject *dummy_args = PyTuple_New(0); - int i; + Py_DECREF(props); + for(i=0; i<PyList_Size(props); i++) { PyObject *py_func_ptr, *py_kw, *py_srna_cobject, *py_ret; - item = PyList_GET_ITEM(props, i); if (PyArg_ParseTuple(item, "O!O!", &PyCObject_Type, &py_func_ptr, &PyDict_Type, &py_kw)) { @@ -360,11 +364,9 @@ void PYTHON_OT_wrapper(wmOperatorType *ot, void *userdata) /* pyOperators - Operators defined IN Python */ -PyObject *PYOP_wrap_add(PyObject *self, PyObject *args) -{ - // XXX ugly - store the Operator type elsewhere!, probably leaks memory - PyObject *optype = PyObject_GetAttrString(PyObject_GetAttrString(PyDict_GetItemString(PyEval_GetGlobals(), "bpy"), "types"), "Operator"); - PyObject *value, *item; +PyObject *PYOP_wrap_add(PyObject *self, PyObject *value) +{ + PyObject *optype, *item; PyOperatorType *pyot; char *idname= NULL; @@ -373,30 +375,37 @@ PyObject *PYOP_wrap_add(PyObject *self, PyObject *args) static char *pyop_func_names[] = {"exec", "invoke", "poll", NULL}; static int pyop_func_nargs[] = {1, 2, 2, 0}; + + PyObject *pyargcount; + int i, argcount; + + + // in python would be... + //PyObject *optype = PyObject_GetAttrString(PyObject_GetAttrString(PyDict_GetItemString(PyEval_GetGlobals(), "bpy"), "types"), "Operator"); + optype = PyObject_GetAttrStringArgs(PyDict_GetItemString(PyEval_GetGlobals(), "bpy"), 2, "types", "Operator"); + Py_DECREF(optype); - int i; - int argcount; - - if (!PyArg_ParseTuple(args, "O", &value) || !PyObject_IsSubclass(value, optype)) { + if (!PyObject_IsSubclass(value, optype)) { PyErr_SetString( PyExc_AttributeError, "expected Operator subclass of bpy.types.Operator"); return NULL; } /* class name is used for operator ID - this can be changed later if we want */ - item = PyObject_GetAttrString(value, "__name__"); - idname = _PyUnicode_AsString(item); + item = PyObject_GetAttrString(value, PYOP_ATTR_IDNAME); Py_DECREF(item); + idname = _PyUnicode_AsString(item); + if (WM_operatortype_find(idname)) { - PyErr_Format( PyExc_AttributeError, "Operator already exists with this name: %s", idname); + PyErr_Format( PyExc_AttributeError, "Operator alredy exists with this name \"%s\"", idname); return NULL; } /* Operator user readible name */ - item = PyObject_GetAttrString(value, "name"); + item = PyObject_GetAttrString(value, PYOP_ATTR_UINAME); if (item) { - name = _PyUnicode_AsString(item); Py_DECREF(item); + name = _PyUnicode_AsString(item); } if (name == NULL) { name = idname; @@ -404,36 +413,37 @@ PyObject *PYOP_wrap_add(PyObject *self, PyObject *args) } /* use py docstring for description, should always be None or a string */ - item = PyObject_GetAttrString(value, "__doc__"); + item = PyObject_GetAttrString(value, PYOP_ATTR_DESCRIPTION); + Py_DECREF(item); + if (PyUnicode_Check(item)) { description = _PyUnicode_AsString(item); } else { description = ""; } - Py_DECREF(item); /* Check known functions and argument lengths */ for (i=0; pyop_func_names[i]; i++) { - if ((item=PyObject_GetAttrString(value, pyop_func_names[i]))) { - PyObject *pyargcount; + + item=PyObject_GetAttrString(value, pyop_func_names[i]); + if (item) { + Py_DECREF(item); /* check its callable */ if (!PyFunction_Check(item)) { PyErr_Format(PyExc_ValueError, "Cant register operator class - %s.%s() is not a function", idname, pyop_func_names[i]); - Py_DECREF(item); return NULL; } /* check the number of args is correct */ - // MyClass.exec.func_code.co_argcount + /* MyClass.exec.func_code.co_argcount */ - pyargcount = PyObject_GetAttrString(PyFunction_GetCode(item), "co_argcount"); - argcount = PyLong_AsSsize_t(pyargcount); + pyargcount = PyObject_GetAttrString(PyFunction_GET_CODE(item), "co_argcount"); Py_DECREF(pyargcount); + argcount = PyLong_AsSsize_t(pyargcount); if (argcount != pyop_func_nargs[i]) { PyErr_Format(PyExc_ValueError, "Cant register operator class - %s.%s() takes %d args, should be %d", idname, pyop_func_names[i], argcount, pyop_func_nargs[i]); - Py_DECREF(item); return NULL; } @@ -444,13 +454,12 @@ PyObject *PYOP_wrap_add(PyObject *self, PyObject *args) } /* If we have properties set, check its a list of dicts */ - item = PyObject_GetAttrString(value, "properties"); + item = PyObject_GetAttrString(value, PYOP_ATTR_PROP); if (item) { - int i; + Py_DECREF(item); if (!PyList_Check(item)) { - PyErr_Format(PyExc_ValueError, "Cant register operator class - %s.properties must be a list", idname); - Py_DECREF(item); + PyErr_Format(PyExc_ValueError, "Cant register operator class - %s.properties must be a list", idname); return NULL; } @@ -460,12 +469,9 @@ PyObject *PYOP_wrap_add(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(py_args, "O!O!", &PyCObject_Type, &py_func_ptr, &PyDict_Type, &py_kw)) { PyErr_Format(PyExc_ValueError, "Cant register operator class - %s.properties must contain values from FloatProperty", idname); - Py_DECREF(item); return NULL; } } - - Py_DECREF(item); } else { PyErr_Clear(); diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 193f2a8d3d2..650475bae96 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -1071,7 +1071,7 @@ PyObject* pyrna_struct_Subtype(PointerRNA *ptr) // Set this later if (newclass) { - BPy_RNA_PYTYPE(ptr->data) = newclass; /* Store for later use */ + BPy_RNA_PYTYPE(ptr->data) = (void *)newclass; /* Store for later use */ /* Not 100% needed but useful, * having an instance within a type looks wrong however this instance IS an rna type */ @@ -1198,8 +1198,8 @@ PyObject *BPY_rna_doc( void ) if (type) { name = PyObject_GetAttrString(type, "__name__"); /* myClass.__name__ */ if (name) { - PyDict_SetItem(dict, name, type); Py_DECREF(name); + PyDict_SetItem(dict, name, type); } else { printf("could not get type __name__\n"); @@ -1222,7 +1222,7 @@ PyObject *BPY_rna_doc( void ) * This isnt incorrect since its a python object - but be careful */ PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw) { - static char *kwlist[] = {"attribute", "name", "description", "min", "max", "soft_min", "soft_max", "default", NULL}; + static char *kwlist[] = {"attr", "name", "description", "min", "max", "soft_min", "soft_max", "default", NULL}; char *id, *name="", *description=""; float min=FLT_MIN, max=FLT_MAX, soft_min=FLT_MIN, soft_max=FLT_MAX, def=0.0f; @@ -1249,7 +1249,7 @@ PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw) PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw) { - static char *kwlist[] = {"attribute", "name", "description", "min", "max", "soft_min", "soft_max", "default", NULL}; + static char *kwlist[] = {"attr", "name", "description", "min", "max", "soft_min", "soft_max", "default", NULL}; char *id, *name="", *description=""; int min=INT_MIN, max=INT_MAX, soft_min=INT_MIN, soft_max=INT_MAX, def=0; @@ -1276,7 +1276,7 @@ PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw) PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw) { - static char *kwlist[] = {"attribute", "name", "description", "default", NULL}; + static char *kwlist[] = {"attr", "name", "description", "default", NULL}; char *id, *name="", *description=""; int def=0; diff --git a/source/blender/python/intern/bpy_ui.c b/source/blender/python/intern/bpy_ui.c index d9df8820e95..ca61c0b425b 100644 --- a/source/blender/python/intern/bpy_ui.c +++ b/source/blender/python/intern/bpy_ui.c @@ -418,7 +418,6 @@ static struct PyMethodDef ui_methods[] = { {"registerKey", (PyCFunction)Method_registerKey, METH_VARARGS, ""}, // XXX could have this in another place too - {"getRegonPtr", (PyCFunction)Method_getRegonPtr, METH_NOARGS, ""}, // XXX Nasty, we really need to improve dealing with context! {"getAreaPtr", (PyCFunction)Method_getAreaPtr, METH_NOARGS, ""}, {"getScreenPtr", (PyCFunction)Method_getScreenPtr, METH_NOARGS, ""}, diff --git a/source/blender/python/intern/bpy_util.c b/source/blender/python/intern/bpy_util.c index 724c99098f4..47ac739eac0 100644 --- a/source/blender/python/intern/bpy_util.c +++ b/source/blender/python/intern/bpy_util.c @@ -175,39 +175,67 @@ void PyLineSpit(void) { void BPY_getFileAndNum(char **filename, int *lineno) { PyObject *getframe, *frame; - PyObject *f_lineno, *f_code, *co_filename; + PyObject *f_lineno= NULL, *co_filename= NULL; if (filename) *filename= NULL; if (lineno) *lineno = -1; getframe = PySys_GetObject("_getframe"); // borrowed - if (getframe) { - frame = PyObject_CallObject(getframe, NULL); - if (frame) { - f_lineno= PyObject_GetAttrString(frame, "f_lineno"); - f_code= PyObject_GetAttrString(frame, "f_code"); - if (f_lineno && f_code) { - co_filename= PyObject_GetAttrString(f_code, "co_filename"); - if (co_filename) { - - if (filename) *filename = _PyUnicode_AsString(co_filename); - if (lineno) *lineno = (int)PyLong_AsSsize_t(f_lineno); - - Py_DECREF(f_lineno); - Py_DECREF(f_code); - Py_DECREF(co_filename); - Py_DECREF(frame); - - return; - } - } + if (getframe==NULL) { + return; + } + + frame = PyObject_CallObject(getframe, NULL); + if (frame==NULL) + return; + + if (filename) { + co_filename= PyObject_GetAttrStringArgs(frame, 1, "f_code", "co_filename"); + if (co_filename==NULL) { + PyErr_SetString(PyExc_SystemError, "Could not access sys._getframe().f_code.co_filename"); + Py_DECREF(frame); + return; } + + *filename = _PyUnicode_AsString(co_filename); + Py_DECREF(co_filename); } - Py_XDECREF(co_filename); - Py_XDECREF(f_lineno); - Py_XDECREF(f_code); - Py_XDECREF(frame); + if (lineno) { + f_lineno= PyObject_GetAttrString(frame, "f_lineno"); + if (f_lineno==NULL) { + PyErr_SetString(PyExc_SystemError, "Could not access sys._getframe().f_lineno"); + Py_DECREF(frame); + return; + } + + *lineno = (int)PyLong_AsSsize_t(f_lineno); + Py_DECREF(f_lineno); + } +} + +/* Would be nice if python had this built in */ +PyObject *PyObject_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...) +{ + Py_ssize_t i; + PyObject *item= o; + char *attr; + + va_list vargs; + + va_start(vargs, n); + for (i=0; i<n; i++) { + attr = va_arg(vargs, char *); + item = PyObject_GetAttrString(item, attr); + + if (item) + Py_DECREF(item); + else /* python will set the error value here */ + break; + + } + va_end(vargs); - PyErr_SetString(PyExc_SystemError, "Could not access sys._getframe().f_code.co_filename"); + Py_INCREF(item); /* final value has is increfed, to match PyObject_GetAttrString */ + return item; } diff --git a/source/blender/python/intern/bpy_util.h b/source/blender/python/intern/bpy_util.h index 4d4d552af4e..d6ee8feb767 100644 --- a/source/blender/python/intern/bpy_util.h +++ b/source/blender/python/intern/bpy_util.h @@ -37,3 +37,6 @@ int BPY_flag_from_seq(BPY_flag_def *flagdef, PyObject *seq, int *flag); void PyObSpit(char *name, PyObject *var); void PyLineSpit(void); void BPY_getFileAndNum(char **filename, int *lineno); + +/* own python like utility function */ +PyObject *PyObject_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...); |