summaryrefslogtreecommitdiff
path: root/sphinx/util/nodes.py
diff options
context:
space:
mode:
Diffstat (limited to 'sphinx/util/nodes.py')
-rw-r--r--sphinx/util/nodes.py62
1 files changed, 57 insertions, 5 deletions
diff --git a/sphinx/util/nodes.py b/sphinx/util/nodes.py
index 0d86c1ec0..d3441565b 100644
--- a/sphinx/util/nodes.py
+++ b/sphinx/util/nodes.py
@@ -16,12 +16,12 @@ from docutils import nodes
from six import text_type
from sphinx import addnodes
-from sphinx.locale import pairindextypes
+from sphinx.locale import __
from sphinx.util import logging
if False:
# For type annotation
- from typing import Any, Callable, Iterable, List, Set, Tuple, Union # NOQA
+ from typing import Any, Callable, Iterable, List, Set, Tuple, Optional # NOQA
from sphinx.builders import Builder # NOQA
from sphinx.utils.tags import Tags # NOQA
@@ -33,6 +33,36 @@ explicit_title_re = re.compile(r'^(.+?)\s*(?<!\x00)<(.*?)>$', re.DOTALL)
caption_ref_re = explicit_title_re # b/w compat alias
+def get_full_module_name(node):
+ # type: (nodes.Node) -> str
+ """
+ return full module dotted path like: 'docutils.nodes.paragraph'
+
+ :param nodes.Node node: target node
+ :return: full module dotted path
+ """
+ return '{}.{}'.format(node.__module__, node.__class__.__name__)
+
+
+def repr_domxml(node, length=80):
+ # type: (nodes.Node, Optional[int]) -> unicode
+ """
+ return DOM XML representation of the specified node like:
+ '<paragraph translatable="False"><inline classes="versionmodified">New in version...'
+
+ :param nodes.Node node: target node
+ :param int length:
+ length of return value to be striped. if false-value is specified, repr_domxml
+ returns full of DOM XML representation.
+ :return: DOM XML representation
+ """
+ # text = node.asdom().toxml() # #4919 crush if node has secnumber with tuple value
+ text = text_type(node) # workaround for #4919
+ if length and len(text) > length:
+ text = text[:length] + '...'
+ return text
+
+
def apply_source_workaround(node):
# type: (nodes.Node) -> None
# workaround: nodes.term have wrong rawsource if classifier is specified.
@@ -41,11 +71,15 @@ def apply_source_workaround(node):
# * rawsource of term node will have: ``term text : classifier1 : classifier2``
# * rawsource of classifier node will be None
if isinstance(node, nodes.classifier) and not node.rawsource:
+ logger.debug('[i18n] PATCH: %r to have source, line and rawsource: %s',
+ get_full_module_name(node), repr_domxml(node))
definition_list_item = node.parent
node.source = definition_list_item.source
node.line = definition_list_item.line - 1
node.rawsource = node.astext() # set 'classifier1' (or 'classifier2')
if isinstance(node, nodes.image) and node.source is None:
+ logger.debug('[i18n] PATCH: %r to have source, line: %s',
+ get_full_module_name(node), repr_domxml(node))
node.source, node.line = node.parent.source, node.parent.line
if isinstance(node, nodes.title) and node.source is None:
# Uncomment these lines after merging into master(1.8)
@@ -53,6 +87,8 @@ def apply_source_workaround(node):
# get_full_module_name(node), repr_domxml(node))
node.source, node.line = node.parent.source, node.parent.line
if isinstance(node, nodes.term):
+ logger.debug('[i18n] PATCH: %r to have rawsource: %s',
+ get_full_module_name(node), repr_domxml(node))
# strip classifier from rawsource of term
for classifier in reversed(node.parent.traverse(nodes.classifier)):
node.rawsource = re.sub(r'\s*:\s*%s' % re.escape(classifier.astext()),
@@ -76,6 +112,8 @@ def apply_source_workaround(node):
nodes.image, # #3093 image directive in substitution
nodes.field_name, # #3335 field list syntax
))):
+ logger.debug('[i18n] PATCH: %r to have source and line: %s',
+ get_full_module_name(node), repr_domxml(node))
node.source = find_source_node(node)
node.line = 0 # need fix docutils to get `node.line`
return
@@ -83,7 +121,6 @@ def apply_source_workaround(node):
IGNORED_NODES = (
nodes.Invisible,
- nodes.Inline,
nodes.literal_block,
nodes.doctest_block,
addnodes.versionmodified,
@@ -105,17 +142,30 @@ def is_translatable(node):
if isinstance(node, addnodes.translatable):
return True
+ if isinstance(node, nodes.Inline) and 'translatable' not in node:
+ # inline node must not be translated if 'translatable' is not set
+ return False
+
if isinstance(node, nodes.TextElement):
if not node.source:
+ logger.debug('[i18n] SKIP %r because no node.source: %s',
+ get_full_module_name(node), repr_domxml(node))
return False # built-in message
if isinstance(node, IGNORED_NODES) and 'translatable' not in node:
+ logger.debug("[i18n] SKIP %r because node is in IGNORED_NODES "
+ "and no node['translatable']: %s",
+ get_full_module_name(node), repr_domxml(node))
return False
if not node.get('translatable', True):
# not(node['translatable'] == True or node['translatable'] is None)
+ logger.debug("[i18n] SKIP %r because not node['translatable']: %s",
+ get_full_module_name(node), repr_domxml(node))
return False
# <field_name>orphan</field_name>
# XXX ignore all metadata (== docinfo)
if isinstance(node, nodes.field_name) and node.children[0] == 'orphan':
+ logger.debug('[i18n] SKIP %r because orphan node: %s',
+ get_full_module_name(node), repr_domxml(node))
return False
return True
@@ -249,6 +299,8 @@ indextypes = [
def process_index_entry(entry, targetid):
# type: (unicode, unicode) -> List[Tuple[unicode, unicode, unicode, unicode, unicode]]
+ from sphinx.domains.python import pairindextypes
+
indexentries = [] # type: List[Tuple[unicode, unicode, unicode, unicode, unicode]]
entry = entry.strip()
oentry = entry
@@ -304,7 +356,7 @@ def inline_all_toctrees(builder, docnameset, docname, tree, colorfunc, traversed
colorfunc, traversed)
docnameset.add(includefile)
except Exception:
- logger.warning('toctree contains ref to nonexisting file %r',
+ logger.warning(__('toctree contains ref to nonexisting file %r'),
includefile, location=docname)
else:
sof = addnodes.start_of_file(docname=includefile)
@@ -377,7 +429,7 @@ def process_only_nodes(document, tags):
try:
ret = tags.eval_condition(node['expr'])
except Exception as err:
- logger.warning('exception while evaluating only directive expression: %s', err,
+ logger.warning(__('exception while evaluating only directive expression: %s'), err,
location=node)
node.replace_self(node.children or nodes.comment())
else: