- lazy subtype initialization rna, was initializing every type in bpy.types at startup, which is slow and doesn't allow access to dynamically added types.
- bpy.types isnt a module anymore, defined as its own PyType, getattr looks up the rna collection each time. - refcounting fixes - fixe epydoc generation with undefined values
This commit is contained in:
@@ -41,8 +41,6 @@ def get_array_str(length):
|
||||
|
||||
def rna2epy(target_path):
|
||||
|
||||
|
||||
|
||||
def write_struct(rna_struct, structs, ident):
|
||||
identifier = rna_struct.identifier
|
||||
|
||||
@@ -131,8 +129,11 @@ def rna2epy(target_path):
|
||||
for rna_type_name in dir(bpy.types):
|
||||
rna_type = getattr(bpy.types, rna_type_name)
|
||||
if hasattr(rna_type, '__rna__'):
|
||||
#if not rna_type_name.startswith('__'):
|
||||
rna_struct = rna_type.__rna__
|
||||
structs.append( (base_id(rna_struct), rna_struct.identifier, rna_struct) )
|
||||
else:
|
||||
print("Ignoring", rna_type_name)
|
||||
|
||||
|
||||
|
||||
@@ -160,7 +161,7 @@ def rna2epy(target_path):
|
||||
i+=1
|
||||
|
||||
if not ok:
|
||||
print('Dependancy "%s"could not be found for "%s"' % (identifier, rna_base))
|
||||
print('Dependancy "%s" could not be found for "%s"' % (identifier, rna_base))
|
||||
|
||||
break
|
||||
|
||||
@@ -199,7 +200,9 @@ def op2epy(target_path):
|
||||
kw_args = [] # "foo = 1", "bar=0.5", "spam='ENUM'"
|
||||
kw_arg_attrs = [] # "@type mode: int"
|
||||
|
||||
rna = getattr(bpy.types, op).__rna__
|
||||
# rna = getattr(bpy.types, op).__rna__
|
||||
rna = bpy.ops.__rna__(op)
|
||||
|
||||
rna_struct = rna.rna_type
|
||||
# print (dir(rna))
|
||||
# print (dir(rna_struct))
|
||||
@@ -217,14 +220,18 @@ def op2epy(target_path):
|
||||
|
||||
try:
|
||||
val = getattr(rna, rna_prop_identifier)
|
||||
val_error = False
|
||||
except:
|
||||
val = '<UNDEFINED>'
|
||||
val = "'<UNDEFINED>'"
|
||||
val_error = True
|
||||
|
||||
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':
|
||||
if val_error:
|
||||
val_str = val
|
||||
elif rna_prop_type=='float':
|
||||
if length==0:
|
||||
val_str= '%g' % val
|
||||
if '.' not in val_str:
|
||||
|
||||
@@ -108,8 +108,10 @@ int PYOP_props_from_dict(PointerRNA *ptr, PyObject *kw)
|
||||
}
|
||||
|
||||
static PyObject *pyop_base_dir(PyObject *self);
|
||||
static PyObject *pyop_base_rna(PyObject *self, PyObject *pyname);
|
||||
static struct PyMethodDef pyop_base_methods[] = {
|
||||
{"__dir__", (PyCFunction)pyop_base_dir, METH_NOARGS, ""},
|
||||
{"__rna__", (PyCFunction)pyop_base_rna, METH_O, ""},
|
||||
{"add", (PyCFunction)PYOP_wrap_add, METH_O, ""},
|
||||
{"remove", (PyCFunction)PYOP_wrap_remove, METH_O, ""},
|
||||
{NULL, NULL, 0, NULL}
|
||||
@@ -199,8 +201,9 @@ static PyObject *pyop_base_getattro( BPy_OperatorBase * self, PyObject *pyname )
|
||||
{
|
||||
char *name = _PyUnicode_AsString(pyname);
|
||||
PyObject *ret;
|
||||
wmOperatorType *ot;
|
||||
|
||||
if ((WM_operatortype_find(name))) {
|
||||
if ((ot= WM_operatortype_find(name))) {
|
||||
ret = PyCFunction_New( pyop_base_call_meth, pyname); /* set the name string as self, PyCFunction_New incref's self */
|
||||
}
|
||||
else if ((ret = PyObject_GenericGetAttr((PyObject *)self, pyname))) {
|
||||
@@ -235,6 +238,28 @@ static PyObject *pyop_base_dir(PyObject *self)
|
||||
return list;
|
||||
}
|
||||
|
||||
static PyObject *pyop_base_rna(PyObject *self, PyObject *pyname)
|
||||
{
|
||||
char *name = _PyUnicode_AsString(pyname);
|
||||
wmOperatorType *ot;
|
||||
|
||||
if ((ot= WM_operatortype_find(name))) {
|
||||
BPy_StructRNA *pyrna;
|
||||
PointerRNA ptr;
|
||||
|
||||
/* XXX POINTER - if this 'ot' is python generated, it could be free'd */
|
||||
RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
|
||||
|
||||
pyrna= (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr); /* were not really using &ptr, overwite next */
|
||||
//pyrna->freeptr= 1;
|
||||
return pyrna;
|
||||
}
|
||||
else {
|
||||
PyErr_SetString(PyExc_AttributeError, "Operator not found");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
PyTypeObject pyop_base_Type = {NULL};
|
||||
|
||||
PyObject *BPY_operator_module( bContext *C )
|
||||
|
||||
@@ -384,7 +384,8 @@ PyObject *PYOP_wrap_add(PyObject *self, PyObject *value)
|
||||
//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);
|
||||
|
||||
|
||||
|
||||
if (!PyObject_IsSubclass(value, optype)) {
|
||||
PyErr_SetString( PyExc_AttributeError, "expected Operator subclass of bpy.types.Operator");
|
||||
return NULL;
|
||||
@@ -450,7 +451,6 @@ PyObject *PYOP_wrap_add(PyObject *self, PyObject *value)
|
||||
} else {
|
||||
PyErr_Clear();
|
||||
}
|
||||
Py_XDECREF(item);
|
||||
}
|
||||
|
||||
/* If we have properties set, check its a list of dicts */
|
||||
|
||||
@@ -574,21 +574,27 @@ static PyMappingMethods pyrna_prop_as_mapping = {
|
||||
static PyObject *pyrna_struct_dir(BPy_StructRNA * self)
|
||||
{
|
||||
PyObject *ret, *dict;
|
||||
PyObject *pystring = PyUnicode_FromString("__dict__");
|
||||
PyObject *pystring;
|
||||
|
||||
/* Include this incase this instance is a subtype of a python class
|
||||
* In these instances we may want to return a function or variable provided by the subtype
|
||||
* */
|
||||
dict = PyObject_GenericGetAttr((PyObject *)self, pystring);
|
||||
Py_DECREF(pystring);
|
||||
|
||||
if (dict==NULL) {
|
||||
PyErr_Clear();
|
||||
|
||||
if (BPy_StructRNA_CheckExact(self)) {
|
||||
ret = PyList_New(0);
|
||||
}
|
||||
else {
|
||||
ret = PyDict_Keys(dict);
|
||||
Py_DECREF(dict);
|
||||
} else {
|
||||
pystring = PyUnicode_FromString("__dict__");
|
||||
dict = PyObject_GenericGetAttr((PyObject *)self, pystring);
|
||||
Py_DECREF(pystring);
|
||||
|
||||
if (dict==NULL) {
|
||||
PyErr_Clear();
|
||||
ret = PyList_New(0);
|
||||
}
|
||||
else {
|
||||
ret = PyDict_Keys(dict);
|
||||
Py_DECREF(dict);
|
||||
}
|
||||
}
|
||||
|
||||
/* Collect RNA items*/
|
||||
@@ -629,12 +635,12 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA * self, PyObject *pyname )
|
||||
|
||||
/* Include this incase this instance is a subtype of a python class
|
||||
* In these instances we may want to return a function or variable provided by the subtype
|
||||
*
|
||||
* Also needed to return methods when its not a subtype
|
||||
* */
|
||||
if (BPy_StructRNA_CheckExact(self) == 0) {
|
||||
ret = PyObject_GenericGetAttr((PyObject *)self, pyname);
|
||||
if (ret) return ret;
|
||||
else PyErr_Clear();
|
||||
}
|
||||
ret = PyObject_GenericGetAttr((PyObject *)self, pyname);
|
||||
if (ret) return ret;
|
||||
else PyErr_Clear();
|
||||
/* done with subtypes */
|
||||
|
||||
prop = RNA_struct_find_property(&self->ptr, name);
|
||||
@@ -1061,6 +1067,8 @@ PyObject* pyrna_struct_Subtype(PointerRNA *ptr)
|
||||
|
||||
if (ptr->type==NULL) {
|
||||
newclass= NULL; /* Nothing to do */
|
||||
} else if ((newclass= BPy_RNA_PYTYPE(ptr->data))) {
|
||||
Py_INCREF(newclass);
|
||||
} else if ((nameprop = RNA_struct_name_property(ptr))) {
|
||||
/* for now, return the base RNA type rather then a real module */
|
||||
|
||||
@@ -1076,7 +1084,6 @@ PyObject* pyrna_struct_Subtype(PointerRNA *ptr)
|
||||
PyObject *args = PyTuple_New(3);
|
||||
PyObject *bases = PyTuple_New(1);
|
||||
PyObject *dict = PyDict_New();
|
||||
PyObject *rna;
|
||||
|
||||
nameptr= RNA_property_string_get_alloc(ptr, nameprop, name, sizeof(name));
|
||||
|
||||
@@ -1087,6 +1094,7 @@ PyObject* pyrna_struct_Subtype(PointerRNA *ptr)
|
||||
// arg 2
|
||||
PyTuple_SET_ITEM(bases, 0, (PyObject *)&pyrna_struct_Type);
|
||||
Py_INCREF(&pyrna_struct_Type);
|
||||
|
||||
PyTuple_SET_ITEM(args, 1, bases);
|
||||
|
||||
// arg 3 - add an instance of the rna
|
||||
@@ -1100,9 +1108,11 @@ PyObject* pyrna_struct_Subtype(PointerRNA *ptr)
|
||||
newclass = PyObject_CallObject((PyObject *)&PyType_Type, args);
|
||||
// Set this later
|
||||
|
||||
|
||||
if (newclass) {
|
||||
PyObject *rna;
|
||||
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 */
|
||||
rna = pyrna_struct_CreatePyObject(ptr);
|
||||
@@ -1110,6 +1120,7 @@ PyObject* pyrna_struct_Subtype(PointerRNA *ptr)
|
||||
Py_DECREF(rna);
|
||||
/* done with rna instance */
|
||||
}
|
||||
|
||||
Py_DECREF(args);
|
||||
|
||||
if ((char *)&name != nameptr)
|
||||
@@ -1123,15 +1134,23 @@ PyObject* pyrna_struct_Subtype(PointerRNA *ptr)
|
||||
/*-----------------------CreatePyObject---------------------------------*/
|
||||
PyObject *pyrna_struct_CreatePyObject( PointerRNA *ptr )
|
||||
{
|
||||
BPy_StructRNA *pyrna;
|
||||
BPy_StructRNA *pyrna= NULL;
|
||||
int tp_init= 0;
|
||||
|
||||
if (ptr->data==NULL && ptr->type==NULL) { /* Operator RNA has NULL data */
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
if (ptr->type && BPy_RNA_PYTYPE(ptr->type)) {
|
||||
PyTypeObject *tp = BPy_RNA_PYTYPE(ptr->type);
|
||||
pyrna = (BPy_StructRNA *) tp->tp_alloc(tp, 0);
|
||||
if (ptr->type == &RNA_Struct) { /* always return a python subtype from rna struct types */
|
||||
PyTypeObject *tp = pyrna_struct_Subtype(ptr);
|
||||
|
||||
if (tp) {
|
||||
pyrna = (BPy_StructRNA *) tp->tp_alloc(tp, 0);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Could not make type\n");
|
||||
pyrna = ( BPy_StructRNA * ) PyObject_NEW( BPy_StructRNA, &pyrna_struct_Type );
|
||||
}
|
||||
}
|
||||
else {
|
||||
pyrna = ( BPy_StructRNA * ) PyObject_NEW( BPy_StructRNA, &pyrna_struct_Type );
|
||||
@@ -1144,7 +1163,6 @@ PyObject *pyrna_struct_CreatePyObject( PointerRNA *ptr )
|
||||
|
||||
pyrna->ptr= *ptr;
|
||||
pyrna->freeptr= 0;
|
||||
|
||||
return ( PyObject * ) pyrna;
|
||||
}
|
||||
|
||||
@@ -1201,50 +1219,74 @@ PyObject *BPY_rna_doc( void )
|
||||
}
|
||||
#endif
|
||||
|
||||
PyObject *BPY_rna_types(void)
|
||||
{
|
||||
/* Now initialize new subtypes based on pyrna_struct_Type */
|
||||
PointerRNA ptr;
|
||||
|
||||
CollectionPropertyIterator iter;
|
||||
PropertyRNA *prop;
|
||||
|
||||
PyObject *mod, *dict, *type, *name;
|
||||
|
||||
mod = PyModule_New("types");
|
||||
dict = PyModule_GetDict(mod);
|
||||
/* pyrna_basetype_* - BPy_BaseTypeRNA is just a BPy_PropertyRNA struct with a differnt type
|
||||
* the self->ptr and self->prop are always set to the "structs" collection */
|
||||
//---------------getattr--------------------------------------------
|
||||
static PyObject *pyrna_basetype_getattro( BPy_BaseTypeRNA * self, PyObject *pyname )
|
||||
{
|
||||
PointerRNA newptr;
|
||||
PyObject *ret;
|
||||
|
||||
/* for now, return the base RNA type rather then a real module */
|
||||
RNA_blender_rna_pointer_create(&ptr);
|
||||
prop = RNA_struct_find_property(&ptr, "structs");
|
||||
ret = PyObject_GenericGetAttr((PyObject *)self, pyname);
|
||||
if (ret) return ret;
|
||||
else PyErr_Clear();
|
||||
|
||||
RNA_property_collection_begin(&ptr, prop, &iter);
|
||||
for(; iter.valid; RNA_property_collection_next(&iter)) {
|
||||
if(iter.ptr.data) {
|
||||
type = (PyObject *)BPy_RNA_PYTYPE(iter.ptr.data);
|
||||
if (type==NULL) {
|
||||
type = pyrna_struct_Subtype(&iter.ptr);
|
||||
}
|
||||
if (type) {
|
||||
name = PyObject_GetAttrString(type, "__name__"); /* myClass.__name__ */
|
||||
if (name) {
|
||||
Py_DECREF(name);
|
||||
PyDict_SetItem(dict, name, type);
|
||||
}
|
||||
else {
|
||||
printf("could not get type __name__\n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("could not generate type\n");
|
||||
}
|
||||
}
|
||||
if (RNA_property_collection_lookup_string(&self->ptr, self->prop, _PyUnicode_AsString(pyname), &newptr)) {
|
||||
return pyrna_struct_Subtype(&newptr);
|
||||
}
|
||||
else { /* Override the error */
|
||||
PyErr_Format(PyExc_AttributeError, "bpy.types.%s not a valid RNA_Struct", _PyUnicode_AsString(pyname));
|
||||
return NULL;
|
||||
}
|
||||
RNA_property_collection_end(&iter);
|
||||
|
||||
return mod;
|
||||
}
|
||||
|
||||
static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self);
|
||||
static struct PyMethodDef pyrna_basetype_methods[] = {
|
||||
{"__dir__", (PyCFunction)pyrna_basetype_dir, METH_NOARGS, ""},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self)
|
||||
{
|
||||
PyObject *list, *name;
|
||||
PyMethodDef *meth;
|
||||
|
||||
list= pyrna_prop_keys(self); /* like calling structs.keys(), avoids looping here */
|
||||
|
||||
for(meth=pyrna_basetype_methods; meth->ml_name; meth++) {
|
||||
name = PyUnicode_FromString(meth->ml_name);
|
||||
PyList_Append(list, name);
|
||||
Py_DECREF(name);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
PyTypeObject pyrna_basetype_Type = {NULL};
|
||||
|
||||
PyObject *BPY_rna_types(void)
|
||||
{
|
||||
BPy_BaseTypeRNA *self;
|
||||
pyrna_basetype_Type.tp_name = "RNA_Types";
|
||||
pyrna_basetype_Type.tp_basicsize = sizeof( BPy_BaseTypeRNA );
|
||||
pyrna_basetype_Type.tp_getattro = ( getattrofunc )pyrna_basetype_getattro;
|
||||
pyrna_basetype_Type.tp_flags = Py_TPFLAGS_DEFAULT;
|
||||
pyrna_basetype_Type.tp_methods = pyrna_basetype_methods;
|
||||
|
||||
if( PyType_Ready( &pyrna_basetype_Type ) < 0 )
|
||||
return NULL;
|
||||
|
||||
self= (BPy_BaseTypeRNA *)PyObject_NEW( BPy_BaseTypeRNA, &pyrna_basetype_Type );
|
||||
|
||||
/* avoid doing this lookup for every getattr */
|
||||
RNA_blender_rna_pointer_create(&self->ptr);
|
||||
self->prop = RNA_struct_find_property(&self->ptr, "structs");
|
||||
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Orphan functions, not sure where they should go */
|
||||
|
||||
|
||||
@@ -61,6 +61,9 @@ typedef struct {
|
||||
PropertyRNA *prop;
|
||||
} BPy_PropertyRNA;
|
||||
|
||||
/* cheap trick */
|
||||
#define BPy_BaseTypeRNA BPy_PropertyRNA
|
||||
|
||||
PyObject *BPY_rna_module( void );
|
||||
/*PyObject *BPY_rna_doc( void );*/
|
||||
PyObject *BPY_rna_types( void );
|
||||
|
||||
@@ -236,6 +236,6 @@ PyObject *PyObject_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...)
|
||||
}
|
||||
va_end(vargs);
|
||||
|
||||
Py_INCREF(item); /* final value has is increfed, to match PyObject_GetAttrString */
|
||||
Py_XINCREF(item); /* final value has is increfed, to match PyObject_GetAttrString */
|
||||
return item;
|
||||
}
|
||||
|
||||
@@ -18,20 +18,41 @@
|
||||
#
|
||||
# #**** END GPL LICENSE BLOCK #****
|
||||
|
||||
if 1:
|
||||
# Print once every 1000
|
||||
GEN_PATH = True
|
||||
PRINT_DATA = False
|
||||
PRINT_DATA_INT = 1000
|
||||
VERBOSE = False
|
||||
VERBOSE_TYPE = False
|
||||
MAX_RECURSIVE = 8
|
||||
else:
|
||||
# Print everything
|
||||
GEN_PATH = True
|
||||
PRINT_DATA = True
|
||||
PRINT_DATA_INT = 0
|
||||
VERBOSE = False
|
||||
VERBOSE_TYPE = False
|
||||
MAX_RECURSIVE = 8
|
||||
|
||||
PRINT_DATA = True
|
||||
VERBOSE = False
|
||||
VERBOSE_TYPE = False
|
||||
SKIP_RECURSIVE = False
|
||||
seek_count = [0]
|
||||
|
||||
|
||||
def seek(r, txt):
|
||||
print(txt)
|
||||
def seek(r, txt, recurs):
|
||||
|
||||
seek_count[0] += 1
|
||||
|
||||
if PRINT_DATA_INT:
|
||||
if not (seek_count[0] % PRINT_DATA_INT):
|
||||
print(seek_count[0], txt)
|
||||
|
||||
if PRINT_DATA:
|
||||
print(txt)
|
||||
|
||||
newtxt = ''
|
||||
|
||||
if len(txt) > 200:
|
||||
print ("Somthing is wrong")
|
||||
print (txt)
|
||||
if recurs > MAX_RECURSIVE:
|
||||
#print ("Recursion is over max")
|
||||
#print (txt)
|
||||
return
|
||||
|
||||
type_r = type(r)
|
||||
@@ -64,27 +85,21 @@ def seek(r, txt):
|
||||
if item.startswith('__'):
|
||||
continue
|
||||
|
||||
if PRINT_DATA: newtxt = txt + '.' + item
|
||||
if GEN_PATH: newtxt = txt + '.' + item
|
||||
|
||||
if item == 'rna_type' and VERBOSE_TYPE==False: # just avoid because it spits out loads of data
|
||||
continue
|
||||
|
||||
if SKIP_RECURSIVE:
|
||||
if item in txt:
|
||||
if PRINT_DATA:
|
||||
print(newtxt + ' - (skipping to avoid recursive search)')
|
||||
continue
|
||||
|
||||
try: value = getattr(r, item)
|
||||
except: value = None
|
||||
|
||||
seek( value, newtxt)
|
||||
seek( value, newtxt, recurs + 1)
|
||||
|
||||
|
||||
if keys:
|
||||
for k in keys:
|
||||
if PRINT_DATA: newtxt = txt + '["' + k + '"]'
|
||||
seek(r.__getitem__(k), newtxt)
|
||||
if GEN_PATH: newtxt = txt + '["' + k + '"]'
|
||||
seek(r.__getitem__(k), newtxt, recurs+1)
|
||||
|
||||
else:
|
||||
try: length = len( r )
|
||||
@@ -96,17 +111,26 @@ def seek(r, txt):
|
||||
if PRINT_DATA:
|
||||
print((' '*len(txt)) + ' ... skipping '+str(length-2)+' items ...')
|
||||
|
||||
if PRINT_DATA: newtxt = txt + '[' + str(i) + ']'
|
||||
seek(r[i], newtxt)
|
||||
if GEN_PATH: newtxt = txt + '[' + str(i) + ']'
|
||||
seek(r[i], newtxt, recurs+1)
|
||||
else:
|
||||
for i in range(length):
|
||||
if PRINT_DATA: newtxt = txt + '[' + str(i) + ']'
|
||||
seek(r[i], newtxt)
|
||||
|
||||
#print (dir(bpy))
|
||||
seek(bpy.data, 'bpy.data')
|
||||
if GEN_PATH: newtxt = txt + '[' + str(i) + ']'
|
||||
seek(r[i], newtxt, recurs+1)
|
||||
|
||||
seek(bpy.data, 'bpy.data', 0)
|
||||
# seek(bpy.types, 'bpy.types', 0)
|
||||
'''
|
||||
for d in dir(bpy.types):
|
||||
t = getattr(bpy.types, d)
|
||||
try: r = t.__rna__
|
||||
except: r = None
|
||||
if r:
|
||||
seek(r, 'bpy.types.' + d + '.__rna__', 0)
|
||||
'''
|
||||
|
||||
#print dir(bpy)
|
||||
#import sys
|
||||
#sys.exit()
|
||||
|
||||
print("iter over ", seek_count, "rna items")
|
||||
|
||||
Reference in New Issue
Block a user