From 3e29ff72049f4dc831e568e5a7ecfd13348a147c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 29 Dec 2008 12:04:25 +0000 Subject: * was using __members__ to get a list of attributes, has been deprecated in python for a while now. use a "__dir__" method instead. now dir() works for rna and operator types. * added array support for bpyoperator doc generation --- source/blender/python/epy_doc_gen.py | 50 ++++++++--- source/blender/python/intern/bpy_operator.c | 124 +++++++++++++-------------- source/blender/python/intern/bpy_opwrapper.c | 21 +---- source/blender/python/intern/bpy_opwrapper.h | 6 +- source/blender/python/intern/bpy_rna.c | 54 +++++++----- 5 files changed, 135 insertions(+), 120 deletions(-) (limited to 'source/blender/python') diff --git a/source/blender/python/epy_doc_gen.py b/source/blender/python/epy_doc_gen.py index 01c4f20962d..77b0c245dbd 100644 --- a/source/blender/python/epy_doc_gen.py +++ b/source/blender/python/epy_doc_gen.py @@ -35,6 +35,10 @@ def range_str(val): else: return str(val) +def get_array_str(length): + if length > 0: return ' array of %d items' % length + else: return '' + def rna2epy(target_path): @@ -80,8 +84,7 @@ def rna2epy(target_path): try: length = rna_prop.array_length except: length = 0 - if length > 0: array_str = ' array of %d items' % length - else: array_str = '' + array_str = get_array_str(length) if rna_prop.readonly: readonly_str = ' (readonly)' else: readonly_str = '' @@ -158,9 +161,10 @@ def rna2epy(target_path): def op2epy(target_path): out = open(target_path, 'w') - operators = bpyoperator.__members__ + operators = dir(bpyoperator) operators.remove('add') operators.remove('remove') + operators.remove('__dir__') operators.sort() @@ -173,7 +177,8 @@ def op2epy(target_path): rna = getattr(bpyoperator, op).rna rna_struct = rna.rna_type - # print (op_rna.__members__) + # print (dir(rna)) + # print (dir(rna_struct)) for rna_prop_identifier, rna_prop in rna_struct.properties.items(): if rna_prop_identifier=='rna_type': continue @@ -181,40 +186,59 @@ def op2epy(target_path): #rna_prop= op_rna.rna_type.properties[attr] rna_prop_type = rna_prop.type.lower() # enum, float, int, boolean + try: length = rna_prop.array_length + except: length = 0 + + array_str = get_array_str(length) + try: val = getattr(rna, rna_prop_identifier) except: val = '' - kw_type_str= "@type %s: %s" % (rna_prop_identifier, rna_prop_type) + kw_type_str= "@type %s: %s%s" % (rna_prop_identifier, rna_prop_type, array_str) kw_param_str= "@param %s: %s" % (rna_prop_identifier, rna_prop.description) kw_param_set = False if rna_prop_type=='float': - val_str= '%g' % val - if '.' not in val_str: - val_str += '.0' + if length==0: + val_str= '%g' % val + if '.' not in val_str: + val_str += '.0' + else: + # array + val_str = str(tuple(val)) + kw_param_str += (' in (%s, %s)' % (range_str(rna_prop.hard_min), range_str(rna_prop.hard_max))) kw_param_set= True elif rna_prop_type=='int': - val_str='%d' % val - # print (rna_prop.__members__) + if length==0: + val_str='%d' % val + else: + val_str = str(tuple(val)) + + # print(dir(rna_prop)) kw_param_str += (' in (%s, %s)' % (range_str(rna_prop.hard_min), range_str(rna_prop.hard_max))) # These strings dont have a max length??? #kw_param_str += ' (maximum length of %s)' % (rna_prop.max_length) kw_param_set= True elif rna_prop_type=='boolean': - if val: val_str='True' - else: val_str='False' - + if length==0: + if val: val_str='True' + else: val_str='False' + else: + val_str = str(tuple(val)) + elif rna_prop_type=='enum': + # no array here? val_str="'%s'" % val kw_param_str += (' in (%s)' % ', '.join(rna_prop.items.keys())) kw_param_set= True elif rna_prop_type=='string': + # no array here? val_str='"%s"' % val # todo - collection - array diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index 1babaebdab8..24e44c153e2 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -106,8 +106,8 @@ int PYOP_props_from_dict(PointerRNA *ptr, PyObject *kw) return error_val; } -/* floats bigger then this are displayed as inf in the docstrings */ -#define MAXFLOAT_DOC 10000000 + + static int pyop_func_compare( BPy_OperatorFunc * a, BPy_OperatorFunc * b ) { @@ -133,76 +133,45 @@ static PyObject *pyop_base_getattro( BPy_OperatorBase * self, PyObject *pyname ) PyObject *ret; wmOperatorType *ot; - if( strcmp( name, "__members__" ) == 0 ) { - PyObject *item; - ret = PyList_New(2); - - PyList_SET_ITEM(ret, 0, PyUnicode_FromString("add")); - PyList_SET_ITEM(ret, 1, PyUnicode_FromString("remove")); - - for(ot= WM_operatortype_first(); ot; ot= ot->next) { - item = PyUnicode_FromString( ot->idname ); - PyList_Append(ret, item); - Py_DECREF(item); - } + if ((ot = WM_operatortype_find(name))) { + ret= pyop_func_CreatePyObject(self->C, name); } - else if ( strcmp( name, "add" ) == 0 ) { - ret= PYOP_wrap_add_func(); - } - else if ( strcmp( name, "remove" ) == 0 ) { - ret= PYOP_wrap_remove_func(); + else if ((ret = PyObject_GenericGetAttr((PyObject *)self, pyname))) { + /* do nothing, this accounts for methoddef's add and remove */ } else { - ot = WM_operatortype_find(name); - - if (ot) { - ret= pyop_func_CreatePyObject(self->C, name); - } - else { - PyErr_Format( PyExc_AttributeError, "Operator \"%s\" not found", name); - ret= NULL; - } + PyErr_Format( PyExc_AttributeError, "Operator \"%s\" not found", name); + ret= NULL; } return ret; } -//---------------getattr-------------------------------------------- -static PyObject * pyop_func_getattro(BPy_OperatorFunc * self, PyObject *pyname) +/* getseter's */ +PyObject *pyop_func_get_rna(BPy_OperatorFunc *self) { - char *name = _PyUnicode_AsString(pyname); - PyObject *ret; + BPy_StructRNA *pyrna; + PointerRNA ptr; + wmOperatorType *ot; - if( strcmp( name, "__members__" ) == 0 ) { - ret = PyList_New(1); - PyList_SET_ITEM(ret, 0, PyUnicode_FromString("rna")); + ot= WM_operatortype_find(self->name); + if (ot == NULL) { + PyErr_SetString( PyExc_SystemError, "Operator could not be found"); + return NULL; } - else if ( strcmp( name, "rna" ) == 0 ) { - BPy_StructRNA *pyrna; - PointerRNA ptr; - //IDProperty *properties = NULL; - wmOperatorType *ot; - - ot= WM_operatortype_find(self->name); - if (ot == NULL) { - PyErr_SetString( PyExc_SystemError, "Operator could not be found"); - return NULL; - } - - pyrna= (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr); /* were not really using &ptr, overwite next */ - /* XXX POINTER - if this 'ot' is python generated, it could be free'd */ - RNA_pointer_create(NULL, NULL, ot->srna, &pyrna->properties, &pyrna->ptr); - ret= (PyObject *)pyrna; - } - else { - PyErr_Format( PyExc_AttributeError, "Operator \"%s\" not found", name); - ret= NULL; - } + pyrna= (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr); /* were not really using &ptr, overwite next */ - return ret; + /* XXX POINTER - if this 'ot' is python generated, it could be free'd */ + RNA_pointer_create(NULL, NULL, ot->srna, &pyrna->properties, &pyrna->ptr); + return (PyObject *)pyrna; } +static PyGetSetDef pyop_func_getseters[] = { + {"rna", (getter)pyop_func_get_rna, (setter)NULL, "vertex's coordinate", NULL}, + {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ +}; + static PyObject * pyop_func_call(BPy_OperatorFunc * self, PyObject *args, PyObject *kw) { IDProperty *properties = NULL; @@ -234,8 +203,6 @@ static PyObject * pyop_func_call(BPy_OperatorFunc * self, PyObject *args, PyObje IDP_FreeProperty(properties); MEM_freeN(properties); } - - #if 0 /* if there is some way to know an operator takes args we should use this */ { @@ -256,6 +223,37 @@ static PyObject * pyop_func_call(BPy_OperatorFunc * self, PyObject *args, PyObje Py_RETURN_NONE; } +static struct PyMethodDef pyop_base_methods[]; + +PyObject *pyop_base_dir(PyObject *self) +{ + PyObject *ret = PyList_New(0); + PyObject *item; + wmOperatorType *ot; + PyMethodDef *meth; + + for(ot= WM_operatortype_first(); ot; ot= ot->next) { + item = PyUnicode_FromString( ot->idname ); + PyList_Append(ret, item); + Py_DECREF(item); + } + + for(meth=pyop_base_methods; meth->ml_name; meth++) { + item = PyUnicode_FromString( meth->ml_name ); + PyList_Append(ret, item); + Py_DECREF(item); + } + + return ret; +} + +static struct PyMethodDef pyop_base_methods[] = { + {"add", (PyCFunction)PYOP_wrap_add, METH_VARARGS, ""}, + {"remove", (PyCFunction)PYOP_wrap_remove, METH_VARARGS, ""}, + {"__dir__", (PyCFunction)pyop_base_dir, METH_NOARGS, ""}, + {NULL, NULL, 0, NULL} +}; + /*-----------------------BPy_OperatorBase method def------------------------------*/ PyTypeObject pyop_base_Type = { #if (PY_VERSION_HEX >= 0x02060000) @@ -318,9 +316,9 @@ PyTypeObject pyop_base_Type = { NULL, /* iternextfunc tp_iternext; */ /*** Attribute descriptor and subclassing stuff ***/ - NULL, /* struct PyMethodDef *tp_methods; */ + pyop_base_methods, /* struct PyMethodDef *tp_methods; */ NULL, /* struct PyMemberDef *tp_members; */ - NULL, /* struct PyGetSetDef *tp_getset; */ + NULL, /* struct PyGetSetDef *tp_getset; */ NULL, /* struct _typeobject *tp_base; */ NULL, /* PyObject *tp_dict; */ NULL, /* descrgetfunc tp_descr_get; */ @@ -374,7 +372,7 @@ PyTypeObject pyop_func_Type = { NULL, /* hashfunc tp_hash; */ (ternaryfunc)pyop_func_call, /* ternaryfunc tp_call; */ NULL, /* reprfunc tp_str; */ - ( getattrofunc ) pyop_func_getattro, /* getattrofunc tp_getattro; */ + NULL, /* getattrofunc tp_getattro; */ NULL, /*PyObject_GenericSetAttr - MINGW Complains, assign later */ /* setattrofunc tp_setattro; */ /* Functions to access object as input/output buffer */ @@ -406,7 +404,7 @@ PyTypeObject pyop_func_Type = { /*** Attribute descriptor and subclassing stuff ***/ NULL, /* struct PyMethodDef *tp_methods; */ NULL, /* struct PyMemberDef *tp_members; */ - NULL, /* struct PyGetSetDef *tp_getset; */ + pyop_func_getseters, /* struct PyGetSetDef *tp_getset; */ NULL, /* struct _typeobject *tp_base; */ NULL, /* PyObject *tp_dict; */ NULL, /* descrgetfunc tp_descr_get; */ diff --git a/source/blender/python/intern/bpy_opwrapper.c b/source/blender/python/intern/bpy_opwrapper.c index aca340df01a..000bec3b675 100644 --- a/source/blender/python/intern/bpy_opwrapper.c +++ b/source/blender/python/intern/bpy_opwrapper.c @@ -322,7 +322,7 @@ void PYTHON_OT_wrapper(wmOperatorType *ot, void *userdata) } /* pyOperators - Operators defined IN Python */ -static PyObject *pyop_add(PyObject *self, PyObject *args) +PyObject *PYOP_wrap_add(PyObject *self, PyObject *args) { PyOperatorType *pyot; @@ -360,7 +360,7 @@ static PyObject *pyop_add(PyObject *self, PyObject *args) Py_RETURN_NONE; } -static PyObject *pyop_remove(PyObject *self, PyObject *args) +PyObject *PYOP_wrap_remove(PyObject *self, PyObject *args) { char *idname= NULL; wmOperatorType *ot; @@ -388,20 +388,3 @@ static PyObject *pyop_remove(PyObject *self, PyObject *args) Py_RETURN_NONE; } -static PyMethodDef pyop_add_methdef[] = { - {"add", pyop_add, METH_VARARGS, ""} -}; - -static PyMethodDef pyop_remove_methdef[] = { - {"remove", pyop_remove, METH_VARARGS, ""} -}; - -PyObject *PYOP_wrap_add_func( void ) -{ - return PyCFunction_New( pyop_add_methdef, NULL ); -} -PyObject *PYOP_wrap_remove_func( void ) -{ - return PyCFunction_New( pyop_remove_methdef, NULL ); -} - diff --git a/source/blender/python/intern/bpy_opwrapper.h b/source/blender/python/intern/bpy_opwrapper.h index 5e4c44056e6..ae607735498 100644 --- a/source/blender/python/intern/bpy_opwrapper.h +++ b/source/blender/python/intern/bpy_opwrapper.h @@ -27,9 +27,9 @@ #include -/* returns the python functions */ -PyObject *PYOP_wrap_add_func( void ); -PyObject *PYOP_wrap_remove_func( void ); +/* these are used for operator methods, used by bpy_operator.c */ +PyObject *PYOP_wrap_add(PyObject *self, PyObject *args); +PyObject *PYOP_wrap_remove(PyObject *self, PyObject *args); #endif diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index d761354f23b..a8409976b73 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -702,27 +702,7 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA * self, PyObject *pyname ) else PyErr_Clear(); /* done with subtypes */ - if( strcmp( name, "__members__" ) == 0 ) { - PyObject *item; - - PropertyRNA *iterprop; - CollectionPropertyIterator iter; - - ret = PyList_New(0); - - iterprop= RNA_struct_iterator_property(&self->ptr); - RNA_property_collection_begin(&self->ptr, iterprop, &iter); - - - for(; iter.valid; RNA_property_collection_next(&iter)) { - prop = iter.ptr.data; - item = PyUnicode_FromString( RNA_property_identifier(&iter.ptr, prop) ); - PyList_Append(ret, item); - Py_DECREF(item); - } - - RNA_property_collection_end(&iter); - } else if ( strcmp( name, "__doc__" ) == 0 ) { + if ( strcmp( name, "__doc__" ) == 0 ) { ret = pyrna_struct_to_docstring(self); } else { prop = RNA_struct_find_property(&self->ptr, name); @@ -758,6 +738,32 @@ static int pyrna_struct_setattro( BPy_StructRNA * self, PyObject *pyname, PyObje return pyrna_py_to_prop(&self->ptr, prop, value); } +static PyObject *pyrna_struct_dir( BPy_StructRNA * self ) +{ + PyObject *ret = PyList_New(0); + PyObject *item; + PropertyRNA *prop; + PropertyRNA *iterprop; + CollectionPropertyIterator iter; + + iterprop= RNA_struct_iterator_property(&self->ptr); + RNA_property_collection_begin(&self->ptr, iterprop, &iter); + + + for(; iter.valid; RNA_property_collection_next(&iter)) { + prop = iter.ptr.data; + item = PyUnicode_FromString( RNA_property_identifier(&iter.ptr, prop) ); + PyList_Append(ret, item); + Py_DECREF(item); + } + + RNA_property_collection_end(&iter); + + return ret; +} + + + PyObject *pyrna_prop_keys(BPy_PropertyRNA *self) { PyObject *ret; @@ -896,6 +902,10 @@ PyObject *pyrna_prop_iter(BPy_PropertyRNA *self) return NULL; } +static struct PyMethodDef pyrna_struct_methods[] = { + {"__dir__", (PyCFunction)pyrna_struct_dir, METH_NOARGS, ""}, + {NULL, NULL, 0, NULL} +}; static struct PyMethodDef pyrna_prop_methods[] = { {"keys", (PyCFunction)pyrna_prop_keys, METH_NOARGS, ""}, @@ -1002,7 +1012,7 @@ PyTypeObject pyrna_struct_Type = { NULL, /* iternextfunc tp_iternext; */ /*** Attribute descriptor and subclassing stuff ***/ - NULL, /* struct PyMethodDef *tp_methods; */ + pyrna_struct_methods, /* struct PyMethodDef *tp_methods; */ NULL, /* struct PyMemberDef *tp_members; */ NULL, /* struct PyGetSetDef *tp_getset; */ NULL, /* struct _typeobject *tp_base; */ -- cgit v1.2.3