diff options
Diffstat (limited to 'doc/python_api/sphinx_doc_gen.py')
-rw-r--r-- | doc/python_api/sphinx_doc_gen.py | 152 |
1 files changed, 110 insertions, 42 deletions
diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index 5843e5ddb6c..b0127c50b29 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -50,7 +50,7 @@ For PDF generation # Check we're running in blender if __import__("sys").modules.get("bpy") is None: - print("\nError, this script must run from inside blender2.5") + print("\nError, this script must run from inside blender") print(script_help_msg) import sys @@ -70,13 +70,14 @@ else: # for testing so doc-builds dont take so long. EXCLUDE_MODULES = ( "bpy.context", - "bpy.app", + #"bpy.app", + #"bpy.app.handlers", "bpy.path", "bpy.data", "bpy.props", "bpy.utils", "bpy.context", - # "bpy.types", # supports filtering + "bpy.types", # supports filtering "bpy.ops", # supports filtering "bpy_extras", "bge", @@ -109,6 +110,18 @@ INFO_DOCS = ( ("info_gotcha.rst", "Gotcha's: some of the problems you may come up against when writing scripts"), ) + +# ----------------------------------------------------------------------------- +# configure compile time options + +try: + __import__("aud") +except ImportError: + print("Warning: Built without 'aud' module, docs incomplete...") + EXCLUDE_MODULES = EXCLUDE_MODULES + ("aud", ) + + + # import rpdb2; rpdb2.start_embedded_debugger('test') import os @@ -120,6 +133,7 @@ import rna_info ClassMethodDescriptorType = type(dict.__dict__['fromkeys']) MethodDescriptorType = type(dict.get) GetSetDescriptorType = type(int.real) +from types import MemberDescriptorType EXAMPLE_SET = set() EXAMPLE_SET_USED = set() @@ -134,6 +148,14 @@ else: _BPY_PROP_COLLECTION_ID = "collection" +def is_struct_seq(value): + return isinstance(value, tuple) and type(tuple) != tuple and hasattr(value, "n_fields") + + +def module_id_as_ref(name): + return "mod_" + name.replace(".", "__") + + def undocumented_message(module_name, type_name, identifier): if str(type_name).startswith('<module'): preloadtitle = '%s.%s' % (module_name, identifier) @@ -305,6 +327,10 @@ def py_descr2sphinx(ident, fw, descr, module_name, type_name, identifier): fw(ident + ".. attribute:: %s\n\n" % identifier) write_indented_lines(ident + " ", fw, doc, False) fw("\n") + elif type(descr) == MemberDescriptorType: # same as above but use 'data' + fw(ident + ".. data:: %s\n\n" % identifier) + write_indented_lines(ident + " ", fw, doc, False) + fw("\n") elif type(descr) in (MethodDescriptorType, ClassMethodDescriptorType): write_indented_lines(ident, fw, doc, False) fw("\n") @@ -367,6 +393,10 @@ def pymodule2sphinx(BASEPATH, module_name, module, title): write_title(fw, "%s (%s)" % (title, module_name), "=") + # write reference, annoying since we should be able to direct reference the + # modules but we cant always! + fw(".. _%s:\n\n" % module_id_as_ref(module_name)) + fw(".. module:: %s\n\n" % module_name) if module.__doc__: @@ -411,59 +441,91 @@ def pymodule2sphinx(BASEPATH, module_name, module, title): if key.startswith("__"): continue # naughty, we also add getset's into PyStructs, this is not typical py but also not incorrect. - if type(descr) == types.GetSetDescriptorType: # 'bpy_app_type' name is only used for examples and messages - py_descr2sphinx("", fw, descr, module_name, "bpy_app_type", key) + + # type_name is only used for examples and messages + type_name = str(type(module)).strip("<>").split(" ", 1)[-1][1:-1] # "<class 'bpy.app.handlers'>" --> bpy.app.handlers + if type(descr) == types.GetSetDescriptorType: + py_descr2sphinx("", fw, descr, module_name, type_name, key) attribute_set.add(key) + descr_sorted = [] for key, descr in sorted(type(module).__dict__.items()): if key.startswith("__"): continue - if type(descr) == types.MemberDescriptorType: + if type(descr) == MemberDescriptorType: if descr.__doc__: - fw(".. data:: %s\n\n" % key) - write_indented_lines(" ", fw, descr.__doc__, False) - fw("\n") - attribute_set.add(key) - - del key, descr + value = getattr(module, key, None) + value_type = type(value) + descr_sorted.append((key, descr, value, type(value))) + # sort by the valye type + descr_sorted.sort(key=lambda descr_data: str(descr_data[3])) + for key, descr, value, value_type in descr_sorted: + type_name = value_type.__name__ + py_descr2sphinx("", fw, descr, module_name, type_name, key) + + if is_struct_seq(value): + # ack, cant use typical reference because we double up once here + # and one fort he module! + full_name = "%s.%s" % (module_name, type_name) + fw(" :ref:`%s submodule details <%s>`\n\n\n" % (full_name, module_id_as_ref(full_name))) # % (module_name, type_name) + del full_name + + attribute_set.add(key) + + del key, descr, descr_sorted classes = [] submodules = [] + # use this list so we can sort by type + module_dir_value_type = [] + for attribute in module_dir: - if not attribute.startswith("_"): - if attribute in attribute_set: - continue + if attribute.startswith("_"): + continue - if attribute.startswith("n_"): # annoying exception, needed for bpy.app - continue + if attribute in attribute_set: + continue - value = getattr(module, attribute) - - value_type = type(value) - - if value_type == types.FunctionType: - pyfunc2sphinx("", fw, attribute, value, is_class=False) - elif value_type in (types.BuiltinMethodType, types.BuiltinFunctionType): # both the same at the moment but to be future proof - # note: can't get args from these, so dump the string as is - # this means any module used like this must have fully formatted docstrings. - py_c_func2sphinx("", fw, module_name, None, attribute, value, is_class=False) - elif value_type == type: - classes.append((attribute, value)) - elif issubclass(value_type, types.ModuleType): - submodules.append((attribute, value)) - elif value_type in (bool, int, float, str, tuple): - # constant, not much fun we can do here except to list it. - # TODO, figure out some way to document these! - fw(".. data:: %s\n\n" % attribute) - write_indented_lines(" ", fw, "constant value %s" % repr(value), False) - fw("\n") - else: - print("\tnot documenting %s.%s of %r type" % (module_name, attribute, value_type.__name__)) - continue + if attribute.startswith("n_"): # annoying exception, needed for bpy.app + continue + + # workaround for bpy.app documenting .index() and .count() + if isinstance(module, tuple) and hasattr(tuple, attribute): + continue + + value = getattr(module, attribute) + + module_dir_value_type.append((attribute, value, type(value))) + + # sort by str of each type + # this way lists, functions etc are grouped. + module_dir_value_type.sort(key=lambda triple: str(triple[2])) + + for attribute, value, value_type in module_dir_value_type: + if value_type == types.FunctionType: + pyfunc2sphinx("", fw, attribute, value, is_class=False) + elif value_type in (types.BuiltinMethodType, types.BuiltinFunctionType): # both the same at the moment but to be future proof + # note: can't get args from these, so dump the string as is + # this means any module used like this must have fully formatted docstrings. + py_c_func2sphinx("", fw, module_name, None, attribute, value, is_class=False) + elif value_type == type: + classes.append((attribute, value)) + elif issubclass(value_type, types.ModuleType): + submodules.append((attribute, value)) + elif value_type in (bool, int, float, str, tuple): + # constant, not much fun we can do here except to list it. + # TODO, figure out some way to document these! + #fw(".. data:: %s\n\n" % attribute) + write_indented_lines(" ", fw, "constant value %s" % repr(value), False) + fw("\n") + else: + print("\tnot documenting %s.%s of %r type" % (module_name, attribute, value_type.__name__)) + continue - attribute_set.add(attribute) - # TODO, more types... + attribute_set.add(attribute) + # TODO, more types... + del module_dir_value_type # TODO, bpy_extras does this already, mathutils not. """ @@ -1103,6 +1165,8 @@ def rna2sphinx(BASEPATH): fw(" bpy.path.rst\n\n") if "bpy.app" not in EXCLUDE_MODULES: fw(" bpy.app.rst\n\n") + if "bpy.app.handlers" not in EXCLUDE_MODULES: + fw(" bpy.app.handlers.rst\n\n") # C modules if "bpy.props" not in EXCLUDE_MODULES: @@ -1242,6 +1306,10 @@ def rna2sphinx(BASEPATH): from bpy import app as module pymodule2sphinx(BASEPATH, "bpy.app", module, "Application Data") + if "bpy.app.handlers" not in EXCLUDE_MODULES: + from bpy.app import handlers as module + pymodule2sphinx(BASEPATH, "bpy.app.handlers", module, "Application Handlers") + if "bpy.props" not in EXCLUDE_MODULES: from bpy import props as module pymodule2sphinx(BASEPATH, "bpy.props", module, "Property Definitions") |