diff --git a/doc/usage/extensions/apidoc.rst b/doc/usage/extensions/apidoc.rst new file mode 100644 index 00000000000..e4328cc0288 --- /dev/null +++ b/doc/usage/extensions/apidoc.rst @@ -0,0 +1,126 @@ +.. _ext-apidoc: + +:mod:`sphinx.ext.apidoc` -- Generate API documentation from Python packages +=========================================================================== + +.. py:module:: sphinx.ext.apidoc + :synopsis: Generate API documentation from Python modules + +.. index:: pair: automatic; documentation +.. index:: pair: generation; documentation +.. index:: pair: generate; documentation + +.. versionadded:: 8.2 + +.. role:: code-py(code) + :language: Python + +:mod:`sphinx.ext.apidoc` is a tool for automatic generation +of Sphinx sources from Python packages. +It provides the :program:`sphinx-apidoc` command-line tool as an extension, +allowing it to be run during the Sphinx build process. + +The extension writes generated source files to a provided directory, +which are then read by Sphinx using the :mod:`sphinx.ext.autodoc` extension. + +.. warning:: + + :mod:`sphinx.ext.apidoc` generates source files that + use :mod:`sphinx.ext.autodoc` to document all found modules. + If any modules have side effects on import, + these will be executed by ``autodoc`` when :program:`sphinx-build` is run. + + If you document scripts (as opposed to library modules), + make sure their main routine is protected by + an ``if __name__ == '__main__'`` condition. + + +Configuration +------------- + +The apidoc extension uses the following configuration values: + +.. confval:: apidoc_modules + :no-index: + :type: :code-py:`Sequence[dict[str, Any]]` + :default: :code-py:`()` + + A list or sequence of dictionaries describing modules to document. + + For example: + + .. code-block:: python + + apidoc_modules = [ + {'destination': 'source/', 'path': 'path/to/module'}, + { + 'destination': 'source/', + 'path': 'path/to/another_module', + 'exclude_patterns': ['**/test*'], + 'maxdepth': 4, + 'followlinks': False, + 'separatemodules': False, + 'includeprivate': False, + 'noheadings': False, + 'modulefirst': False, + 'implicit_namespaces': False, + 'automodule_options': { + 'members', 'show-inheritance', 'undoc-members' + }, + }, + ] + + + Valid keys are: + + ``destination`` + The output directory for generated files (**required**). + This must be relative to the source directory, + and will be created if it does not exist. + + ``path`` + The path to the module to document (**required**). + This must be absolute or relative to the configuration directory. + + ``exclude_patterns`` + A sequence of patterns to exclude from generation. + These may be literal paths or :py:mod:`fnmatch`-style patterns. + Defaults to :code-py:`()`. + + ``maxdepth`` + The maximum depth of submodules to show in the generated table of contents. + Defaults to :code-py:`4`. + + ``followlinks`` + Follow symbolic links. + Defaults to :code-py:`False`. + + ``separatemodules`` + Put documentation for each module on an individual page. + Defaults to :code-py:`False`. + + ``includeprivate`` + Generate documentation for '_private' modules with leading underscores. + Defaults to :code-py:`False`. + + ``noheadings`` + Do not create headings for the modules/packages. + Useful when source docstrings already contain headings. + Defaults to :code-py:`False`. + + ``modulefirst`` + Place module documentation before submodule documentation. + Defaults to :code-py:`False`. + + ``implicit_namespaces`` + By default sphinx-apidoc processes sys.path searching for modules only. + Python 3.3 introduced :pep:`420` implicit namespaces that allow module path + structures such as ``foo/bar/module.py`` or ``foo/bar/baz/__init__.py`` + (notice that ``bar`` and ``foo`` are namespaces, not modules). + + Interpret module paths using :pep:`420` implicit namespaces. + Defaults to :code-py:`False`. + + ``automodule_options`` + Options to pass to generated :rst:dir:`automodule` directives. + Defaults to :code-py:`{'members', 'show-inheritance', 'undoc-members'}`. diff --git a/sphinx/ext/apidoc/__init__.py b/sphinx/ext/apidoc/__init__.py index d8ef2173530..18097ff9d4c 100644 --- a/sphinx/ext/apidoc/__init__.py +++ b/sphinx/ext/apidoc/__init__.py @@ -28,6 +28,7 @@ def setup(app: Sphinx) -> ExtensionMetadata: from sphinx.ext.apidoc._extension import run_apidoc + # Require autodoc app.setup_extension('sphinx.ext.autodoc') app.add_config_value('apidoc_modules', (), 'env', types=frozenset((list, tuple))) app.connect('builder-inited', run_apidoc) diff --git a/sphinx/ext/apidoc/_extension.py b/sphinx/ext/apidoc/_extension.py index 0cef1fcf87a..ba44749adc2 100644 --- a/sphinx/ext/apidoc/_extension.py +++ b/sphinx/ext/apidoc/_extension.py @@ -185,8 +185,8 @@ def _parse_module_options( ) return ApidocOptions( - module_path=module_path, destdir=dest_path, + module_path=module_path, exclude_pattern=exclude_patterns, automodule_options=automodule_options, maxdepth=maxdepth, @@ -204,9 +204,9 @@ def _check_list_of_strings( """ if key not in options: return [] - if not isinstance(options[key], list): + if not isinstance(options[key], list | tuple | set | frozenset): LOGGER.warning( - __("apidoc_modules item %i '%s' must be a list"), + __("apidoc_modules item %i '%s' must be a sequence"), index, key, type='apidoc', diff --git a/sphinx/ext/apidoc/_shared.py b/sphinx/ext/apidoc/_shared.py index 858e4da7dce..e707cce749c 100644 --- a/sphinx/ext/apidoc/_shared.py +++ b/sphinx/ext/apidoc/_shared.py @@ -37,8 +37,8 @@ class ApidocOptions: destdir: Path module_path: Path - exclude_pattern: list[str] + exclude_pattern: Sequence[str] = () maxdepth: int = 4 followlinks: bool = False separatemodules: bool = False