Skip to content

Commit ca36c9a

Browse files
authored
Merge pull request #9246 from tk0miya/9240_unknown_node_pending_xref_condition
Fix #9240: Unknown node error for pending_xref_condition is raised
2 parents 630e5bd + 2d3d668 commit ca36c9a

File tree

5 files changed

+85
-9
lines changed

5 files changed

+85
-9
lines changed

CHANGES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Incompatible changes
1010
* #9222: Update Underscore.js to 1.13.1
1111
* #9217: manpage: Stop creating a section directory on build manpage by default
1212
(see :confval:`man_make_section_directory`)
13+
* #9240: Unknown node error for pending_xref_condition is raised if an extension
14+
that does not support the node installs a missing-reference handler
1315

1416
Deprecated
1517
----------

sphinx/transforms/post_transforms/__init__.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
:license: BSD, see LICENSE for details.
99
"""
1010

11-
from typing import Any, Dict, List, Optional, Tuple, Type, cast
11+
from typing import Any, Dict, List, Optional, Sequence, Tuple, Type, cast
1212

1313
from docutils import nodes
14-
from docutils.nodes import Element
14+
from docutils.nodes import Element, Node
1515

1616
from sphinx import addnodes
1717
from sphinx.addnodes import pending_xref
@@ -26,10 +26,6 @@
2626

2727
logger = logging.getLogger(__name__)
2828

29-
if False:
30-
# For type annotation
31-
from docutils.nodes import Node
32-
3329

3430
class SphinxPostTransform(SphinxTransform):
3531
"""A base class of post-transforms.
@@ -71,7 +67,12 @@ class ReferencesResolver(SphinxPostTransform):
7167

7268
def run(self, **kwargs: Any) -> None:
7369
for node in self.document.traverse(addnodes.pending_xref):
74-
contnode = cast(nodes.TextElement, node[0].deepcopy())
70+
content = self.find_pending_xref_condition(node, ("resolved", "*"))
71+
if content:
72+
contnode = cast(Element, content[0].deepcopy())
73+
else:
74+
contnode = cast(Element, node[0].deepcopy())
75+
7576
newnode = None
7677

7778
typ = node['reftype']
@@ -108,9 +109,9 @@ def run(self, **kwargs: Any) -> None:
108109
else:
109110
newnodes = [contnode]
110111
if newnode is None and isinstance(node[0], addnodes.pending_xref_condition):
111-
matched = find_pending_xref_condition(node, "*")
112+
matched = self.find_pending_xref_condition(node, ("*",))
112113
if matched:
113-
newnodes = matched.children
114+
newnodes = matched
114115
else:
115116
logger.warning(__('Could not determine the fallback text for the '
116117
'cross-reference. Might be a bug.'), location=node)
@@ -193,6 +194,15 @@ def warn_missing_reference(self, refdoc: str, typ: str, target: str,
193194
msg = __('%r reference target not found: %s') % (typ, target)
194195
logger.warning(msg, location=node, type='ref', subtype=typ)
195196

197+
def find_pending_xref_condition(self, node: pending_xref, conditions: Sequence[str]
198+
) -> Optional[List[Node]]:
199+
for condition in conditions:
200+
matched = find_pending_xref_condition(node, condition)
201+
if matched:
202+
return matched.children
203+
else:
204+
return None
205+
196206

197207
class OnlyNodeTransform(SphinxPostTransform):
198208
default_priority = 50
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
nitpicky = True
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
transforms-post_transforms-missing-reference
2+
============================================
3+
4+
:class:`io.StringIO`
5+
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
"""
2+
test_transforms_post_transforms
3+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4+
5+
Tests the post_transforms
6+
7+
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
8+
:license: BSD, see LICENSE for details.
9+
"""
10+
11+
import pytest
12+
from docutils import nodes
13+
14+
15+
@pytest.mark.sphinx('html', testroot='transforms-post_transforms-missing-reference')
16+
def test_nitpicky_warning(app, status, warning):
17+
app.build()
18+
assert ('index.rst:4: WARNING: py:class reference target '
19+
'not found: io.StringIO' in warning.getvalue())
20+
21+
content = (app.outdir / 'index.html').read_text()
22+
assert ('<p><code class="xref py py-class docutils literal notranslate"><span class="pre">'
23+
'io.StringIO</span></code></p>' in content)
24+
25+
26+
@pytest.mark.sphinx('html', testroot='transforms-post_transforms-missing-reference',
27+
freshenv=True)
28+
def test_missing_reference(app, status, warning):
29+
def missing_reference(app, env, node, contnode):
30+
assert app is app
31+
assert env is app.env
32+
assert node['reftarget'] == 'io.StringIO'
33+
assert contnode.astext() == 'io.StringIO'
34+
35+
return nodes.inline('', 'missing-reference.StringIO')
36+
37+
warning.truncate(0)
38+
app.connect('missing-reference', missing_reference)
39+
app.build()
40+
assert warning.getvalue() == ''
41+
42+
content = (app.outdir / 'index.html').read_text()
43+
assert '<p><span>missing-reference.StringIO</span></p>' in content
44+
45+
46+
@pytest.mark.sphinx('html', testroot='domain-py-python_use_unqualified_type_names',
47+
freshenv=True)
48+
def test_missing_reference_conditional_pending_xref(app, status, warning):
49+
def missing_reference(app, env, node, contnode):
50+
return contnode
51+
52+
warning.truncate(0)
53+
app.connect('missing-reference', missing_reference)
54+
app.build()
55+
assert warning.getvalue() == ''
56+
57+
content = (app.outdir / 'index.html').read_text()
58+
assert '<span class="n"><span class="pre">Age</span></span>' in content

0 commit comments

Comments
 (0)