summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES1
-rw-r--r--doc/man/sphinx-apidoc.rst24
-rw-r--r--sphinx/ext/apidoc.py40
-rw-r--r--sphinx/util/template.py14
4 files changed, 59 insertions, 20 deletions
diff --git a/CHANGES b/CHANGES
index efa7223b1..b35e097a6 100644
--- a/CHANGES
+++ b/CHANGES
@@ -27,6 +27,7 @@ Features added
--------------
* #5124: graphviz: ``:graphviz_dot:`` option is renamed to ``:layout:``
+* #5602: apidoc: Add ``--templatedir`` option
Bugs fixed
----------
diff --git a/doc/man/sphinx-apidoc.rst b/doc/man/sphinx-apidoc.rst
index aef497e0d..78c0735cb 100644
--- a/doc/man/sphinx-apidoc.rst
+++ b/doc/man/sphinx-apidoc.rst
@@ -126,6 +126,30 @@ These options are used when :option:`--full` is specified:
Sets the project release to put in generated files (see :confval:`release`).
+.. rubric:: Project templating
+
+.. versionadded:: 2.2
+ Project templating options for sphinx-apidoc
+
+.. option:: -t, --templatedir=TEMPLATEDIR
+
+ Template directory for template files. You can modify the templates of
+ sphinx project files generated by apidoc. Following Jinja2 template
+ files are allowed:
+
+ * ``module.rst_t``
+ * ``package.rst_t``
+ * ``toc.rst_t``
+ * ``master_doc.rst_t``
+ * ``conf.py_t``
+ * ``Makefile_t``
+ * ``Makefile.new_t``
+ * ``make.bat_t``
+ * ``make.bat.new_t``
+
+ In detail, please refer the system template files Sphinx provides.
+ (``sphinx/templates/apidoc`` and ``sphinx/templates/quickstart``)
+
Environment
-----------
diff --git a/sphinx/ext/apidoc.py b/sphinx/ext/apidoc.py
index 18b5481f9..ed413de52 100644
--- a/sphinx/ext/apidoc.py
+++ b/sphinx/ext/apidoc.py
@@ -111,8 +111,8 @@ def format_directive(module, package=None):
return directive
-def create_module_file(package, basename, opts):
- # type: (str, str, Any) -> None
+def create_module_file(package, basename, opts, user_template_dir=None):
+ # type: (str, str, Any, str) -> None
"""Build the text of the file and write the file."""
qualname = module_join(package, basename)
context = {
@@ -121,12 +121,13 @@ def create_module_file(package, basename, opts):
'qualname': qualname,
'automodule_options': OPTIONS,
}
- text = ReSTRenderer(template_dir).render('module.rst_t', context)
+ text = ReSTRenderer([user_template_dir, template_dir]).render('module.rst_t', context)
write_file(qualname, text, opts)
-def create_package_file(root, master_package, subroot, py_files, opts, subs, is_namespace, excludes=[]): # NOQA
- # type: (str, str, str, List[str], Any, List[str], bool, List[str]) -> None
+def create_package_file(root, master_package, subroot, py_files, opts, subs,
+ is_namespace, excludes=[], user_template_dir=None):
+ # type: (str, str, str, List[str], Any, List[str], bool, List[str], str) -> None
"""Build the text of the file and write the file."""
# build a list of sub packages (directories containing an INITPY file)
subpackages = [sub for sub in subs if not
@@ -151,7 +152,7 @@ def create_package_file(root, master_package, subroot, py_files, opts, subs, is_
'automodule_options': OPTIONS,
'show_headings': not opts.noheadings,
}
- text = ReSTRenderer(template_dir).render('package.rst_t', context)
+ text = ReSTRenderer([user_template_dir, template_dir]).render('package.rst_t', context)
write_file(pkgname, text, opts)
if submodules and opts.separatemodules:
@@ -159,8 +160,8 @@ def create_package_file(root, master_package, subroot, py_files, opts, subs, is_
create_module_file(None, submodule, opts)
-def create_modules_toc_file(modules, opts, name='modules'):
- # type: (List[str], Any, str) -> None
+def create_modules_toc_file(modules, opts, name='modules', user_template_dir=None):
+ # type: (List[str], Any, str, str) -> None
"""Create the module's index."""
modules.sort()
prev_module = ''
@@ -176,7 +177,7 @@ def create_modules_toc_file(modules, opts, name='modules'):
'maxdepth': opts.maxdepth,
'docnames': modules,
}
- text = ReSTRenderer(template_dir).render('toc.rst_t', context)
+ text = ReSTRenderer([user_template_dir, template_dir]).render('toc.rst_t', context)
write_file(name, text, opts)
@@ -220,8 +221,8 @@ def is_skipped_module(filename, opts, excludes):
return False
-def recurse_tree(rootpath, excludes, opts):
- # type: (str, List[str], Any) -> List[str]
+def recurse_tree(rootpath, excludes, opts, user_template_dir=None):
+ # type: (str, List[str], Any, str) -> List[str]
"""
Look for every file in the directory tree and create the corresponding
ReST files.
@@ -271,7 +272,8 @@ def recurse_tree(rootpath, excludes, opts):
# a namespace and there is something there to document
if not is_namespace or len(py_files) > 0:
create_package_file(root, root_package, subpackage,
- py_files, opts, subs, is_namespace, excludes)
+ py_files, opts, subs, is_namespace, excludes,
+ user_template_dir)
toplevels.append(module_join(root_package, subpackage))
else:
# if we are at the root level, we don't require it to be a package
@@ -279,7 +281,7 @@ def recurse_tree(rootpath, excludes, opts):
for py_file in py_files:
if not is_skipped_module(path.join(rootpath, py_file), opts, excludes):
module = path.splitext(py_file)[0]
- create_module_file(root_package, module, opts)
+ create_module_file(root_package, module, opts, user_template_dir)
toplevels.append(module)
return toplevels
@@ -386,6 +388,11 @@ Note: By default this script will not overwrite already created files."""))
const='sphinx.ext.%s' % ext, dest='extensions',
help=__('enable %s extension') % ext)
+ group = parser.add_argument_group(__('Project templating'))
+ group.add_argument('-t', '--templatedir', metavar='TEMPLATEDIR',
+ dest='templatedir',
+ help=__('template directory for template files'))
+
return parser
@@ -412,7 +419,7 @@ def main(argv=sys.argv[1:]):
if not args.dryrun:
ensuredir(args.destdir)
excludes = [path.abspath(exclude) for exclude in args.exclude_pattern]
- modules = recurse_tree(rootpath, excludes, args)
+ modules = recurse_tree(rootpath, excludes, args, args.templatedir)
if args.full:
from sphinx.cmd import quickstart as qs
@@ -455,9 +462,10 @@ def main(argv=sys.argv[1:]):
d['extensions'].extend(ext.split(','))
if not args.dryrun:
- qs.generate(d, silent=True, overwrite=args.force)
+ qs.generate(d, silent=True, overwrite=args.force,
+ templatedir=args.templatedir)
elif args.tocfile:
- create_modules_toc_file(modules, args, args.tocfile)
+ create_modules_toc_file(modules, args, args.tocfile, args.templatedir)
return 0
diff --git a/sphinx/util/template.py b/sphinx/util/template.py
index 636767d41..fd8886944 100644
--- a/sphinx/util/template.py
+++ b/sphinx/util/template.py
@@ -9,7 +9,7 @@
"""
import os
-from typing import Dict
+from typing import Dict, List, Union
from jinja2.loaders import BaseLoader
from jinja2.sandbox import SandboxedEnvironment
@@ -34,7 +34,13 @@ class BaseRenderer:
class FileRenderer(BaseRenderer):
- def __init__(self, search_path: str) -> None:
+ def __init__(self, search_path: Union[str, List[str]]) -> None:
+ if isinstance(search_path, str):
+ search_path = [search_path]
+ else:
+ # filter "None" paths
+ search_path = list(filter(None, search_path))
+
loader = SphinxFileSystemLoader(search_path)
super().__init__(loader)
@@ -46,7 +52,7 @@ class FileRenderer(BaseRenderer):
class SphinxRenderer(FileRenderer):
- def __init__(self, template_path: str = None) -> None:
+ def __init__(self, template_path: Union[str, List[str]] = None) -> None:
if template_path is None:
template_path = os.path.join(package_dir, 'templates')
super().__init__(template_path)
@@ -76,7 +82,7 @@ class LaTeXRenderer(SphinxRenderer):
class ReSTRenderer(SphinxRenderer):
- def __init__(self, template_path: str = None, language: str = None) -> None:
+ def __init__(self, template_path: Union[str, List[str]] = None, language: str = None) -> None: # NOQA
super().__init__(template_path)
# add language to environment