Edit on GitHub

pdoc.render

  1from __future__ import annotations
  2
  3import os
  4from pathlib import Path
  5import types
  6from typing import Literal
  7from typing import Mapping
  8from typing import cast
  9import warnings
 10
 11import jinja2
 12from jinja2 import Environment
 13from jinja2 import FileSystemLoader
 14
 15import pdoc.doc
 16import pdoc.docstrings
 17from pdoc.render_helpers import DefaultMacroExtension
 18from pdoc.render_helpers import defuse_unsafe_reprs
 19from pdoc.render_helpers import edit_url
 20from pdoc.render_helpers import format_signature
 21from pdoc.render_helpers import highlight
 22from pdoc.render_helpers import link
 23from pdoc.render_helpers import linkify
 24from pdoc.render_helpers import minify_css
 25from pdoc.render_helpers import root_module_name
 26from pdoc.render_helpers import to_html
 27from pdoc.render_helpers import to_markdown_with_context
 28from pdoc.search import make_index
 29from pdoc.search import precompile_index
 30
 31
 32def configure(
 33    *,
 34    docformat: Literal[
 35        "markdown", "google", "numpy", "restructuredtext"  # noqa: F821
 36    ] = "restructuredtext",
 37    include_undocumented: bool = True,
 38    edit_url_map: Mapping[str, str] | None = None,
 39    favicon: str | None = None,
 40    footer_text: str = "",
 41    logo: str | None = None,
 42    logo_link: str | None = None,
 43    math: bool = False,
 44    mermaid: bool = False,
 45    search: bool = True,
 46    show_source: bool = True,
 47    template_directory: Path | None = None,
 48):
 49    """
 50    Configure the rendering output.
 51
 52    - `docformat` is the docstring flavor in use.
 53      pdoc prefers plain Markdown (the default), but also supports other formats.
 54    - `include_undocumented` controls whether members without a docstring are included in the output.
 55    - `edit_url_map` is a mapping from module names to URL prefixes. For example,
 56
 57        ```json
 58        {"pdoc": "https://github.com/mitmproxy/pdoc/blob/main/pdoc/"}
 59        ```
 60
 61      renders the "Edit on GitHub" button on this page. The URL prefix can be modified to pin a particular version.
 62    - `favicon` is an optional path/URL for a favicon image
 63    - `footer_text` is additional text that should appear in the navigation footer.
 64    - `logo` is an optional URL to the project's logo image
 65    - `logo_link` is an optional URL the logo should point to
 66    - `math` enables math rendering by including MathJax into the rendered documentation.
 67    - `mermaid` enables diagram rendering by including Mermaid.js into the rendered documentation.
 68    - `search` controls whether search functionality is enabled and a search index is built.
 69    - `show_source` controls whether a "View Source" button should be included in the output.
 70    - `template_directory` can be used to set an additional (preferred) directory
 71      for templates. You can find an example in the main documentation of `pdoc`
 72      or in `examples/custom-template`.
 73    """
 74    searchpath = _default_searchpath
 75    if template_directory:
 76        searchpath = [template_directory] + searchpath
 77    env.loader = FileSystemLoader(searchpath)
 78
 79    env.globals["docformat"] = docformat
 80    env.globals["include_undocumented"] = include_undocumented
 81    env.globals["edit_url_map"] = edit_url_map or {}
 82    env.globals["math"] = math
 83    env.globals["mermaid"] = mermaid
 84    env.globals["show_source"] = show_source
 85    env.globals["favicon"] = favicon
 86    env.globals["logo"] = logo
 87    env.globals["logo_link"] = logo_link
 88    env.globals["footer_text"] = footer_text
 89    env.globals["search"] = search
 90
 91
 92@defuse_unsafe_reprs()
 93def html_module(
 94    module: pdoc.doc.Module,
 95    all_modules: Mapping[str, pdoc.doc.Module],
 96    mtime: str | None = None,
 97) -> str:
 98    """
 99    Renders the documentation for a `pdoc.doc.Module`.
100
101    - `all_modules` contains all modules that are rendered in this invocation.
102      This is used to determine which identifiers should be linked and which should not.
103    - If `mtime` is given, include additional JavaScript on the page for live-reloading.
104      This is only passed by `pdoc.web`.
105    """
106    return env.get_template("module.html.jinja2").render(
107        module=module,
108        all_modules=all_modules,
109        root_module_name=root_module_name(all_modules),
110        edit_url=edit_url(
111            module.modulename,
112            module.is_package,
113            cast(Mapping[str, str], env.globals["edit_url_map"]),
114        ),
115        mtime=mtime,
116    )
117
118
119@defuse_unsafe_reprs()
120def html_index(all_modules: Mapping[str, pdoc.doc.Module]) -> str:
121    """Renders the module index."""
122    return env.get_template("index.html.jinja2").render(
123        all_modules=all_modules,
124        root_module_name=root_module_name(all_modules),
125    )
126
127
128@defuse_unsafe_reprs()
129def html_error(error: str, details: str = "") -> str:
130    """Renders an error message."""
131    return env.get_template("error.html.jinja2").render(
132        error=error,
133        details=details,
134    )
135
136
137@defuse_unsafe_reprs()
138def search_index(all_modules: Mapping[str, pdoc.doc.Module]) -> str:
139    """Renders the Elasticlunr.js search index."""
140    if not env.globals["search"]:
141        return ""
142    # This is a rather terrible hack to determine if a given object is public and should be included in the index.
143    module_template: jinja2.Template = env.get_template("module.html.jinja2")
144    ctx: jinja2.runtime.Context = module_template.new_context(
145        {"module": pdoc.doc.Module(types.ModuleType("")), "all_modules": all_modules}
146    )
147    for _ in module_template.root_render_func(ctx):  # type: ignore
148        pass
149
150    def is_public(x: pdoc.doc.Doc) -> bool:
151        return bool(ctx["is_public"](x).strip())
152
153    index = make_index(
154        all_modules,
155        is_public,
156        cast(str, env.globals["docformat"]),
157    )
158
159    compile_js = Path(env.get_template("build-search-index.js").filename)  # type: ignore
160    return env.get_template("search.js.jinja2").render(
161        search_index=precompile_index(index, compile_js)
162    )
163
164
165@defuse_unsafe_reprs()
166def repr_module(module: pdoc.doc.Module) -> str:
167    """Renders `repr(pdoc.doc.Module)`, primarily used for tests and debugging."""
168    return repr(module)
169
170
171_default_searchpath = [
172    Path(os.environ.get("XDG_CONFIG_HOME", "~/.config")).expanduser() / "pdoc",
173    Path(__file__).parent / "templates",
174    Path(__file__).parent / "templates" / "default",
175    Path(__file__).parent / "templates" / "deprecated",
176]
177
178env = Environment(
179    loader=FileSystemLoader(_default_searchpath),
180    extensions=["jinja2.ext.loopcontrols", DefaultMacroExtension],
181    autoescape=True,
182    trim_blocks=True,
183    lstrip_blocks=True,
184)
185"""
186The Jinja2 environment used to render all templates.
187You can modify this object to add custom filters and globals.
188"""
189env.filters["to_markdown"] = to_markdown_with_context
190env.filters["to_html"] = to_html
191env.filters["highlight"] = highlight
192env.filters["format_signature"] = format_signature
193env.filters["linkify"] = linkify
194env.filters["link"] = link
195env.filters["minify_css"] = minify_css
196env.globals["__version__"] = pdoc.__version__
197env.globals["env"] = os.environ
198env.globals["warn"] = warnings.warn
199configure()  # add default globals
def configure( *, docformat: Literal['markdown', 'google', 'numpy', 'restructuredtext'] = 'restructuredtext', include_undocumented: bool = True, edit_url_map: Optional[Mapping[str, str]] = None, favicon: str | None = None, footer_text: str = '', logo: str | None = None, logo_link: str | None = None, math: bool = False, mermaid: bool = False, search: bool = True, show_source: bool = True, template_directory: pathlib._local.Path | None = None):
33def configure(
34    *,
35    docformat: Literal[
36        "markdown", "google", "numpy", "restructuredtext"  # noqa: F821
37    ] = "restructuredtext",
38    include_undocumented: bool = True,
39    edit_url_map: Mapping[str, str] | None = None,
40    favicon: str | None = None,
41    footer_text: str = "",
42    logo: str | None = None,
43    logo_link: str | None = None,
44    math: bool = False,
45    mermaid: bool = False,
46    search: bool = True,
47    show_source: bool = True,
48    template_directory: Path | None = None,
49):
50    """
51    Configure the rendering output.
52
53    - `docformat` is the docstring flavor in use.
54      pdoc prefers plain Markdown (the default), but also supports other formats.
55    - `include_undocumented` controls whether members without a docstring are included in the output.
56    - `edit_url_map` is a mapping from module names to URL prefixes. For example,
57
58        ```json
59        {"pdoc": "https://github.com/mitmproxy/pdoc/blob/main/pdoc/"}
60        ```
61
62      renders the "Edit on GitHub" button on this page. The URL prefix can be modified to pin a particular version.
63    - `favicon` is an optional path/URL for a favicon image
64    - `footer_text` is additional text that should appear in the navigation footer.
65    - `logo` is an optional URL to the project's logo image
66    - `logo_link` is an optional URL the logo should point to
67    - `math` enables math rendering by including MathJax into the rendered documentation.
68    - `mermaid` enables diagram rendering by including Mermaid.js into the rendered documentation.
69    - `search` controls whether search functionality is enabled and a search index is built.
70    - `show_source` controls whether a "View Source" button should be included in the output.
71    - `template_directory` can be used to set an additional (preferred) directory
72      for templates. You can find an example in the main documentation of `pdoc`
73      or in `examples/custom-template`.
74    """
75    searchpath = _default_searchpath
76    if template_directory:
77        searchpath = [template_directory] + searchpath
78    env.loader = FileSystemLoader(searchpath)
79
80    env.globals["docformat"] = docformat
81    env.globals["include_undocumented"] = include_undocumented
82    env.globals["edit_url_map"] = edit_url_map or {}
83    env.globals["math"] = math
84    env.globals["mermaid"] = mermaid
85    env.globals["show_source"] = show_source
86    env.globals["favicon"] = favicon
87    env.globals["logo"] = logo
88    env.globals["logo_link"] = logo_link
89    env.globals["footer_text"] = footer_text
90    env.globals["search"] = search

Configure the rendering output.

  • docformat is the docstring flavor in use. pdoc prefers plain Markdown (the default), but also supports other formats.
  • include_undocumented controls whether members without a docstring are included in the output.
  • edit_url_map is a mapping from module names to URL prefixes. For example,

    {"pdoc": "https://github.com/mitmproxy/pdoc/blob/main/pdoc/"}
    

    renders the "Edit on GitHub" button on this page. The URL prefix can be modified to pin a particular version.

  • favicon is an optional path/URL for a favicon image
  • footer_text is additional text that should appear in the navigation footer.
  • logo is an optional URL to the project's logo image
  • logo_link is an optional URL the logo should point to
  • math enables math rendering by including MathJax into the rendered documentation.
  • mermaid enables diagram rendering by including Mermaid.js into the rendered documentation.
  • search controls whether search functionality is enabled and a search index is built.
  • show_source controls whether a "View Source" button should be included in the output.
  • template_directory can be used to set an additional (preferred) directory for templates. You can find an example in the main documentation of pdoc or in examples/custom-template.
@defuse_unsafe_reprs()
def html_module( module: pdoc.doc.Module, all_modules: Mapping[str, pdoc.doc.Module], mtime: str | None = None) -> str:
 93@defuse_unsafe_reprs()
 94def html_module(
 95    module: pdoc.doc.Module,
 96    all_modules: Mapping[str, pdoc.doc.Module],
 97    mtime: str | None = None,
 98) -> str:
 99    """
100    Renders the documentation for a `pdoc.doc.Module`.
101
102    - `all_modules` contains all modules that are rendered in this invocation.
103      This is used to determine which identifiers should be linked and which should not.
104    - If `mtime` is given, include additional JavaScript on the page for live-reloading.
105      This is only passed by `pdoc.web`.
106    """
107    return env.get_template("module.html.jinja2").render(
108        module=module,
109        all_modules=all_modules,
110        root_module_name=root_module_name(all_modules),
111        edit_url=edit_url(
112            module.modulename,
113            module.is_package,
114            cast(Mapping[str, str], env.globals["edit_url_map"]),
115        ),
116        mtime=mtime,
117    )

Renders the documentation for a pdoc.doc.Module.

  • all_modules contains all modules that are rendered in this invocation. This is used to determine which identifiers should be linked and which should not.
  • If mtime is given, include additional JavaScript on the page for live-reloading. This is only passed by pdoc.web.
@defuse_unsafe_reprs()
def html_index(all_modules: Mapping[str, pdoc.doc.Module]) -> str:
120@defuse_unsafe_reprs()
121def html_index(all_modules: Mapping[str, pdoc.doc.Module]) -> str:
122    """Renders the module index."""
123    return env.get_template("index.html.jinja2").render(
124        all_modules=all_modules,
125        root_module_name=root_module_name(all_modules),
126    )

Renders the module index.

@defuse_unsafe_reprs()
def html_error(error: str, details: str = '') -> str:
129@defuse_unsafe_reprs()
130def html_error(error: str, details: str = "") -> str:
131    """Renders an error message."""
132    return env.get_template("error.html.jinja2").render(
133        error=error,
134        details=details,
135    )

Renders an error message.

@defuse_unsafe_reprs()
def search_index(all_modules: Mapping[str, pdoc.doc.Module]) -> str:
138@defuse_unsafe_reprs()
139def search_index(all_modules: Mapping[str, pdoc.doc.Module]) -> str:
140    """Renders the Elasticlunr.js search index."""
141    if not env.globals["search"]:
142        return ""
143    # This is a rather terrible hack to determine if a given object is public and should be included in the index.
144    module_template: jinja2.Template = env.get_template("module.html.jinja2")
145    ctx: jinja2.runtime.Context = module_template.new_context(
146        {"module": pdoc.doc.Module(types.ModuleType("")), "all_modules": all_modules}
147    )
148    for _ in module_template.root_render_func(ctx):  # type: ignore
149        pass
150
151    def is_public(x: pdoc.doc.Doc) -> bool:
152        return bool(ctx["is_public"](x).strip())
153
154    index = make_index(
155        all_modules,
156        is_public,
157        cast(str, env.globals["docformat"]),
158    )
159
160    compile_js = Path(env.get_template("build-search-index.js").filename)  # type: ignore
161    return env.get_template("search.js.jinja2").render(
162        search_index=precompile_index(index, compile_js)
163    )

Renders the Elasticlunr.js search index.

@defuse_unsafe_reprs()
def repr_module(module: pdoc.doc.Module) -> str:
166@defuse_unsafe_reprs()
167def repr_module(module: pdoc.doc.Module) -> str:
168    """Renders `repr(pdoc.doc.Module)`, primarily used for tests and debugging."""
169    return repr(module)

Renders repr(pdoc.doc.Module), primarily used for tests and debugging.

env = <jinja2.environment.Environment object>

The Jinja2 environment used to render all templates. You can modify this object to add custom filters and globals.