Merge pull request #4742 from tk0miya/refactor_enumerable_nodes

Refactor enumerable nodes
This commit is contained in:
Takeshi KOMIYA
2018-03-21 23:41:38 +09:00
committed by GitHub
8 changed files with 48 additions and 13 deletions

View File

@@ -49,6 +49,8 @@ Features added
* Add ``app.add_message_catalog()`` and ``sphinx.locale.get_translations()`` to
support translation for 3rd party extensions
* helper function ``warning()`` for HTML themes is added
* Add ``Domain.enumerable_nodes`` to manage own enumerable nodes for domains
(experimental)
Bugs fixed
----------

View File

@@ -150,6 +150,8 @@ class Domain(object):
indices = [] # type: List[Type[Index]]
#: role name -> a warning message if reference is missing
dangling_warnings = {} # type: Dict[unicode, unicode]
#: node_class -> (enum_node_type, title_getter)
enumerable_nodes = {} # type: Dict[nodes.Node, Tuple[unicode, Callable]]
#: data value for a fresh environment
initial_data = {} # type: Dict
@@ -333,6 +335,12 @@ class Domain(object):
return type.lname
return _('%s %s') % (self.label, type.lname)
def get_enumerable_node_type(self, node):
# type: (nodes.Node) -> unicode
"""Get type of enumerable nodes (experimental)."""
enum_node_type, _ = self.enumerable_nodes.get(node.__class__, (None, None))
return enum_node_type
def get_full_qualified_name(self, node):
# type: (nodes.Node) -> unicode
"""Return full qualified name for given node."""

View File

@@ -11,6 +11,7 @@
import re
import unicodedata
import warnings
from copy import copy
from docutils import nodes
@@ -19,6 +20,7 @@ from docutils.statemachine import ViewList
from six import iteritems
from sphinx import addnodes
from sphinx.deprecation import RemovedInSphinx30Warning
from sphinx.directives import ObjectDescription
from sphinx.domains import Domain, ObjType
from sphinx.locale import _, __
@@ -726,7 +728,7 @@ class StandardDomain(Domain):
return None
target_node = env.get_doctree(docname).ids.get(labelid)
figtype = self.get_figtype(target_node)
figtype = self.get_enumerable_node_type(target_node)
if figtype is None:
return None
@@ -926,9 +928,9 @@ class StandardDomain(Domain):
return None
def get_figtype(self, node):
def get_enumerable_node_type(self, node):
# type: (nodes.Node) -> unicode
"""Get figure type of nodes."""
"""Get type of enumerable nodes."""
def has_child(node, cls):
# type: (nodes.Node, Type) -> bool
return any(isinstance(child, cls) for child in node)
@@ -944,6 +946,17 @@ class StandardDomain(Domain):
figtype, _ = self.enumerable_nodes.get(node.__class__, (None, None))
return figtype
def get_figtype(self, node):
# type: (nodes.Node) -> unicode
"""Get figure type of nodes.
.. deprecated:: 1.8
"""
warnings.warn('StandardDomain.get_figtype() is deprecated. '
'Please use get_enumerable_node_type() instead.',
RemovedInSphinx30Warning)
return self.get_enumerable_node_type(node)
def get_fignumber(self, env, builder, figtype, docname, target_node):
# type: (BuildEnvironment, Builder, unicode, unicode, nodes.Node) -> Tuple[int, ...]
if figtype == 'section':

View File

@@ -223,6 +223,15 @@ class TocTreeCollector(EnvironmentCollector):
env.toc_fignumbers = {}
fignum_counter = {} # type: Dict[unicode, Dict[Tuple[int, ...], int]]
def get_figtype(node):
# type: (nodes.Node) -> unicode
for domain in env.domains.values():
figtype = domain.get_enumerable_node_type(node)
if figtype:
return figtype
return None
def get_section_number(docname, section):
# type: (unicode, nodes.Node) -> Tuple[int, ...]
anchorname = '#' + section['ids'][0]
@@ -270,7 +279,7 @@ class TocTreeCollector(EnvironmentCollector):
continue
figtype = env.get_domain('std').get_figtype(subnode)
figtype = get_figtype(subnode)
if figtype and subnode['ids']:
register_fignumber(docname, secnum, figtype, subnode)

View File

@@ -62,6 +62,9 @@ class MathDomain(Domain):
dangling_warnings = {
'eq': 'equation not found: %(target)s',
}
enumerable_nodes = { # node_class -> (figtype, title_getter)
displaymath: ('displaymath', None),
} # type: Dict[nodes.Node, Tuple[unicode, Callable]]
def clear_doc(self, docname):
# type: (unicode) -> None
@@ -378,12 +381,12 @@ def setup_math(app, htmlinlinevisitors, htmldisplayvisitors):
man=(man_visit_math, None),
texinfo=(texinfo_visit_math, None),
html=htmlinlinevisitors)
app.add_enumerable_node(displaymath, 'displaymath',
latex=(latex_visit_displaymath, None),
text=(text_visit_displaymath, None),
man=(man_visit_displaymath, man_depart_displaymath),
texinfo=(texinfo_visit_displaymath, texinfo_depart_displaymath),
html=htmldisplayvisitors)
app.add_node(displaymath,
latex=(latex_visit_displaymath, None),
text=(text_visit_displaymath, None),
man=(man_visit_displaymath, man_depart_displaymath),
texinfo=(texinfo_visit_displaymath, texinfo_depart_displaymath),
html=htmldisplayvisitors)
app.add_node(eqref, latex=(latex_visit_eqref, None))
app.add_role('math', math_role)
app.add_role('eq', EqXRefRole(warn_dangling=True))

View File

@@ -342,7 +342,7 @@ class HTMLTranslator(BaseTranslator):
self.body.append(prefix % '.'.join(map(str, numbers)) + ' ')
self.body.append('</span>')
figtype = self.builder.env.domains['std'].get_figtype(node) # type: ignore
figtype = self.builder.env.domains['std'].get_enumerable_node_type(node)
if figtype:
if len(node['ids']) == 0:
msg = __('Any IDs not assigned for %s node') % node.tagname

View File

@@ -310,7 +310,7 @@ class HTML5Translator(BaseTranslator):
self.body.append(prefix % '.'.join(map(str, numbers)) + ' ')
self.body.append('</span>')
figtype = self.builder.env.domains['std'].get_figtype(node) # type: ignore
figtype = self.builder.env.domains['std'].get_enumerable_node_type(node)
if figtype:
if len(node['ids']) == 0:
msg = __('Any IDs not assigned for %s node') % node.tagname

View File

@@ -1995,7 +1995,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
return
else:
domain = self.builder.env.get_domain('std')
figtype = domain.get_figtype(next)
figtype = domain.get_enumerable_node_type(next)
if figtype and domain.get_numfig_title(next):
ids = set()
# labels for figures go in the figure body, not before