usse/scrape/venv/lib/python3.10/site-packages/sphinx/ext/duration.py
2023-12-22 15:26:01 +01:00

93 lines
2.8 KiB
Python

"""Measure document reading durations."""
from __future__ import annotations
import time
from itertools import islice
from operator import itemgetter
from typing import TYPE_CHECKING, cast
import sphinx
from sphinx.domains import Domain
from sphinx.locale import __
from sphinx.util import logging
if TYPE_CHECKING:
from docutils import nodes
from sphinx.application import Sphinx
logger = logging.getLogger(__name__)
class DurationDomain(Domain):
"""A domain for durations of Sphinx processing."""
name = 'duration'
@property
def reading_durations(self) -> dict[str, float]:
return self.data.setdefault('reading_durations', {})
def note_reading_duration(self, duration: float) -> None:
self.reading_durations[self.env.docname] = duration
def clear(self) -> None:
self.reading_durations.clear()
def clear_doc(self, docname: str) -> None:
self.reading_durations.pop(docname, None)
def merge_domaindata(self, docnames: list[str], otherdata: dict[str, float]) -> None:
for docname, duration in otherdata.items():
if docname in docnames:
self.reading_durations[docname] = duration
def on_builder_inited(app: Sphinx) -> None:
"""Initialize DurationDomain on bootstrap.
This clears the results of the last build.
"""
domain = cast(DurationDomain, app.env.get_domain('duration'))
domain.clear()
def on_source_read(app: Sphinx, docname: str, content: list[str]) -> None:
"""Start to measure reading duration."""
app.env.temp_data['started_at'] = time.monotonic()
def on_doctree_read(app: Sphinx, doctree: nodes.document) -> None:
"""Record a reading duration."""
started_at = app.env.temp_data['started_at']
duration = time.monotonic() - started_at
domain = cast(DurationDomain, app.env.get_domain('duration'))
domain.note_reading_duration(duration)
def on_build_finished(app: Sphinx, error: Exception) -> None:
"""Display duration ranking on the current build."""
domain = cast(DurationDomain, app.env.get_domain('duration'))
if not domain.reading_durations:
return
durations = sorted(domain.reading_durations.items(), key=itemgetter(1), reverse=True)
logger.info('')
logger.info(__('====================== slowest reading durations ======================='))
for docname, d in islice(durations, 5):
logger.info(f'{d:.3f} {docname}') # NoQA: G004
def setup(app: Sphinx) -> dict[str, bool | str]:
app.add_domain(DurationDomain)
app.connect('builder-inited', on_builder_inited)
app.connect('source-read', on_source_read)
app.connect('doctree-read', on_doctree_read)
app.connect('build-finished', on_build_finished)
return {
'version': sphinx.__display_version__,
'parallel_read_safe': True,
'parallel_write_safe': True,
}