mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Rewrite the 'extension metadata' section
This commit is contained in:
@@ -159,40 +159,61 @@ Extension metadata
|
||||
|
||||
.. versionadded:: 1.3
|
||||
|
||||
The ``setup()`` function can return a dictionary. This is treated by Sphinx
|
||||
as metadata of the extension. Metadata keys currently recognized are:
|
||||
The ``setup()`` function should return a dictionary.
|
||||
This is treated by Sphinx as metadata of the extension.
|
||||
Metadata keys currently recognized are:
|
||||
|
||||
* ``'version'``: a string that identifies the extension version. It is used for
|
||||
extension version requirement checking (see :confval:`needs_extensions`) and
|
||||
informational purposes. If not given, ``"unknown version"`` is substituted.
|
||||
* ``'env_version'``: an integer that identifies the version of env data
|
||||
structure if the extension stores any data to environment. It is used to
|
||||
detect the data structure has been changed from last build. The extensions
|
||||
have to increment the version when data structure has changed. If not given,
|
||||
Sphinx considers the extension does not stores any data to environment.
|
||||
* ``'parallel_read_safe'``: a boolean that specifies if parallel reading of
|
||||
source files can be used when the extension is loaded. It defaults to
|
||||
``False``, i.e. you have to explicitly specify your extension to be
|
||||
parallel-read-safe after checking that it is.
|
||||
``'version'``
|
||||
a string that identifies the extension version.
|
||||
It is used for extension version requirement checking
|
||||
(see :confval:`needs_extensions`) and informational purposes.
|
||||
If not given, ``"unknown version"`` is substituted.
|
||||
|
||||
.. note:: The *parallel-read-safe* extension must satisfy the following
|
||||
conditions:
|
||||
``'env_version'``
|
||||
a non-zero positive integer integer that records
|
||||
the version of data stored in the environment by the extension.
|
||||
|
||||
* The core logic of the extension is parallelly executable during
|
||||
the reading phase.
|
||||
* It has event handlers for :event:`env-merge-info` and
|
||||
:event:`env-purge-doc` events if it stores data to the build
|
||||
environment object (env) during the reading phase.
|
||||
.. attention::
|
||||
If ``'env_version'`` is not set, the extension **must not**
|
||||
store any data or state directly on the environment object (``env``).
|
||||
|
||||
* ``'parallel_write_safe'``: a boolean that specifies if parallel writing of
|
||||
output files can be used when the extension is loaded. Since extensions
|
||||
usually don't negatively influence the process, this defaults to ``True``.
|
||||
This key must be defined if the extension uses the ``env`` object to store data.
|
||||
The version number must be incremented whenever the type, structure, or meaning
|
||||
of the stored data change, to ensure Sphinx does not try and load invalid data
|
||||
from a cached environment.
|
||||
|
||||
.. note:: The *parallel-write-safe* extension must satisfy the following
|
||||
conditions:
|
||||
.. versionadded:: 1.8
|
||||
|
||||
* The core logic of the extension is parallelly executable during
|
||||
the writing phase.
|
||||
``'parallel_read_safe'``
|
||||
a boolean that specifies if parallel reading of source files
|
||||
can be used when the extension is loaded.
|
||||
It defaults to ``False``, meaning that you have to explicitly specify
|
||||
your extension to be safe for parallel reading after checking that it is.
|
||||
|
||||
.. important::
|
||||
|
||||
When *parallel-read-safe* is ``True``,
|
||||
the extension must satisfy the following conditions:
|
||||
|
||||
* The core logic of the extension is parallelly executable during
|
||||
the reading phase.
|
||||
* It has event handlers for :event:`env-merge-info` and
|
||||
:event:`env-purge-doc` events if it stores data to the build
|
||||
environment object (``env``) during the reading phase.
|
||||
|
||||
``'parallel_write_safe'``
|
||||
a boolean that specifies if parallel writing of output files
|
||||
can be used when the extension is loaded.
|
||||
Since extensions usually don't negatively influence the process,
|
||||
this defaults to ``True``.
|
||||
|
||||
.. important::
|
||||
|
||||
When *parallel-write-safe* is ``True``,
|
||||
the extension must satisfy the following conditions:
|
||||
|
||||
* The core logic of the extension is parallelly executable during
|
||||
the writing phase.
|
||||
|
||||
|
||||
APIs used for writing extensions
|
||||
|
||||
@@ -31,7 +31,7 @@ from sphinx.util.nodes import is_translatable
|
||||
from sphinx.util.osutil import _last_modified_time, _relative_path, canon_path
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Callable, Iterable, Iterator
|
||||
from collections.abc import Callable, Iterable, Iterator, Mapping
|
||||
from typing import Any, Literal
|
||||
|
||||
from docutils import nodes
|
||||
@@ -45,6 +45,7 @@ if TYPE_CHECKING:
|
||||
from sphinx.domains.c._symbol import Symbol as CSymbol
|
||||
from sphinx.domains.cpp._symbol import Symbol as CPPSymbol
|
||||
from sphinx.events import EventManager
|
||||
from sphinx.extension import Extension
|
||||
from sphinx.project import Project
|
||||
from sphinx.util._pathlib import _StrPath
|
||||
|
||||
@@ -113,7 +114,7 @@ class BuildEnvironment:
|
||||
self.config_status_extra: str = ''
|
||||
self.events: EventManager = app.events
|
||||
self.project: Project = app.project
|
||||
self.version: dict[str, int] = app.registry.get_envversion(app)
|
||||
self.version: Mapping[str, int] = _get_env_version(app.extensions)
|
||||
|
||||
# the method of doctree versioning; see set_versioning_method
|
||||
self.versioning_condition: Literal[False] | Callable[[Node], bool] | None = None
|
||||
@@ -247,7 +248,7 @@ class BuildEnvironment:
|
||||
|
||||
def setup(self, app: Sphinx) -> None:
|
||||
"""Set up BuildEnvironment object."""
|
||||
if self.version and self.version != app.registry.get_envversion(app):
|
||||
if self.version and self.version != _get_env_version(app.extensions):
|
||||
raise BuildEnvironmentError(__('build environment version not current'))
|
||||
if self.srcdir and self.srcdir != app.srcdir:
|
||||
raise BuildEnvironmentError(__('source directory has changed'))
|
||||
@@ -260,7 +261,7 @@ class BuildEnvironment:
|
||||
self.events = app.events
|
||||
self.srcdir = app.srcdir
|
||||
self.project = app.project
|
||||
self.version = app.registry.get_envversion(app)
|
||||
self.version = _get_env_version(app.extensions)
|
||||
|
||||
# initialise domains
|
||||
if self.domains is None:
|
||||
@@ -808,6 +809,16 @@ class BuildEnvironment:
|
||||
self.events.emit('env-check-consistency', self)
|
||||
|
||||
|
||||
def _get_env_version(extensions: Mapping[str, Extension]) -> Mapping[str, int]:
|
||||
env_version = {
|
||||
ext.name: ext_env_version
|
||||
for ext in extensions.values()
|
||||
if (ext_env_version := ext.metadata.get('env_version'))
|
||||
}
|
||||
env_version['sphinx'] = ENV_VERSION
|
||||
return env_version
|
||||
|
||||
|
||||
def _differing_config_keys(old: Config, new: Config) -> frozenset[str]:
|
||||
"""Return a set of keys that differ between two config objects."""
|
||||
old_vals = {c.name: c.value for c in old}
|
||||
|
||||
@@ -22,7 +22,7 @@ from sphinx.util.logging import prefixed_warnings
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import os
|
||||
from collections.abc import Callable, Iterator, Sequence
|
||||
from collections.abc import Callable, Iterator, Mapping, Sequence
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.core import Publisher
|
||||
@@ -565,16 +565,10 @@ class SphinxComponentRegistry:
|
||||
|
||||
app.extensions[extname] = Extension(extname, mod, **metadata)
|
||||
|
||||
def get_envversion(self, app: Sphinx) -> dict[str, int]:
|
||||
from sphinx.environment import ENV_VERSION
|
||||
def get_envversion(self, app: Sphinx) -> Mapping[str, int]:
|
||||
from sphinx.environment import _get_env_version
|
||||
|
||||
envversion = {
|
||||
ext.name: ext.metadata['env_version']
|
||||
for ext in app.extensions.values()
|
||||
if ext.metadata.get('env_version')
|
||||
}
|
||||
envversion['sphinx'] = ENV_VERSION
|
||||
return envversion
|
||||
return _get_env_version(app.extensions)
|
||||
|
||||
def get_publisher(self, app: Sphinx, filetype: str) -> Publisher:
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user