Skip to content

Commit 114093c

Browse files
authored
Use _parse_str_to_doctree() in Builder.read_doc() (#13676)
1 parent ea53cd4 commit 114093c

File tree

3 files changed

+43
-27
lines changed

3 files changed

+43
-27
lines changed

sphinx/builders/__init__.py

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from typing import TYPE_CHECKING, final
1212

1313
from docutils import nodes
14-
from docutils.utils import DependencyList
1514

1615
from sphinx._cli.util.colour import bold
1716
from sphinx.deprecation import _deprecation_warning
@@ -23,16 +22,12 @@
2322
from sphinx.environment.adapters.asset import ImageAdapter
2423
from sphinx.errors import SphinxError
2524
from sphinx.locale import __
26-
from sphinx.util import (
27-
get_filetype,
28-
logging,
29-
rst,
30-
)
25+
from sphinx.util import get_filetype, logging
3126
from sphinx.util._importer import import_object
3227
from sphinx.util._pathlib import _StrPathProperty
3328
from sphinx.util.build_phase import BuildPhase
3429
from sphinx.util.display import progress_message, status_iterator
35-
from sphinx.util.docutils import sphinx_domains
30+
from sphinx.util.docutils import _parse_str_to_doctree
3631
from sphinx.util.i18n import CatalogRepository, docname_to_domain
3732
from sphinx.util.osutil import ensuredir, relative_uri, relpath
3833
from sphinx.util.parallel import (
@@ -644,26 +639,33 @@ def read_doc(self, docname: str, *, _cache: bool = True) -> None:
644639
if docutils_conf.is_file():
645640
env.note_dependency(docutils_conf)
646641

647-
filename = str(env.doc2path(docname))
648-
filetype = get_filetype(self._app.config.source_suffix, filename)
649-
publisher = self._registry._get_publisher(
650-
filetype, config=self.config, env=self.env
642+
filename = env.doc2path(docname)
643+
644+
# set up error_handler for the target document
645+
error_handler = _UnicodeDecodeErrorHandler(docname)
646+
codecs.register_error('sphinx', error_handler) # type: ignore[arg-type]
647+
648+
# read the source file
649+
content = filename.read_text(
650+
encoding=env.settings['input_encoding'], errors='sphinx'
651651
)
652-
self.env.current_document._parser = publisher.parser
653-
# record_dependencies is mutable even though it is in settings,
654-
# explicitly re-initialise for each document
655-
publisher.settings.record_dependencies = DependencyList()
656-
with (
657-
sphinx_domains(env),
658-
rst.default_role(docname, self.config.default_role),
659-
):
660-
# set up error_handler for the target document
661-
error_handler = _UnicodeDecodeErrorHandler(docname)
662-
codecs.register_error('sphinx', error_handler) # type: ignore[arg-type]
663652

664-
publisher.set_source(source_path=filename)
665-
publisher.publish()
666-
doctree = publisher.document
653+
# TODO: move the "source-read" event to here.
654+
655+
filetype = get_filetype(self.config.source_suffix, filename)
656+
parser = self._registry.create_source_parser(
657+
filetype, config=self.config, env=env
658+
)
659+
doctree = _parse_str_to_doctree(
660+
content,
661+
filename=filename,
662+
default_role=self.config.default_role,
663+
default_settings=env.settings,
664+
env=env,
665+
events=self.events,
666+
parser=parser,
667+
transforms=self._registry.get_transforms(),
668+
)
667669

668670
# store time of reading, for outdated files detection
669671
env.all_docs[docname] = time.time_ns() // 1_000

sphinx/util/docutils.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
from sphinx.builders import Builder
4848
from sphinx.config import Config
4949
from sphinx.environment import BuildEnvironment
50+
from sphinx.events import EventManager
5051
from sphinx.util.typing import RoleFunction
5152

5253
class _LanguageModule(Protocol):
@@ -840,14 +841,17 @@ def _parse_str_to_doctree(
840841
default_role: str = '',
841842
default_settings: Mapping[str, Any],
842843
env: BuildEnvironment,
844+
events: EventManager | None = None,
843845
parser: Parser,
844846
transforms: Sequence[type[Transform]] = (),
845847
) -> nodes.document:
846848
env.current_document._parser = parser
847849

848850
# Propagate exceptions by default when used programmatically:
849851
defaults = {'traceback': True, **default_settings}
850-
settings = _get_settings(standalone.Reader, parser, defaults=defaults)
852+
settings = _get_settings(
853+
standalone.Reader, parser, defaults=defaults, read_config_files=True
854+
)
851855
settings._source = str(filename)
852856

853857
# Create root document node
@@ -872,6 +876,16 @@ def _parse_str_to_doctree(
872876
else:
873877
default_role_cm = nullcontext() # type: ignore[assignment]
874878
with sphinx_domains(env), default_role_cm:
879+
# TODO: Move the stanza below to Builder.read_doc(), within
880+
# a sphinx_domains() context manager.
881+
# This will require changes to IntersphinxDispatcher and/or
882+
# CustomReSTDispatcher.
883+
if events is not None:
884+
# emit "source-read" event
885+
arg = [content]
886+
events.emit('source-read', env.current_document.docname, arg)
887+
content = arg[0]
888+
875889
# parse content to abstract syntax tree
876890
parser.parse(content, document)
877891
document.current_source = document.current_line = None

tests/test_directives/test_directive_object_description.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def _doctree_for_test(
3131
parser = registry.create_source_parser('restructuredtext', config=config, env=env)
3232
return _parse_str_to_doctree(
3333
content,
34-
filename=env.doc2path(docname),
34+
filename=filename,
3535
default_settings={'env': env},
3636
env=env,
3737
parser=parser,

0 commit comments

Comments
 (0)