mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
refactor: transplant node handlers for writer on instantiation of translator
For now, node handlers are registered as class methods of translator classes. After this change, they are registered as instance method.
This commit is contained in:
parent
18efa1a63a
commit
446eab49b8
@ -23,7 +23,7 @@ from typing import TYPE_CHECKING
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers.rst import Directive, directives, roles
|
||||
from six import iteritems, itervalues
|
||||
from six import itervalues
|
||||
from six.moves import cStringIO
|
||||
|
||||
import sphinx
|
||||
@ -41,7 +41,7 @@ from sphinx.util import import_object
|
||||
from sphinx.util import logging
|
||||
from sphinx.util import pycompat # noqa: F401
|
||||
from sphinx.util.console import bold # type: ignore
|
||||
from sphinx.util.docutils import is_html5_writer_available, directive_helper
|
||||
from sphinx.util.docutils import directive_helper
|
||||
from sphinx.util.i18n import find_catalog_source_files
|
||||
from sphinx.util.osutil import abspath, ensuredir
|
||||
from sphinx.util.tags import Tags
|
||||
@ -618,39 +618,7 @@ class Sphinx(object):
|
||||
self._setting_up_extension, node.__name__,
|
||||
type='app', subtype='add_node')
|
||||
nodes._add_node_class_names([node.__name__])
|
||||
for key, val in iteritems(kwds):
|
||||
try:
|
||||
visit, depart = val
|
||||
except ValueError:
|
||||
raise ExtensionError(__('Value for key %r must be a '
|
||||
'(visit, depart) function tuple') % key)
|
||||
translator = self.registry.translators.get(key)
|
||||
translators = []
|
||||
if translator is not None:
|
||||
translators.append(translator)
|
||||
elif key == 'html':
|
||||
from sphinx.writers.html import HTMLTranslator
|
||||
translators.append(HTMLTranslator)
|
||||
if is_html5_writer_available():
|
||||
from sphinx.writers.html5 import HTML5Translator
|
||||
translators.append(HTML5Translator)
|
||||
elif key == 'latex':
|
||||
from sphinx.writers.latex import LaTeXTranslator
|
||||
translators.append(LaTeXTranslator)
|
||||
elif key == 'text':
|
||||
from sphinx.writers.text import TextTranslator
|
||||
translators.append(TextTranslator)
|
||||
elif key == 'man':
|
||||
from sphinx.writers.manpage import ManualPageTranslator
|
||||
translators.append(ManualPageTranslator)
|
||||
elif key == 'texinfo':
|
||||
from sphinx.writers.texinfo import TexinfoTranslator
|
||||
translators.append(TexinfoTranslator)
|
||||
|
||||
for translator in translators:
|
||||
setattr(translator, 'visit_' + node.__name__, visit)
|
||||
if depart:
|
||||
setattr(translator, 'depart_' + node.__name__, depart)
|
||||
self.registry.add_translation_handlers(node, **kwds)
|
||||
|
||||
def add_enumerable_node(self, node, figtype, title_getter=None, **kwds):
|
||||
# type: (nodes.Node, unicode, TitleGetter, Any) -> None
|
||||
|
@ -127,9 +127,7 @@ class Builder(object):
|
||||
This method returns an instance of ``default_translator_class`` by default.
|
||||
Users can replace the translator class with ``app.set_translator()`` API.
|
||||
"""
|
||||
translator_class = self.app.registry.get_translator_class(self)
|
||||
assert translator_class, "translator not found for %s" % self.__class__.__name__
|
||||
return translator_class(*args)
|
||||
return self.app.registry.create_translator(self, *args)
|
||||
|
||||
@property
|
||||
def translator_class(self):
|
||||
|
@ -12,6 +12,7 @@ from __future__ import print_function
|
||||
|
||||
import traceback
|
||||
import warnings
|
||||
from types import MethodType
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from pkg_resources import iter_entry_points
|
||||
@ -104,6 +105,10 @@ class SphinxComponentRegistry(object):
|
||||
#: custom translators; builder name -> translator class
|
||||
self.translators = {} # type: Dict[unicode, nodes.NodeVisitor]
|
||||
|
||||
#: custom handlers for translators
|
||||
#: a dict of builder name -> dict of node name -> visitor and departure functions
|
||||
self.translation_handlers = {} # type: Dict[unicode, Dict[unicode, Tuple[Callable, Callable]]] # NOQA
|
||||
|
||||
#: additional transforms; list of transforms
|
||||
self.transforms = [] # type: List[Type[Transform]]
|
||||
|
||||
@ -312,15 +317,41 @@ class SphinxComponentRegistry(object):
|
||||
logger.info(bold(__('Change of translator for the %s builder.') % name))
|
||||
self.translators[name] = translator
|
||||
|
||||
def add_translation_handlers(self, node, **kwargs):
|
||||
# type: (nodes.Node, Any) -> None
|
||||
logger.debug('[app] adding translation_handlers: %r, %r', node, kwargs)
|
||||
for builder_name, handlers in iteritems(kwargs):
|
||||
translation_handlers = self.translation_handlers.setdefault(builder_name, {})
|
||||
try:
|
||||
visit, depart = handlers # unpack once for assertion
|
||||
translation_handlers[node.__name__] = (visit, depart)
|
||||
except ValueError:
|
||||
raise ExtensionError(__('kwargs for add_node() must be a (visit, depart) '
|
||||
'function tuple: %r=%r') % builder_name, handlers)
|
||||
|
||||
def get_translator_class(self, builder):
|
||||
# type: (Builder) -> Type[nodes.NodeVisitor]
|
||||
return self.translators.get(builder.name,
|
||||
builder.default_translator_class)
|
||||
|
||||
def create_translator(self, builder, document):
|
||||
# type: (Builder, nodes.Node) -> nodes.NodeVisitor
|
||||
def create_translator(self, builder, *args):
|
||||
# type: (Builder, Any) -> nodes.NodeVisitor
|
||||
translator_class = self.get_translator_class(builder)
|
||||
return translator_class(builder, document)
|
||||
assert translator_class, "translator not found for %s" % builder.name
|
||||
translator = translator_class(*args)
|
||||
|
||||
# transplant handlers for custom nodes to translator instance
|
||||
handlers = self.translation_handlers.get(builder.name, None)
|
||||
if handlers is None:
|
||||
# retry with builder.format
|
||||
handlers = self.translation_handlers.get(builder.format, {})
|
||||
|
||||
for name, (visit, depart) in iteritems(handlers):
|
||||
setattr(translator, 'visit_' + name, MethodType(visit, translator))
|
||||
if depart:
|
||||
setattr(translator, 'depart_' + name, MethodType(depart, translator))
|
||||
|
||||
return translator
|
||||
|
||||
def add_transform(self, transform):
|
||||
# type: (Type[Transform]) -> None
|
||||
|
Loading…
Reference in New Issue
Block a user