intersphinx: Support pending_xref_condition

This commit is contained in:
Takeshi KOMIYA
2021-03-06 14:43:13 +09:00
parent 930a880294
commit 7f0b13af6e
2 changed files with 26 additions and 5 deletions

View File

@@ -33,10 +33,11 @@ from typing import IO, Any, Dict, List, Tuple
from urllib.parse import urlsplit, urlunsplit from urllib.parse import urlsplit, urlunsplit
from docutils import nodes from docutils import nodes
from docutils.nodes import Element, TextElement from docutils.nodes import TextElement
from docutils.utils import relative_path from docutils.utils import relative_path
import sphinx import sphinx
from sphinx.addnodes import pending_xref
from sphinx.application import Sphinx from sphinx.application import Sphinx
from sphinx.builders.html import INVENTORY_FILENAME from sphinx.builders.html import INVENTORY_FILENAME
from sphinx.config import Config from sphinx.config import Config
@@ -44,6 +45,7 @@ from sphinx.environment import BuildEnvironment
from sphinx.locale import _, __ from sphinx.locale import _, __
from sphinx.util import logging, requests from sphinx.util import logging, requests
from sphinx.util.inventory import InventoryFile from sphinx.util.inventory import InventoryFile
from sphinx.util.nodes import find_pending_xref_condition
from sphinx.util.typing import Inventory from sphinx.util.typing import Inventory
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -257,8 +259,8 @@ def load_mappings(app: Sphinx) -> None:
inventories.main_inventory.setdefault(type, {}).update(objects) inventories.main_inventory.setdefault(type, {}).update(objects)
def missing_reference(app: Sphinx, env: BuildEnvironment, node: Element, contnode: TextElement def missing_reference(app: Sphinx, env: BuildEnvironment, node: pending_xref,
) -> nodes.reference: contnode: TextElement) -> nodes.reference:
"""Attempt to resolve a missing reference via intersphinx references.""" """Attempt to resolve a missing reference via intersphinx references."""
target = node['reftarget'] target = node['reftarget']
inventories = InventoryAdapter(env) inventories = InventoryAdapter(env)
@@ -284,6 +286,17 @@ def missing_reference(app: Sphinx, env: BuildEnvironment, node: Element, contnod
if 'py:attribute' in objtypes: if 'py:attribute' in objtypes:
# Since Sphinx-2.1, properties are stored as py:method # Since Sphinx-2.1, properties are stored as py:method
objtypes.append('py:method') objtypes.append('py:method')
# determine the contnode by pending_xref_condition
content = find_pending_xref_condition(node, 'resolved')
if content:
# resolved condition found.
contnodes = content.children
contnode = content.children[0] # type: ignore
else:
# not resolved. Use the given contnode
contnodes = [contnode]
to_try = [(inventories.main_inventory, target)] to_try = [(inventories.main_inventory, target)]
if domain: if domain:
full_qualified_name = env.get_domain(domain).get_full_qualified_name(node) full_qualified_name = env.get_domain(domain).get_full_qualified_name(node)
@@ -316,7 +329,7 @@ def missing_reference(app: Sphinx, env: BuildEnvironment, node: Element, contnod
newnode = nodes.reference('', '', internal=False, refuri=uri, reftitle=reftitle) newnode = nodes.reference('', '', internal=False, refuri=uri, reftitle=reftitle)
if node.get('refexplicit'): if node.get('refexplicit'):
# use whatever title was given # use whatever title was given
newnode.append(contnode) newnode.extend(contnodes)
elif dispname == '-' or \ elif dispname == '-' or \
(domain == 'std' and node['reftype'] == 'keyword'): (domain == 'std' and node['reftype'] == 'keyword'):
# use whatever title was given, but strip prefix # use whatever title was given, but strip prefix
@@ -325,7 +338,7 @@ def missing_reference(app: Sphinx, env: BuildEnvironment, node: Element, contnod
newnode.append(contnode.__class__(title[len(in_set) + 1:], newnode.append(contnode.__class__(title[len(in_set) + 1:],
title[len(in_set) + 1:])) title[len(in_set) + 1:]))
else: else:
newnode.append(contnode) newnode.extend(contnodes)
else: else:
# else use the given display name (used for :ref:) # else use the given display name (used for :ref:)
newnode.append(contnode.__class__(dispname, dispname)) newnode.append(contnode.__class__(dispname, dispname))

View File

@@ -196,6 +196,14 @@ def test_missing_reference_pydomain(tempdir, app, status, warning):
rn = missing_reference(app, app.env, node, contnode) rn = missing_reference(app, app.env, node, contnode)
assert rn.astext() == 'Foo.bar' assert rn.astext() == 'Foo.bar'
# pending_xref_condition="resolved"
node = addnodes.pending_xref('', reftarget='Foo.bar', refdomain='py', reftype='attr')
node['py:module'] = 'module1'
node += addnodes.pending_xref_condition('', 'Foo.bar', condition='resolved')
node += addnodes.pending_xref_condition('', 'module1.Foo.bar', condition='*')
rn = missing_reference(app, app.env, node, nodes.Text('dummy-cont-node'))
assert rn.astext() == 'Foo.bar'
def test_missing_reference_stddomain(tempdir, app, status, warning): def test_missing_reference_stddomain(tempdir, app, status, warning):
inv_file = tempdir / 'inventory' inv_file = tempdir / 'inventory'