from functools import cache
from sphinx.util.logging import getLogger
logger = getLogger(__name__)
def override_pst_pagetoc(app, pagename, templatename, context, doctree):
"""Overrides the `generate_toc_html` function of pydata-sphinx-theme for API."""
@cache
def generate_api_toc_html(kind="html"):
"""Generate the in-page toc for an API page.
This relies on the `generate_toc_html` function added by pydata-sphinx-theme
into the context. We save the original function into `pst_generate_toc_html`
and override `generate_toc_html` with this function for generated API pages.
The pagetoc of an API page would look like the following:
<-- Unwrap
- <-- Unwrap
{{obj}} <-- Decompose
-
...object
<-- Set visible if exists
- ...method 1
<-- Shorten
- ...method 2
<-- Shorten
...more methods <-- Shorten
- ...gallery examples
<-- Unwrapped
<-- Unwrapped
"""
soup = context["pst_generate_toc_html"](kind="soup")
try:
# Unwrap the outermost level
soup.ul.unwrap()
soup.li.unwrap()
soup.a.decompose()
# Get all toc-h2 level entries, where the first one should be the function
# or class, and the second one, if exists, should be the examples; there
# should be no more than two entries at this level for generated API pages
lis = soup.ul.select("li.toc-h2")
main_li = lis[0]
meth_list = main_li.ul
if meth_list is not None:
# This is a class API page, we remove the class name from the method
# names to make them better fit into the secondary sidebar; also we
# make the toc-h3 level entries always visible to more easily navigate
# through the methods
meth_list["class"].append("visible")
for meth in meth_list.find_all("li", {"class": "toc-h3"}):
target = meth.a.code.span
target.string = target.string.split(".", 1)[1]
# This corresponds to the behavior of `generate_toc_html`
return str(soup) if kind == "html" else soup
except Exception as e:
# Upon any failure we return the original pagetoc
logger.warning(
f"Failed to generate API pagetoc for {pagename}: {e}; falling back"
)
return context["pst_generate_toc_html"](kind=kind)
# Override the pydata-sphinx-theme implementation for generate API pages
if pagename.startswith("modules/generated/"):
context["pst_generate_toc_html"] = context["generate_toc_html"]
context["generate_toc_html"] = generate_api_toc_html
def setup(app):
# Need to be triggered after `pydata_sphinx_theme.toctree.add_toctree_functions`,
# and since default priority is 500 we set 900 for safety
app.connect("html-page-context", override_pst_pagetoc, priority=900)