PyDoc: resolve duplicate module warnings

Remove submodule listings from the module docstring,
as this information already exists in the generator.
This commit is contained in:
Campbell Barton 2020-10-09 11:56:11 +11:00
parent c69df6728a
commit 05710171cb
5 changed files with 62 additions and 63 deletions

View File

@ -5,17 +5,6 @@
--partial bmesh* ; cd doc/python_api ; sphinx-build sphinx-in sphinx-out ; cd ../../
Submodules:
.. toctree::
:maxdepth: 1
bmesh.ops.rst
bmesh.types.rst
bmesh.utils.rst
bmesh.geometry.rst
Introduction
------------

View File

@ -495,6 +495,13 @@ else:
bpy_struct = None
def import_value_from_module(module_name, import_name):
ns = {}
exec_str = "from %s import %s as value" % (module_name, import_name)
exec(exec_str, ns, ns)
return ns["value"]
def escape_rst(text):
""" Escape plain text which may contain characters used by RST.
"""
@ -749,7 +756,7 @@ def pyprop2sphinx(ident, fw, identifier, py_prop):
fw(ident + " (readonly)\n\n")
def pymodule2sphinx(basepath, module_name, module, title):
def pymodule2sphinx(basepath, module_name, module, title, module_all_extra):
import types
attribute_set = set()
filepath = os.path.join(basepath, module_name + ".rst")
@ -796,22 +803,25 @@ def pymodule2sphinx(basepath, module_name, module, title):
fw(module.__doc__.strip())
fw("\n\n")
write_example_ref("", fw, module_name)
# write submodules
# we could also scan files but this ensures __all__ is used correctly
if module_all is not None:
if module_all or module_all_extra:
submod_name = None
submod = None
submod_ls = []
for submod_name in module_all:
ns = {}
exec_str = "from %s import %s as submod" % (module.__name__, submod_name)
exec(exec_str, ns, ns)
submod = ns["submod"]
for submod_name in (module_all or ()):
submod = import_value_from_module(module_name, submod_name)
if type(submod) == types.ModuleType:
submod_ls.append((submod_name, submod))
for submod_name in module_all_extra:
if submod_name in attribute_set:
continue
submod = import_value_from_module(module_name, submod_name)
# No type checks, since there are non-module types we treat as modules
# such as `bpy.app.translations` & `bpy.app.handlers`.
submod_ls.append((submod_name, submod))
del submod_name
del submod
@ -821,17 +831,22 @@ def pymodule2sphinx(basepath, module_name, module, title):
for submod_name, submod in submod_ls:
submod_name_full = "%s.%s" % (module_name, submod_name)
fw(" %s.rst\n\n" % submod_name_full)
fw(" %s.rst\n" % submod_name_full)
pymodule2sphinx(basepath, submod_name_full, submod, "%s submodule" % module_name)
pymodule2sphinx(basepath, submod_name_full, submod, "%s submodule" % module_name, ())
fw("\n")
del submod_ls
# done writing submodules!
write_example_ref("", fw, module_name)
# write members of the module
# only tested with PyStructs which are not exactly modules
for key, descr in sorted(type(module).__dict__.items()):
if key.startswith("__"):
continue
if key in module_all_extra:
continue
# naughty, we also add getset's into PyStructs, this is not typical py but also not incorrect.
# type_name is only used for examples and messages
@ -854,6 +869,8 @@ def pymodule2sphinx(basepath, module_name, module, title):
# 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:
if key in module_all_extra:
continue
# must be documented as a submodule
if is_struct_seq(value):
@ -895,6 +912,9 @@ def pymodule2sphinx(basepath, module_name, module, title):
module_dir_value_type.sort(key=lambda triple: str(triple[2]))
for attribute, value, value_type in module_dir_value_type:
if attribute in module_all_extra:
continue
if value_type == FunctionType:
pyfunc2sphinx("", fw, module_name, None, attribute, value, is_class=False)
# both the same at the moment but to be future proof
@ -1895,7 +1915,7 @@ def write_rst_msgbus(basepath):
file.close()
# Write the contents.
pymodule2sphinx(basepath, 'bpy.msgbus', bpy.msgbus, 'Message Bus')
pymodule2sphinx(basepath, 'bpy.msgbus', bpy.msgbus, 'Message Bus', ())
EXAMPLE_SET_USED.add("bpy.msgbus")
@ -1947,6 +1967,7 @@ def write_rst_importable_modules(basepath):
"gpu.select": "GPU Select",
"gpu.shader": "GPU Shader",
"bmesh": "BMesh Module",
"bmesh.ops": "BMesh Operators",
"bmesh.types": "BMesh Types",
"bmesh.utils": "BMesh Utilities",
"bmesh.geometry": "BMesh Geometry Utilities",
@ -1972,11 +1993,32 @@ def write_rst_importable_modules(basepath):
"freestyle.shaders": "Freestyle Shaders",
"freestyle.utils": "Freestyle Utilities",
}
# This is needed since some of the sub-modules listed above are not actual modules.
# Examples include `bpy.app.translations` & `bpy.app.handlers`.
#
# Most of these are `PyStructSequence` internally,
# however we don't want to document all of these as modules since some only contain
# a few values (version number for e.g).
#
# If we remove this logic and document all `PyStructSequence` as sub-modules it means
# `bpy.app.timers` for example would be presented on the same level as library information
# access such as `bpy.app.sdl` which doesn't seem useful since it hides more useful
# module-like objects among library data access.
importable_modules_parent_map = {}
for mod_name in importable_modules.keys():
if mod_name in EXCLUDE_MODULES:
continue
if "." in mod_name:
mod_name, submod_name = mod_name.rsplit(".", 1)
importable_modules_parent_map.setdefault(mod_name, []).append(submod_name)
for mod_name, mod_descr in importable_modules.items():
if mod_name not in EXCLUDE_MODULES:
module = __import__(mod_name,
fromlist=[mod_name.rsplit(".", 1)[-1]])
pymodule2sphinx(basepath, mod_name, module, mod_descr)
if mod_name in EXCLUDE_MODULES:
continue
module_all_extra = importable_modules_parent_map.get(mod_name, ())
module = __import__(mod_name, fromlist=[mod_name.rsplit(".", 1)[-1]])
pymodule2sphinx(basepath, mod_name, module, mod_descr, module_all_extra)
def copy_handwritten_rsts(basepath):

View File

@ -106,19 +106,8 @@ success:
* \{ */
PyDoc_STRVAR(GPU_doc,
"This module provides Python wrappers for the GPU implementation in Blender. "
"Some higher level functions can be found in the `gpu_extras` module. "
"\n\n"
"Submodules:\n"
"\n"
".. toctree::\n"
" :maxdepth: 1\n"
"\n"
" gpu.types.rst\n"
" gpu.shader.rst\n"
" gpu.matrix.rst\n"
" gpu.select.rst\n"
"\n");
"This module provides Python wrappers for the GPU implementation in Blender.\n"
"Some higher level functions can be found in the `gpu_extras` module.");
static struct PyModuleDef GPU_module_def = {
PyModuleDef_HEAD_INIT,
.m_name = "gpu",

View File

@ -126,17 +126,7 @@ static PyStructSequence_Field app_info_fields[] = {
};
PyDoc_STRVAR(bpy_app_doc,
"This module contains application values that remain unchanged during runtime.\n"
"\n"
"Submodules:\n"
"\n"
".. toctree::\n"
" :maxdepth: 1\n"
"\n"
" bpy.app.handlers.rst\n"
" bpy.app.icons.rst\n"
" bpy.app.timers.rst\n"
" bpy.app.translations.rst\n");
"This module contains application values that remain unchanged during runtime.");
static PyStructSequence_Desc app_info_desc = {
"bpy.app", /* name */

View File

@ -39,18 +39,7 @@ PyDoc_STRVAR(
".. note::\n"
"\n"
" Classes, methods and attributes that accept vectors also accept other numeric sequences,\n"
" such as tuples, lists."
"\n\n"
"Submodules:\n"
"\n"
".. toctree::\n"
" :maxdepth: 1\n"
"\n"
" mathutils.geometry.rst\n"
" mathutils.bvhtree.rst\n"
" mathutils.kdtree.rst\n"
" mathutils.interpolate.rst\n"
" mathutils.noise.rst\n"
" such as tuples, lists.\n"
"\n"
"The :mod:`mathutils` module provides the following classes:\n"
"\n"