Add per-event overloads to `EventManager.connect()` (#12787)

Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
This commit is contained in:
Adam Dangoor 2024-08-16 21:46:55 +01:00 committed by GitHub
parent c9d3414be7
commit d1c23a08a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 312 additions and 2 deletions

View File

@ -33,5 +33,6 @@ exclude =
doc/usage/extensions/example*.py,
per-file-ignores =
doc/conf.py:W605
sphinx/events.py:E704,
tests/test_extensions/ext_napoleon_pep526_data_google.py:MLL001,
tests/test_extensions/ext_napoleon_pep526_data_numpy.py:MLL001,

View File

@ -7,7 +7,7 @@ from __future__ import annotations
from collections import defaultdict
from operator import attrgetter
from typing import TYPE_CHECKING, Any, NamedTuple
from typing import TYPE_CHECKING, NamedTuple, overload
from sphinx.errors import ExtensionError, SphinxError
from sphinx.locale import __
@ -15,9 +15,19 @@ from sphinx.util import logging
from sphinx.util.inspect import safe_getattr
if TYPE_CHECKING:
from collections.abc import Callable
from collections.abc import Callable, Iterable, Sequence, Set
from pathlib import Path
from typing import Any, Literal
from docutils import nodes
from sphinx import addnodes
from sphinx.application import Sphinx
from sphinx.builders import Builder
from sphinx.config import Config
from sphinx.domains import Domain
from sphinx.environment import BuildEnvironment
from sphinx.ext.todo import todo_node
logger = logging.getLogger(__name__)
@ -66,6 +76,305 @@ class EventManager:
raise ExtensionError(__('Event %r already present') % name)
self.events[name] = ''
# ---- Core events -------------------------------------------------------
@overload
def connect(
self,
name: Literal['config-inited'],
callback: Callable[[Sphinx, Config], None],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['builder-inited'],
callback: Callable[[Sphinx], None],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['env-get-outdated'],
callback: Callable[
[Sphinx, BuildEnvironment, Set[str], Set[str], Set[str]], Sequence[str]
],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['env-before-read-docs'],
callback: Callable[[Sphinx, BuildEnvironment, list[str]], None],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['env-purge-doc'],
callback: Callable[[Sphinx, BuildEnvironment, str], None],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['source-read'],
callback: Callable[[Sphinx, str, list[str]], None],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['include-read'],
callback: Callable[[Sphinx, Path, str, list[str]], None],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['doctree-read'],
callback: Callable[[Sphinx, nodes.document], None],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['env-merge-info'],
callback: Callable[
[Sphinx, BuildEnvironment, list[str], BuildEnvironment], None
],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['env-updated'],
callback: Callable[[Sphinx, BuildEnvironment], str],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['env-get-updated'],
callback: Callable[[Sphinx, BuildEnvironment], Iterable[str]],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['env-check-consistency'],
callback: Callable[[Sphinx, BuildEnvironment], None],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['write-started'],
callback: Callable[[Sphinx, Builder], None],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['doctree-resolved'],
callback: Callable[[Sphinx, nodes.document, str], None],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['missing-reference'],
callback: Callable[
[Sphinx, BuildEnvironment, addnodes.pending_xref, nodes.TextElement],
nodes.reference | None,
],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['warn-missing-reference'],
callback: Callable[[Sphinx, Domain, addnodes.pending_xref], bool | None],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['build-finished'],
callback: Callable[[Sphinx, Exception | None], None],
priority: int,
) -> int: ...
# ---- Events from builtin builders --------------------------------------
@overload
def connect(
self,
name: Literal['html-collect-pages'],
callback: Callable[[Sphinx], Iterable[tuple[str, dict[str, Any], str]]],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['html-page-context'],
callback: Callable[
[Sphinx, str, str, dict[str, Any], nodes.document], str | None
],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['linkcheck-process-uri'],
callback: Callable[[Sphinx, str], str | None],
priority: int,
) -> int: ...
# ---- Events from builtin extensions-- ----------------------------------
@overload
def connect(
self,
name: Literal['object-description-transform'],
callback: Callable[[Sphinx, str, str, addnodes.desc_content], None],
priority: int,
) -> int: ...
# ---- Events from first-party extensions --------------------------------
@overload
def connect(
self,
name: Literal['autodoc-process-docstring'],
callback: Callable[
[
Sphinx,
Literal[
'module', 'class', 'exception', 'function', 'method', 'attribute'
],
str,
Any,
dict[str, bool],
Sequence[str],
],
None,
],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['autodoc-before-process-signature'],
callback: Callable[[Sphinx, Any, bool], None],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['autodoc-process-signature'],
callback: Callable[
[
Sphinx,
Literal[
'module', 'class', 'exception', 'function', 'method', 'attribute'
],
str,
Any,
dict[str, bool],
str | None,
str | None,
],
tuple[str | None, str | None] | None,
],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['autodoc-process-bases'],
callback: Callable[[Sphinx, str, Any, dict[str, bool], list[str]], None],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['autodoc-skip-member'],
callback: Callable[
[
Sphinx,
Literal[
'module', 'class', 'exception', 'function', 'method', 'attribute'
],
str,
Any,
bool,
dict[str, bool],
],
bool,
],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['todo-defined'],
callback: Callable[[Sphinx, todo_node], None],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['viewcode-find-source'],
callback: Callable[
[Sphinx, str],
tuple[str, dict[str, tuple[Literal['class', 'def', 'other'], int, int]]],
],
priority: int,
) -> int: ...
@overload
def connect(
self,
name: Literal['viewcode-follow-imported'],
callback: Callable[[Sphinx, str, str], str | None],
priority: int,
) -> int: ...
# ---- Catch-all ---------------------------------------------------------
@overload
def connect(
self,
name: str,
callback: Callable[..., Any],
priority: int,
) -> int: ...
def connect(self, name: str, callback: Callable, priority: int) -> int:
"""Connect a handler to specific event."""
if name not in self.events: