diff options
Diffstat (limited to 'sphinx/util/nodes.py')
-rw-r--r-- | sphinx/util/nodes.py | 62 |
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: |