mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Cache doctrees more efficiently
This commit is contained in:
parent
f4ab9adf77
commit
a9b0f2708b
@ -6,7 +6,7 @@ import functools
|
||||
import os
|
||||
import pickle
|
||||
from collections import defaultdict
|
||||
from copy import copy, deepcopy
|
||||
from copy import copy
|
||||
from datetime import datetime
|
||||
from os import path
|
||||
from typing import TYPE_CHECKING, Any, Callable, Generator, Iterator
|
||||
@ -178,6 +178,9 @@ class BuildEnvironment:
|
||||
# docnames to re-read unconditionally on next build
|
||||
self.reread_always: set[str] = set()
|
||||
|
||||
# docname -> pickled doctree
|
||||
self._pickled_doctree_cache: dict[str, bytes] = {}
|
||||
|
||||
# File metadata
|
||||
# docname -> dict of metadata items
|
||||
self.metadata: dict[str, dict[str, Any]] = defaultdict(dict)
|
||||
@ -577,20 +580,22 @@ class BuildEnvironment:
|
||||
|
||||
def get_doctree(self, docname: str) -> nodes.document:
|
||||
"""Read the doctree for a file from the pickle and return it."""
|
||||
doctreedir = self.doctreedir
|
||||
|
||||
@functools.lru_cache(maxsize=None)
|
||||
def _load_doctree_from_disk(docname: str) -> nodes.document:
|
||||
"""Read the doctree for a file from the pickle and return it."""
|
||||
filename = path.join(doctreedir, docname + '.doctree')
|
||||
try:
|
||||
serialised = self._pickled_doctree_cache[docname]
|
||||
except KeyError:
|
||||
filename = path.join(self.doctreedir, docname + '.doctree')
|
||||
with open(filename, 'rb') as f:
|
||||
return pickle.load(f)
|
||||
serialised = self._pickled_doctree_cache[docname] = f.read()
|
||||
|
||||
doctree = deepcopy(_load_doctree_from_disk(docname))
|
||||
doctree = pickle.loads(serialised)
|
||||
doctree.settings.env = self
|
||||
doctree.reporter = LoggingReporter(self.doc2path(docname))
|
||||
return doctree
|
||||
|
||||
@functools.cached_property
|
||||
def master_doctree(self) -> nodes.document:
|
||||
return self.get_doctree(self.config.root_doc)
|
||||
|
||||
def get_and_resolve_doctree(
|
||||
self,
|
||||
docname: str,
|
||||
|
@ -319,7 +319,7 @@ class TocTree:
|
||||
def get_toctree_for(self, docname: str, builder: Builder, collapse: bool,
|
||||
**kwargs: Any) -> Element | None:
|
||||
"""Return the global TOC nodetree."""
|
||||
doctree = self.env.get_doctree(self.env.config.root_doc)
|
||||
doctree = self.env.master_doctree
|
||||
toctrees: list[Element] = []
|
||||
if 'includehidden' not in kwargs:
|
||||
kwargs['includehidden'] = True
|
||||
|
@ -156,6 +156,10 @@ class SphinxTestApp(application.Sphinx):
|
||||
def __repr__(self) -> str:
|
||||
return f'<{self.__class__.__name__} buildername={self.builder.name!r}>'
|
||||
|
||||
def build(self, force_all: bool = False, filenames: list[str] | None = None) -> None:
|
||||
self.env._pickled_doctree_cache.clear()
|
||||
super().build(force_all, filenames)
|
||||
|
||||
|
||||
class SphinxTestAppWrapperForSkipBuilding:
|
||||
"""
|
||||
|
@ -135,6 +135,7 @@ def test_gettext_index_entries(app):
|
||||
'gettext_additional_targets': []})
|
||||
def test_gettext_disable_index_entries(app):
|
||||
# regression test for #976
|
||||
app.env._pickled_doctree_cache.clear() # clear cache
|
||||
app.builder.build(['index_entries'])
|
||||
|
||||
_msgid_getter = re.compile(r'msgid "(.*)"').search
|
||||
@ -165,7 +166,7 @@ def test_gettext_disable_index_entries(app):
|
||||
|
||||
@pytest.mark.sphinx('gettext', testroot='intl', srcdir='gettext')
|
||||
def test_gettext_template(app):
|
||||
app.builder.build_all()
|
||||
app.build()
|
||||
assert (app.outdir / 'sphinx.pot').isfile()
|
||||
|
||||
result = (app.outdir / 'sphinx.pot').read_text(encoding='utf8')
|
||||
|
@ -665,7 +665,7 @@ def test_numfig_without_numbered_toctree_warn(app, warning):
|
||||
index = (app.srcdir / 'index.rst').read_text(encoding='utf8')
|
||||
index = re.sub(':numbered:.*', '', index)
|
||||
(app.srcdir / 'index.rst').write_text(index, encoding='utf8')
|
||||
app.builder.build_all()
|
||||
app.build()
|
||||
|
||||
warnings = warning.getvalue()
|
||||
assert 'index.rst:47: WARNING: numfig is disabled. :numref: is ignored.' not in warnings
|
||||
|
@ -429,7 +429,7 @@ def test_numref_with_prefix2(app, status, warning):
|
||||
'latex', testroot='numfig',
|
||||
confoverrides={'numfig': True, 'language': 'ja'})
|
||||
def test_numref_with_language_ja(app, status, warning):
|
||||
app.builder.build_all()
|
||||
app.build()
|
||||
result = (app.outdir / 'python.tex').read_text(encoding='utf8')
|
||||
print(result)
|
||||
print(status.getvalue())
|
||||
|
@ -108,7 +108,7 @@ def test_mathjax_align(app, status, warning):
|
||||
confoverrides={'math_number_all': True,
|
||||
'extensions': ['sphinx.ext.mathjax']})
|
||||
def test_math_number_all_mathjax(app, status, warning):
|
||||
app.builder.build_all()
|
||||
app.build()
|
||||
|
||||
content = (app.outdir / 'index.html').read_text(encoding='utf8')
|
||||
html = (r'<div class="math notranslate nohighlight" id="equation-index-0">\s*'
|
||||
@ -119,7 +119,7 @@ def test_math_number_all_mathjax(app, status, warning):
|
||||
@pytest.mark.sphinx('latex', testroot='ext-math',
|
||||
confoverrides={'extensions': ['sphinx.ext.mathjax']})
|
||||
def test_math_number_all_latex(app, status, warning):
|
||||
app.builder.build_all()
|
||||
app.build()
|
||||
|
||||
content = (app.outdir / 'python.tex').read_text(encoding='utf8')
|
||||
macro = (r'\\begin{equation\*}\s*'
|
||||
|
Loading…
Reference in New Issue
Block a user