summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel McCloy <dan@mccloy.info>2022-06-02 11:03:19 -0500
committerGitHub <noreply@github.com>2022-06-02 09:03:19 -0700
commit601642bbe93c906dcbd991c9cb429e48cf5cefe6 (patch)
tree928e39f368c2839f4524cb166c8f1febde60b089
parent85a4327d87270f4f9c4139f784b6d8f327ec45f0 (diff)
downloadnumpydoc-601642bbe93c906dcbd991c9cb429e48cf5cefe6.tar.gz
Use node.findall if available (docutils 18.x) (#403)
* use node.findall if available (docutils 18.x) * fix test_reference * keep test_reference backwards-compatible * Add comments about when triage becomes unnecessary/obsolete Co-authored-by: Jarrod Millman <jarrod.millman@gmail.com> * whitespace * fix docutils version as noted in docstring Co-authored-by: Jarrod Millman <jarrod.millman@gmail.com> Co-authored-by: Eric Larson <larson.eric.d@gmail.com>
-rw-r--r--numpydoc/numpydoc.py29
-rw-r--r--numpydoc/tests/test_full.py11
2 files changed, 33 insertions, 7 deletions
diff --git a/numpydoc/numpydoc.py b/numpydoc/numpydoc.py
index 8210006..e656fb5 100644
--- a/numpydoc/numpydoc.py
+++ b/numpydoc/numpydoc.py
@@ -43,6 +43,19 @@ logger = logging.getLogger(__name__)
HASH_LEN = 12
+def _traverse_or_findall(node, condition, **kwargs):
+ """Triage node.traverse (docutils <0.18.1) vs node.findall.
+
+ TODO: This check can be removed when the minimum supported docutils version
+ for numpydoc is docutils>=0.18.1
+ """
+ return (
+ node.findall(condition, **kwargs)
+ if hasattr(node, "findall")
+ else node.traverse(condition, **kwargs)
+ )
+
+
def rename_references(app, what, name, obj, options, lines):
# decorate reference numbers so that there are no duplicates
# these are later undecorated in the doctree, in relabel_references
@@ -81,8 +94,12 @@ def _is_cite_in_numpydoc_docstring(citation_node):
return False
sibling_sections = itertools.chain(
- section_node.traverse(
- is_docstring_section, include_self=True, descend=False, siblings=True
+ _traverse_or_findall(
+ section_node,
+ is_docstring_section,
+ include_self=True,
+ descend=False,
+ siblings=True,
)
)
for sibling_section in sibling_sections:
@@ -101,7 +118,7 @@ def _is_cite_in_numpydoc_docstring(citation_node):
def relabel_references(app, doc):
# Change 'hash-ref' to 'ref' in label text
- for citation_node in doc.traverse(citation):
+ for citation_node in _traverse_or_findall(doc, citation):
if not _is_cite_in_numpydoc_docstring(citation_node):
continue
label_node = citation_node[0]
@@ -121,7 +138,7 @@ def relabel_references(app, doc):
and node[0].astext() == f"[{ref_text}]"
)
- for xref_node in ref.parent.traverse(matching_pending_xref):
+ for xref_node in _traverse_or_findall(ref.parent, matching_pending_xref):
xref_node.replace(xref_node[0], Text(f"[{new_text}]"))
ref.replace(ref_text, new_text.copy())
@@ -129,10 +146,10 @@ def relabel_references(app, doc):
def clean_backrefs(app, doc, docname):
# only::latex directive has resulted in citation backrefs without reference
known_ref_ids = set()
- for ref in doc.traverse(reference, descend=True):
+ for ref in _traverse_or_findall(doc, reference, descend=True):
for id_ in ref["ids"]:
known_ref_ids.add(id_)
- for citation_node in doc.traverse(citation, descend=True):
+ for citation_node in _traverse_or_findall(doc, citation, descend=True):
# remove backrefs to non-existent refs
citation_node["backrefs"] = [
id_ for id_ in citation_node["backrefs"] if id_ in known_ref_ids
diff --git a/numpydoc/tests/test_full.py b/numpydoc/tests/test_full.py
index e0defe2..c4ae134 100644
--- a/numpydoc/tests/test_full.py
+++ b/numpydoc/tests/test_full.py
@@ -1,11 +1,13 @@
import os.path as op
import re
import shutil
+from packaging import version
import pytest
import sphinx
from sphinx.application import Sphinx
from sphinx.util.docutils import docutils_namespace
+from docutils import __version__ as docutils_version
# Test framework adapted from sphinx-gallery (BSD 3-clause)
@@ -89,7 +91,14 @@ def test_reference(sphinx_app, html_file, expected_length):
with open(op.join(out_dir, *html_file)) as fid:
html = fid.read()
- reference_list = re.findall(r'<a class="fn-backref" href="\#id\d+">(.*)<\/a>', html)
+ # TODO: This check can be removed when the minimum supported docutils version
+ # for numpydoc is docutils>=0.18
+ pattern = (
+ 'role="doc-backlink"'
+ if version.parse(docutils_version) >= version.parse("0.18")
+ else 'class="fn-backref"'
+ )
+ reference_list = re.findall(rf'<a {pattern} href="\#id\d+">(.*)<\/a>', html)
assert len(reference_list) == expected_length
for ref in reference_list: