- rna documentation layout now matches blenders internal layout, autogenerate packages for nested modules.

bpy.data, bpy.ops.object etc.
- added basic docs for bpy.props
- omit panel, menu and operator classes (took up too much space and not useful)
- exec cant be used as an operator suffix eg- CONSOLE_OT_exec --> CONSOLE_OT_execute (same for file)
- fixed some crashes when generating docs

Updated docs here
http://www.graphicall.org/ftp/ideasman42/html/
This commit is contained in:
Campbell Barton 2009-09-04 04:29:54 +00:00
parent a819ef1bf2
commit 6caff6b390
11 changed files with 203 additions and 52 deletions

@ -110,7 +110,7 @@ class CONSOLE_OT_exec(bpy.types.Operator):
'''
Operator documentatuon text, will be used for the operator tooltip and python docs.
'''
__idname__ = "console.exec"
__idname__ = "console.execute"
__label__ = "Console Execute"
__register__ = False

@ -434,10 +434,8 @@ static EnumPropertyItem *modifier_add_itemf(bContext *C, PointerRNA *ptr, int *f
Object *ob;
int totitem= 0, a;
if(!C) /* needed for docs */
if(!C || !(ob= CTX_data_active_object(C))) /* needed for docs */
return modifier_type_items;
ob= CTX_data_active_object(C);
for(a=0; modifier_type_items[a].identifier; a++) {
md_item= &modifier_type_items[a];

@ -3336,7 +3336,7 @@ void ED_keymap_screen(wmWindowManager *wm)
WM_keymap_verify_item(keymap, "SCRIPT_OT_python_run_ui_scripts", F8KEY, KM_PRESS, 0, 0);
/* files */
WM_keymap_add_item(keymap, "FILE_OT_exec", RETKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "FILE_OT_execute", RETKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "FILE_OT_cancel", ESCKEY, KM_PRESS, 0, 0);
/* undo */

@ -97,7 +97,7 @@ static int report_replay_exec(bContext *C, wmOperator *op)
for(report=reports->list.last; report; report=report->prev) {
if((report->type & report_mask) && (report->type & RPT_OPERATOR_ALL) && (report->flag & SELECT)) {
console_history_add_str(C, report->message, 0);
WM_operator_name_call(C, "CONSOLE_OT_exec", WM_OP_EXEC_DEFAULT, NULL);
WM_operator_name_call(C, "CONSOLE_OT_execute", WM_OP_EXEC_DEFAULT, NULL);
ED_area_tag_redraw(CTX_wm_area(C));
}

@ -278,8 +278,8 @@ void console_keymap(struct wmWindowManager *wm)
RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", BACKSPACEKEY, KM_PRESS, 0, 0)->ptr, "type", DEL_PREV_CHAR);
#ifndef DISABLE_PYTHON
WM_keymap_add_item(keymap, "CONSOLE_OT_exec", RETKEY, KM_PRESS, 0, 0); /* python operator - space_text.py */
WM_keymap_add_item(keymap, "CONSOLE_OT_exec", PADENTER, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "CONSOLE_OT_execute", RETKEY, KM_PRESS, 0, 0); /* python operator - space_text.py */
WM_keymap_add_item(keymap, "CONSOLE_OT_execute", PADENTER, KM_PRESS, 0, 0);
//WM_keymap_add_item(keymap, "CONSOLE_OT_autocomplete", TABKEY, KM_PRESS, 0, 0); /* python operator - space_text.py */
WM_keymap_add_item(keymap, "CONSOLE_OT_autocomplete", SPACEKEY, KM_PRESS, KM_CTRL, 0); /* python operator - space_text.py */

@ -59,7 +59,7 @@ void FILE_OT_add_bookmark(struct wmOperatorType *ot);
void FILE_OT_delete_bookmark(struct wmOperatorType *ot);
void FILE_OT_hidedot(struct wmOperatorType *ot);
void FILE_OT_loadimages(struct wmOperatorType *ot);
void FILE_OT_exec(struct wmOperatorType *ot);
void FILE_OT_execute(struct wmOperatorType *ot);
void FILE_OT_cancel(struct wmOperatorType *ot);
void FILE_OT_parent(struct wmOperatorType *ot);
void FILE_OT_directory_new(struct wmOperatorType *ot);

@ -566,11 +566,11 @@ int file_exec(bContext *C, wmOperator *unused)
return OPERATOR_FINISHED;
}
void FILE_OT_exec(struct wmOperatorType *ot)
void FILE_OT_execute(struct wmOperatorType *ot)
{
/* identifiers */
ot->name= "Execute File Window";
ot->idname= "FILE_OT_exec";
ot->idname= "FILE_OT_execute";
/* api callbacks */
ot->exec= file_exec;

@ -330,7 +330,7 @@ void file_operatortypes(void)
WM_operatortype_append(FILE_OT_select_bookmark);
WM_operatortype_append(FILE_OT_loadimages);
WM_operatortype_append(FILE_OT_highlight);
WM_operatortype_append(FILE_OT_exec);
WM_operatortype_append(FILE_OT_execute);
WM_operatortype_append(FILE_OT_cancel);
WM_operatortype_append(FILE_OT_parent);
WM_operatortype_append(FILE_OT_previous);

@ -122,9 +122,6 @@ static void rna_ParticleEdit_update(bContext *C, PointerRNA *ptr)
static EnumPropertyItem *rna_ParticleEdit_tool_itemf(bContext *C, PointerRNA *ptr, int *free)
{
Scene *scene= CTX_data_scene(C);
PTCacheEdit *edit;
if(C==NULL) {
EnumPropertyItem *item= NULL;
int totitem= 0;
@ -137,13 +134,15 @@ static EnumPropertyItem *rna_ParticleEdit_tool_itemf(bContext *C, PointerRNA *pt
return item;
}
else {
Scene *scene= CTX_data_scene(C);
PTCacheEdit *edit = PE_get_current(scene, CTX_data_active_object(C));
if(edit && edit->psys)
return particle_edit_hair_brush_items;
edit = PE_get_current(scene, CTX_data_active_object(C));
if(edit && edit->psys)
return particle_edit_hair_brush_items;
return particle_edit_cache_brush_items;
return particle_edit_cache_brush_items;
}
}
static int rna_ParticleEdit_editable_get(PointerRNA *ptr)

@ -37,6 +37,94 @@ Generate html docs by running...
# if you dont have graphvis installed ommit the --graph arg.
# GLOBALS['BASEDIR'] = './source/blender/python/doc'
import os
SUBMODULES = {}
INIT_SUBMODULES = {} # store initialized files
INIT_SUBMODULES_IMPORTS = {} # dont import the same module twice
def append_package(package_path, mod_name):
init_path = os.path.join(os.path.dirname(package_path), "__init__.py")
# avoid double ups
if mod_name:
imports = INIT_SUBMODULES_IMPORTS.setdefault(init_path, [])
if mod_name in imports:
return
imports.append(mod_name)
try:
os.makedirs(os.path.dirname(init_path)) # make the dirs if they are not there
except:
pass
# Open the new file for the first time, otherwise keep it open.
f = INIT_SUBMODULES.get(init_path)
if f == None:
f = INIT_SUBMODULES[init_path] = open(init_path, 'w')
if mod_name:
f.write("import %s\n" % mod_name)
return f
def append_package_recursive(package_path, BASEPATH):
'''
assume the last item of package_path will be a file (not a dir thats created)
'''
package_path = os.path.splitext(package_path)[0] # incase of .py
try:
os.makedirs(os.path.join(BASEPATH, os.path.dirname(package_path))) # make the dirs if they are not there
except:
pass
new_path = BASEPATH
for mod_name in package_path.split(os.sep):
init_path = os.path.join(new_path, "__init__.py")
new_path = os.path.join(new_path, mod_name)
append_package(init_path, mod_name)
def open_submodule(subpath, BASEPATH):
'''
This is a utility function that lets us quickly add submodules
'''
# create all the package paths leading up to this module
append_package_recursive(subpath, BASEPATH)
module_name = os.path.basename( os.path.splitext(subpath)[0] )
mod_path = os.path.join(BASEPATH, subpath)
# Open the new file for the first time, otherwise keep it open.
f = SUBMODULES.get(mod_path)
if f == None:
f = SUBMODULES[mod_path] = open(mod_path, 'w')
f = open(mod_path, 'w')
return f
def close_all():
for files in (INIT_SUBMODULES.values(), SUBMODULES.values()):
for f in files:
if f.name.endswith('.py'):
f_name = f.name
f.close()
f = open(f_name, 'a')
f.write("\ndel __package__\n") # annoying, no need do show this
f.close()
def range_str(val):
if val < -10000000: return '-inf'
if val > 10000000: return 'inf'
@ -59,6 +147,19 @@ def full_rna_struct_path(rna_struct):
else:
return rna_struct.identifier
def rna_id_ignore(rna_id):
if rna_id == "rna_type":
return True
if "_OT_" in rna_id:
return True
if "_MT_" in rna_id:
return True
if "_PT_" in rna_id:
return True
return False
def write_func(rna, ident, out, func_type):
# Keyword attributes
kw_args = [] # "foo = 1", "bar=0.5", "spam='ENUM'"
@ -68,7 +169,7 @@ def write_func(rna, ident, out, func_type):
# Operators and functions work differently
if func_type=='OPERATOR':
rna_func_name = rna_struct.identifier
rna_func_name = rna_struct.identifier.split("_OT_")[-1]
rna_func_desc = rna_struct.description.strip()
items = rna_struct.properties.items()
else:
@ -78,7 +179,7 @@ def write_func(rna, ident, out, func_type):
for rna_prop_identifier, rna_prop in items:
if rna_prop_identifier=='rna_type':
if rna_id_ignore(rna_prop_identifier):
continue
# clear vars
@ -196,7 +297,7 @@ def write_func(rna, ident, out, func_type):
def rna2epy(target_path):
def rna2epy(BASEPATH):
# Use for faster lookups
# use rna_struct.identifier as the key for each dict
@ -255,7 +356,7 @@ def rna2epy(target_path):
for rna_prop_identifier, rna_prop in rna_struct.properties.items():
if rna_prop_identifier=='RNA': continue
if rna_prop_identifier=='rna_type': continue
if rna_id_ignore(rna_prop_identifier): continue
if rna_prop_identifier in rna_base_prop_keys: continue # does this prop exist in our parent class, if so skip
rna_desc = rna_prop.description.strip()
@ -320,7 +421,10 @@ def rna2epy(target_path):
for child in rna_children_dict[identifier]:
write_struct(child, ident + '\t')
out = open(target_path, 'w')
# out = open(target_path, 'w')
out = open_submodule("types.py", BASEPATH) # bpy.types
def base_id(rna_struct):
try: return rna_struct.base.identifier
@ -343,21 +447,23 @@ def rna2epy(target_path):
#if not rna_type_name.startswith('__'):
identifier = rna_struct.identifier
structs.append( (base_id(rna_struct), identifier, rna_struct) )
# Simple lookup
rna_struct_dict[identifier] = rna_struct
# Store full rna path 'GameObjectSettings' -> 'Object.GameObjectSettings'
rna_full_path_dict[identifier] = full_rna_struct_path(rna_struct)
# Store a list of functions, remove inherited later
rna_functions_dict[identifier]= list(rna_struct.functions)
# fill in these later
rna_children_dict[identifier]= []
rna_references_dict[identifier]= []
if not rna_id_ignore(identifier):
structs.append( (base_id(rna_struct), identifier, rna_struct) )
# Simple lookup
rna_struct_dict[identifier] = rna_struct
# Store full rna path 'GameObjectSettings' -> 'Object.GameObjectSettings'
rna_full_path_dict[identifier] = full_rna_struct_path(rna_struct)
# Store a list of functions, remove inherited later
rna_functions_dict[identifier]= list(rna_struct.functions)
# fill in these later
rna_children_dict[identifier]= []
rna_references_dict[identifier]= []
else:
@ -417,7 +523,7 @@ def rna2epy(target_path):
for rna_prop_identifier, rna_prop in rna_struct.properties.items():
if rna_prop_identifier=='RNA': continue
if rna_prop_identifier=='rna_type': continue
if rna_id_ignore(rna_prop_identifier): continue
if rna_prop_identifier in rna_base_prop_keys: continue
try: rna_prop_ptr = rna_prop.fixed_type
@ -431,7 +537,7 @@ def rna2epy(target_path):
for rna_prop_identifier, rna_prop in rna_func.parameters.items():
if rna_prop_identifier=='RNA': continue
if rna_prop_identifier=='rna_type': continue
if rna_id_ignore(rna_prop_identifier): continue
if rna_prop_identifier in rna_base_func_keys: continue
@ -476,6 +582,7 @@ def rna2epy(target_path):
# # We could also just run....
# os.system('epydoc source/blender/python/doc/rna.py -o ./source/blender/python/doc/html -v')
target_path = os.path.join(BASEPATH, "dump.py") # XXX - used for other funcs
# Write graphviz
out= open(target_path.replace('.py', '.dot'), 'w')
@ -546,8 +653,8 @@ def rna2epy(target_path):
out.write('%s\n' % w)
def op2epy(target_path):
out = open(target_path, 'w')
def op2epy(BASEPATH):
# out = open(target_path, 'w')
op_mods = dir(bpy.ops)
op_mods.remove('add')
@ -556,26 +663,73 @@ def op2epy(target_path):
for op_mod_name in sorted(op_mods):
if op_mod_name.startswith('__'):
continue
# open the submodule
mod_path = os.path.join("ops", op_mod_name + ".py")
out = open_submodule(mod_path, BASEPATH)
op_mod = getattr(bpy.ops, op_mod_name)
operators = dir(op_mod)
for op in sorted(operators):
# rna = getattr(bpy.types, op).__rna__
rna = getattr(op_mod, op).get_rna()
write_func(rna, '', out, 'OPERATOR')
out.write('\n')
out.close()
def misc2epy(BASEPATH):
'''
Hard coded modules, try to avoid adding stuff here
'''
out.write('\n')
out.close()
f = append_package(os.path.join(BASEPATH, ""), ""); # add a slash on the end of the base path
f.write('''
"""
@type data: L{bpy.types.Main}
@var data: blender data is accessed from here
"""
''')
f = open_submodule("props.py", BASEPATH)
f.write('''
MAX_INT= 2**31
MAX_FLOAT= 1e+37
def BoolProperty(attr, name="", description="", default=False):
"""
return a new bool property
"""
def IntProperty(attr, name="", description="", min=-MAX_INT, max=MAX_INT, soft_min=-MAX_INT, soft_max=MAX_INT, default=0):
"""
return a new int property
"""
def FloatProperty(attr, name="", description="", min=-MAX_FLOAT, max=MAX_FLOAT, soft_min=-MAX_FLOAT, soft_max=MAX_FLOAT, default=0.0):
"""
return a new float property
"""
def StringProperty(attr, name="", description="", maxlen=0, default=""):
"""
return a new string property
"""
def EnumProperty(attr, items, name="", description="", default=""):
"""
return a new enum property
"""
''')
if __name__ == '__main__':
if 'bpy' not in dir():
print("\nError, this script must run from inside blender2.5")
print(script_help_msg)
else:
rna2epy('source/blender/python/doc/rna.py')
op2epy('source/blender/python/doc/bpyoperator.py')
misc2epy('source/blender/python/doc/bpy') # first to write in info in some of the modules.
rna2epy('source/blender/python/doc/bpy')
op2epy('source/blender/python/doc/bpy')
close_all()
import sys
sys.exit()

@ -228,7 +228,7 @@ static int PYTHON_OT_invoke(bContext *C, wmOperator *op, wmEvent *event)
return PYTHON_OT_generic(PYOP_INVOKE, C, op, event);
}
static int PYTHON_OT_exec(bContext *C, wmOperator *op)
static int PYTHON_OT_execute(bContext *C, wmOperator *op)
{
return PYTHON_OT_generic(PYOP_EXEC, C, op, NULL);
}
@ -268,7 +268,7 @@ void PYTHON_OT_wrapper(wmOperatorType *ot, void *userdata)
if (PyObject_HasAttrString(py_class, "invoke"))
ot->invoke= PYTHON_OT_invoke;
if (PyObject_HasAttrString(py_class, "execute"))
ot->exec= PYTHON_OT_exec;
ot->exec= PYTHON_OT_execute;
if (PyObject_HasAttrString(py_class, "poll"))
ot->poll= PYTHON_OT_poll;