Source code for sphinx.parsers

"""A Base class for additional parsers."""

from __future__ import annotations

from typing import TYPE_CHECKING

import docutils.parsers
import docutils.parsers.rst
from docutils.parsers.rst import states
from docutils.statemachine import StringList
from docutils.transforms.universal import SmartQuotes

from sphinx.deprecation import _deprecation_warning
from sphinx.util.rst import _append_epilogue, _prepend_prologue

if TYPE_CHECKING:
    from docutils import nodes
    from docutils.transforms import Transform

    from sphinx.application import Sphinx
    from sphinx.config import Config
    from sphinx.environment import BuildEnvironment
    from sphinx.util.typing import ExtensionMetadata


[docs] class Parser(docutils.parsers.Parser): """A base class for source parsers. Additional parsers should inherit from this class instead of ``docutils.parsers.Parser``. This class provides access to core Sphinx objects; *config* and *env*. """ _config: Config _env: BuildEnvironment @property def config(self) -> Config: """The config object.""" cls_module = self.__class__.__module__ cls_name = self.__class__.__qualname__ _deprecation_warning(cls_module, f'{cls_name}.config', remove=(9, 0)) return self._config @property def env(self) -> BuildEnvironment: """The environment object.""" cls_module = self.__class__.__module__ cls_name = self.__class__.__qualname__ _deprecation_warning(cls_module, f'{cls_name}.env', remove=(9, 0)) return self._env
[docs] def set_application(self, app: Sphinx) -> None: """set_application will be called from Sphinx to set app and other instance variables :param sphinx.application.Sphinx app: Sphinx application object """ cls_module = self.__class__.__module__ cls_name = self.__class__.__qualname__ _deprecation_warning(cls_module, f'{cls_name}.set_application', remove=(9, 0)) self._config = app.config self._env = app.env
class RSTParser(docutils.parsers.rst.Parser, Parser): """A reST parser for Sphinx.""" def get_transforms(self) -> list[type[Transform]]: """Sphinx's reST parser replaces a transform class for smart-quotes by its own refs: sphinx.io.SphinxStandaloneReader """ transforms = super(RSTParser, RSTParser()).get_transforms() transforms.remove(SmartQuotes) return transforms def parse(self, inputstring: str | StringList, document: nodes.document) -> None: """Parse text and generate a document tree.""" self.setup_parse(inputstring, document) # type: ignore[arg-type] self.statemachine = states.RSTStateMachine( state_classes=self.state_classes, initial_state=self.initial_state, debug=document.reporter.debug_flag, ) # preprocess inputstring if isinstance(inputstring, str): lines = docutils.statemachine.string2lines( inputstring, tab_width=document.settings.tab_width, convert_whitespace=True, ) inputlines = StringList(lines, document.current_source) else: inputlines = inputstring self.decorate(inputlines) self.statemachine.run(inputlines, document, inliner=self.inliner) self.finish_parse() def decorate(self, content: StringList) -> None: """Preprocess reStructuredText content before parsing.""" _prepend_prologue(content, self._config.rst_prolog) _append_epilogue(content, self._config.rst_epilog) def setup(app: Sphinx) -> ExtensionMetadata: app.add_source_parser(RSTParser) return { 'version': 'builtin', 'parallel_read_safe': True, 'parallel_write_safe': True, }