diff --git a/numpydoc/numpydoc.py b/numpydoc/numpydoc.py index c8e676f5..2544d0f3 100644 --- a/numpydoc/numpydoc.py +++ b/numpydoc/numpydoc.py @@ -27,8 +27,9 @@ except ImportError: from collections import Callable import hashlib +import itertools -from docutils.nodes import citation, Text, reference +from docutils.nodes import citation, Text, section, comment, reference import sphinx from sphinx.addnodes import pending_xref, desc_content, only @@ -73,18 +74,39 @@ def rename_references(app, what, name, obj, options, lines): sixu('.. [%s]') % new_r) -def _ascend(node, cls): - while node and not isinstance(node, cls): - node = node.parent - return node +def _is_cite_in_numpydoc_docstring(citation_node): + # Find DEDUPLICATION_TAG in comment as last node of sibling section + + # XXX: I failed to use citation_node.traverse to do this: + section_node = citation_node.parent + + def is_docstring_section(node): + return isinstance(node, (section, desc_content)) + + while not is_docstring_section(section_node): + section_node = section_node.parent + if section_node is None: + return False + + sibling_sections = itertools.chain(section_node.traverse(is_docstring_section, + include_self=True, + descend=False, + siblings=True)) + for sibling_section in sibling_sections: + if not sibling_section.children: + continue + last_child = sibling_section.children[-1] + if not isinstance(last_child, comment): + continue + if last_child.rawsource.strip() == DEDUPLICATION_TAG.strip(): + return True + return False def relabel_references(app, doc): # Change 'hash-ref' to 'ref' in label text for citation_node in doc.traverse(citation): - if _ascend(citation_node, desc_content) is None: - # no desc node in ancestry -> not in a docstring - # XXX: should we also somehow check it's in a References section? + if not _is_cite_in_numpydoc_docstring(citation_node): continue label_node = citation_node[0] prefix, _, new_label = label_node[0].astext().partition('-')