From 76c033badca91f563ea840d780485377b0c71e76 Mon Sep 17 00:00:00 2001 From: Daniel McCloy Date: Sat, 28 May 2022 13:49:22 -0500 Subject: [PATCH 1/6] use node.findall if available (docutils 18.x) --- numpydoc/numpydoc.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/numpydoc/numpydoc.py b/numpydoc/numpydoc.py index 82100062..7748cd02 100644 --- a/numpydoc/numpydoc.py +++ b/numpydoc/numpydoc.py @@ -43,6 +43,15 @@ HASH_LEN = 12 +def _traverse_or_findall(node, condition, **kwargs): + """Triage node.traverse (docutils <0.18) vs node.findall.""" + 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 +90,12 @@ def is_docstring_section(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 +114,7 @@ def is_docstring_section(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 +134,7 @@ def matching_pending_xref(node): 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 +142,10 @@ def matching_pending_xref(node): 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 From 29caa4938f418df0eaf55a0e55fde74e999b48c2 Mon Sep 17 00:00:00 2001 From: Daniel McCloy Date: Sat, 28 May 2022 14:53:50 -0500 Subject: [PATCH 2/6] fix test_reference --- numpydoc/tests/test_full.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/numpydoc/tests/test_full.py b/numpydoc/tests/test_full.py index e0defe2e..0ecf57c7 100644 --- a/numpydoc/tests/test_full.py +++ b/numpydoc/tests/test_full.py @@ -89,7 +89,7 @@ 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>', html) + reference_list = re.findall(r'(.*)<\/a>', html) assert len(reference_list) == expected_length for ref in reference_list: From 61becbaabbcd22dfe579963d42101a206c35ed1e Mon Sep 17 00:00:00 2001 From: Daniel McCloy Date: Sat, 28 May 2022 15:34:38 -0500 Subject: [PATCH 3/6] keep test_reference backwards-compatible --- numpydoc/tests/test_full.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/numpydoc/tests/test_full.py b/numpydoc/tests/test_full.py index 0ecf57c7..8b14c8d4 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,12 @@ 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>', html) + pattern = ( + 'role="doc-backlink"' + if version.parse(docutils_version) >= version.parse("0.18") + else 'class="fn-backref"' + ) + reference_list = re.findall(rf'(.*)<\/a>', html) assert len(reference_list) == expected_length for ref in reference_list: From 99d09618223c4cff9bf1169d683c2ed0ea46d963 Mon Sep 17 00:00:00 2001 From: Daniel McCloy Date: Tue, 31 May 2022 13:24:06 -0500 Subject: [PATCH 4/6] Add comments about when triage becomes unnecessary/obsolete Co-authored-by: Jarrod Millman --- numpydoc/numpydoc.py | 6 +++++- numpydoc/tests/test_full.py | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/numpydoc/numpydoc.py b/numpydoc/numpydoc.py index 7748cd02..74a32e9f 100644 --- a/numpydoc/numpydoc.py +++ b/numpydoc/numpydoc.py @@ -44,7 +44,11 @@ def _traverse_or_findall(node, condition, **kwargs): - """Triage node.traverse (docutils <0.18) vs node.findall.""" + """Triage node.traverse (docutils <0.18) vs node.findall. + + TODO: This check can be removed when the minimum supported docutils version + for numpydoc is docutils>=0.18 + """ return ( node.findall(condition, **kwargs) if hasattr(node, "findall") diff --git a/numpydoc/tests/test_full.py b/numpydoc/tests/test_full.py index 8b14c8d4..c4ae1340 100644 --- a/numpydoc/tests/test_full.py +++ b/numpydoc/tests/test_full.py @@ -91,6 +91,8 @@ def test_reference(sphinx_app, html_file, expected_length): with open(op.join(out_dir, *html_file)) as fid: html = fid.read() + # 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") From 0df45f0cc87fc6c88f99756b24756f363cd8515b Mon Sep 17 00:00:00 2001 From: Daniel McCloy Date: Tue, 31 May 2022 13:25:52 -0500 Subject: [PATCH 5/6] whitespace --- numpydoc/numpydoc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/numpydoc/numpydoc.py b/numpydoc/numpydoc.py index 74a32e9f..8111698b 100644 --- a/numpydoc/numpydoc.py +++ b/numpydoc/numpydoc.py @@ -45,8 +45,8 @@ def _traverse_or_findall(node, condition, **kwargs): """Triage node.traverse (docutils <0.18) vs node.findall. - - TODO: This check can be removed when the minimum supported docutils version + + TODO: This check can be removed when the minimum supported docutils version for numpydoc is docutils>=0.18 """ return ( From 296bbdebc42990e96eb2f05c4224bb11950e9f3d Mon Sep 17 00:00:00 2001 From: Daniel McCloy Date: Wed, 1 Jun 2022 09:39:16 -0500 Subject: [PATCH 6/6] fix docutils version as noted in docstring --- numpydoc/numpydoc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/numpydoc/numpydoc.py b/numpydoc/numpydoc.py index 8111698b..e656fb5c 100644 --- a/numpydoc/numpydoc.py +++ b/numpydoc/numpydoc.py @@ -44,10 +44,10 @@ def _traverse_or_findall(node, condition, **kwargs): - """Triage node.traverse (docutils <0.18) vs node.findall. + """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 + for numpydoc is docutils>=0.18.1 """ return ( node.findall(condition, **kwargs)