From 6caff6b390b257f70abe3949463797898b8bd2fd Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 4 Sep 2009 04:29:54 +0000 Subject: [PATCH] - 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/ --- release/ui/space_console.py | 2 +- .../blender/editors/object/object_modifier.c | 4 +- source/blender/editors/screen/screen_ops.c | 2 +- .../editors/space_console/console_report.c | 2 +- .../editors/space_console/space_console.c | 4 +- .../blender/editors/space_file/file_intern.h | 2 +- source/blender/editors/space_file/file_ops.c | 4 +- .../blender/editors/space_file/space_file.c | 2 +- .../makesrna/intern/rna_sculpt_paint.c | 17 +- source/blender/python/epy_doc_gen.py | 212 +++++++++++++++--- .../blender/python/intern/bpy_operator_wrap.c | 4 +- 11 files changed, 203 insertions(+), 52 deletions(-) diff --git a/release/ui/space_console.py b/release/ui/space_console.py index f1038b5616a..dbf202f924c 100644 --- a/release/ui/space_console.py +++ b/release/ui/space_console.py @@ -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 diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index f9e2ac2f4de..96e485e5462 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -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]; diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 799bb0741f3..cb874ec1447 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -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 */ diff --git a/source/blender/editors/space_console/console_report.c b/source/blender/editors/space_console/console_report.c index 08d003f0706..b6920d148fd 100644 --- a/source/blender/editors/space_console/console_report.c +++ b/source/blender/editors/space_console/console_report.c @@ -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)); } diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c index a763e7ce153..48890d6cac2 100644 --- a/source/blender/editors/space_console/space_console.c +++ b/source/blender/editors/space_console/space_console.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 */ diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index 9f1e4ad0e25..a99594e9575 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -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); diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 9c73956d375..a06c1663d8e 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -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; diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 22ad03f3523..793f7cf8815 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -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); diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c index fabe0b647ea..b00119efaf6 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.c +++ b/source/blender/makesrna/intern/rna_sculpt_paint.c @@ -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) diff --git a/source/blender/python/epy_doc_gen.py b/source/blender/python/epy_doc_gen.py index 6a515648340..c2ef6bbc0d0 100644 --- a/source/blender/python/epy_doc_gen.py +++ b/source/blender/python/epy_doc_gen.py @@ -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() diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c index 9a74bf0aee8..0a487a8dbe8 100644 --- a/source/blender/python/intern/bpy_operator_wrap.c +++ b/source/blender/python/intern/bpy_operator_wrap.c @@ -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;