Страницы с пользовательскими топдеревами помечаются правильно, однако когда я обновляю фактический объект toctree в другом файле .rst, узле toctree (toc_tree), полученный в render_named_toctree, не является обновленной версией. (Полный исходный код расширения приведен ниже)
def render_named_toctree(
app: Sphinx, docname: str, tocname: str, collapse: bool = True, **kwargs: Any
) -> str:
builder = app.builder
maxdepth = kwargs.get('maxdepth',0)
includehidden = kwargs.get("includehidden", False)
titles_only = kwargs.get("titles_only", False)
toc_env = app.env.master_doctree.ids[tocname]
toc_tree = toc_env.children[0]
# for toctree_node in app.env.master_doctree.findall(addnodes.toctree):
# if tocname in toctree_node.parent.attributes["ids"]:
# toc_tree = toctree_node
resolved = _resolve_toctree(app.env, docname, builder, toc_tree, prune=True, collapse=collapse, maxdepth=int(maxdepth), includehidden=includehidden, titles_only=titles_only)
if not resolved:
resolved = None
return builder.render_partial(resolved)["fragment"]
Я создал небольшую папку с тестовой документацией, то есть текущая структура каталогов следующая (без файлов сборки).
├───src
│ └───sphinx_replace_htmlpage_toctree
│ __init__.py
│
└───test
│ conf.py
│ index.rst
└───tutorial
foo.rst
index.rst
Чтобы использовать собственное дерево toctree в учебнике/index.rst, я настраиваю два дерева toctree в index.rst. Содержимое Tutorial/index.rst и Tutorial/foo.rst — это просто заголовок, дающий им имя в дереве цепочек.
index.rst:
Docs
=====
Test document to see if the toctree changes
.. toctree::
:name: maintoc
self
tutorial/index
.. toctree::
:name: tutorialtree
tutorial/index
tutorial/foo
Чтобы создать учебник/index.rst, пользовательское дерево разделов conf.py имеет следующий код:
project = 'replace toctree tester'
copyright = '2024, Foo'
author = 'Bar'
release = '0.0.1'
html_theme = 'alabaster'
extensions = [
"sphinx_replace_htmlpage_toctree"
]
replace_global_tocs = {
"tutorial/*": "tutorialtree",
}
(Для тестирования может потребоваться добавить каталог расширений напрямую, я сам установил его в пакеты сайта).
Чтобы затем протестировать поведение, я запускаю следующую команду:
sphinx-autobuild test test/build/html -a
При изменении дерева обучающих программ в test/index.rst с помощью автоматической сборки (например, при удалении из него себя) дерево на веб-странице не меняется. когда документация перестраивается. Проверка возвращенного дерева данных, как описано выше, по-прежнему показывает три записи из исходной версии.
Это можно решить, запустив флаг -E, но это значительно увеличивает время сборки. , и я чувствую, что это можно сделать и без этого флага. Я подозреваю, что мне не хватает способа указать где-то, что один из документов изменился, из-за чего он использует устаревшее маринованное дерево документов вместо нового.
Я пытался принудительно установить для документов значение можно прочитать еще раз (как те, в которых объявлено обучающее дерево, так и учебное/индексное, но дерево тем все еще устарело.
Я пробовал это на нескольких этапах сфинкса API, отметив sphinx были обновлены как «index», так и «tutorial/index», т.е. я подключил функцию к следующим событиям:
- "env-get-updated"
"env-updated" - "env-before-read-docs"
- "env-get -удатированный"
Код в __init__.py< /code>:
from typing import *
import re
from docutils import nodes
from sphinx import addnodes
from sphinx.util import logging
from sphinx.application import Sphinx
from sphinx.util.typing import ExtensionMetadata
from sphinx.util.docutils import SphinxDirective
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.environment.adapters.toctree import _resolve_toctree
from sphinx.environment import BuildEnvironment
__version__ = "0.0.1"
_LOGGER = logging.getLogger(__name__)
EXTENSION_NAME = "replace-htmlpage-toctree"
TOCLIST_ATTR = "replace_docname_toctree"
def update_toctree_context(app: Sphinx, pagename, templatename, context, doctree):
"""Updates the toctree key in the context object if the pagename has a custom toc
"""
if pagename in app.env.replace_docname_toctree:
context["toctree"] = lambda **kwargs: render_named_toctree(app, pagename, app.env.replace_docname_toctree[pagename], **kwargs)
return
def render_named_toctree(
app: Sphinx, docname: str, tocname: str, collapse: bool = True, **kwargs: Any
) -> str:
builder = app.builder
maxdepth = kwargs.get('maxdepth',0)
includehidden = kwargs.get("includehidden", False)
titles_only = kwargs.get("titles_only", False)
toc_env = app.env.master_doctree.ids[tocname]
toc_tree = toc_env.children[0]
# for toctree_node in app.env.master_doctree.findall(addnodes.toctree):
# if tocname in toctree_node.parent.attributes["ids"]:
# toc_tree = toctree_node
resolved = _resolve_toctree(app.env, docname, builder, toc_tree, prune=True, collapse=collapse, maxdepth=int(maxdepth), includehidden=includehidden, titles_only=titles_only)
if not resolved:
resolved = None
return builder.render_partial(resolved)["fragment"]
def isold(app, env, added, changed, removed):
return {"tutorial/index", "index"}
def process_namedtocs(app: Sphinx, env: BuildEnvironment):
app.env.replace_docname_toctree = {}
for doc, treename in app.config.replace_global_tocs.items():
env_ids = app.env.master_doctree.ids
if treename not in env_ids:
_LOGGER.error(f"No toctree with name {treename} was found")
continue
named_toc = env_ids[treename]
if "toctree-wrapper" not in named_toc.attributes["classes"]:
_LOGGER.error(f"{treename} is not a toctree")
continue
if "*" in doc:
expr = re.compile(doc)
for found_doc in env.found_docs:
if expr.match(found_doc):
app.env.replace_docname_toctree[found_doc] = treename
elif doc in env.found_docs:
app.env.replace_docname_toctree[doc] = treename
else:
_LOGGER.error(f"{EXTENSION_NAME}: {doc} was not found and is not an expression.")
return ["tutorial/index", "index"]
def before_read(app: Sphinx, env: BuildEnvironment, docnames: list):
if "tutorial/index" not in docnames: docnames.append("tutorial/index")
if "index" not in docnames: docnames.append("index")
return
def return_updated(app, env):
return ["tutorial/index", "index"]
def setup(app: Sphinx) -> ExtensionMetadata:
app.add_config_value('replace_global_tocs', {}, 'env')
app.connect('html-page-context', update_toctree_context)
app.connect('env-get-updated', process_namedtocs)
app.connect("env-updated", return_updated)
app.connect("env-get-outdated", isold)
return ExtensionMetadata(version=__version__, parallel_read_safe=False, parallel_write_safe=False)
Подробнее здесь: https://stackoverflow.com/questions/793 ... s-outdated