|
27 | 27 | except ImportError:
|
28 | 28 | from collections import Callable
|
29 | 29 | import hashlib
|
| 30 | +import itertools |
30 | 31 |
|
31 |
| -from docutils.nodes import citation, Text, reference |
| 32 | +from docutils.nodes import citation, Text, section, comment, reference |
32 | 33 | import sphinx
|
33 | 34 | from sphinx.addnodes import pending_xref, desc_content, only
|
34 | 35 |
|
@@ -73,18 +74,39 @@ def rename_references(app, what, name, obj, options, lines):
|
73 | 74 | sixu('.. [%s]') % new_r)
|
74 | 75 |
|
75 | 76 |
|
76 |
| -def _ascend(node, cls): |
77 |
| - while node and not isinstance(node, cls): |
78 |
| - node = node.parent |
79 |
| - return node |
| 77 | +def _is_cite_in_numpydoc_docstring(citation_node): |
| 78 | + # Find DEDUPLICATION_TAG in comment as last node of sibling section |
| 79 | + |
| 80 | + # XXX: I failed to use citation_node.traverse to do this: |
| 81 | + section_node = citation_node.parent |
| 82 | + |
| 83 | + def is_docstring_section(node): |
| 84 | + return isinstance(node, (section, desc_content)) |
| 85 | + |
| 86 | + while not is_docstring_section(section_node): |
| 87 | + section_node = section_node.parent |
| 88 | + if section_node is None: |
| 89 | + return False |
| 90 | + |
| 91 | + sibling_sections = itertools.chain(section_node.traverse(is_docstring_section, |
| 92 | + include_self=True, |
| 93 | + descend=False, |
| 94 | + siblings=True)) |
| 95 | + for sibling_section in sibling_sections: |
| 96 | + if not sibling_section.children: |
| 97 | + continue |
| 98 | + last_child = sibling_section.children[-1] |
| 99 | + if not isinstance(last_child, comment): |
| 100 | + continue |
| 101 | + if last_child.rawsource.strip() == DEDUPLICATION_TAG.strip(): |
| 102 | + return True |
| 103 | + return False |
80 | 104 |
|
81 | 105 |
|
82 | 106 | def relabel_references(app, doc):
|
83 | 107 | # Change 'hash-ref' to 'ref' in label text
|
84 | 108 | for citation_node in doc.traverse(citation):
|
85 |
| - if _ascend(citation_node, desc_content) is None: |
86 |
| - # no desc node in ancestry -> not in a docstring |
87 |
| - # XXX: should we also somehow check it's in a References section? |
| 109 | + if not _is_cite_in_numpydoc_docstring(citation_node): |
88 | 110 | continue
|
89 | 111 | label_node = citation_node[0]
|
90 | 112 | prefix, _, new_label = label_node[0].astext().partition('-')
|
|
0 commit comments