Merge pull request #3425 from tk0miya/3351_intersphinx_ref_with_context

Fix #3351: intersphinx does not refers context
This commit is contained in:
Takeshi KOMIYA 2017-04-23 16:15:07 +09:00 committed by GitHub
commit bd7fccb8d0
6 changed files with 69 additions and 2 deletions

View File

@ -133,6 +133,8 @@ Bugs fixed
* C++, properly look up ``any`` references. * C++, properly look up ``any`` references.
* #3624: sphinx.ext.intersphinx couldn't load inventories compressed with gzip * #3624: sphinx.ext.intersphinx couldn't load inventories compressed with gzip
* #3551: PDF information dictionary is lacking author and title data * #3551: PDF information dictionary is lacking author and title data
* #3351: intersphinx does not refers context like ``py:module``, ``py:class``
and so on.
* Fail to load template file if the parent template is archived * Fail to load template file if the parent template is archived
Deprecated Deprecated

View File

@ -308,3 +308,8 @@ class Domain(object):
if primary: if primary:
return type.lname return type.lname
return _('%s %s') % (self.label, type.lname) return _('%s %s') % (self.label, type.lname)
def get_full_qualified_name(self, node):
# type: (nodes.Node) -> unicode
"""Return full qualified name for given node."""
return None

View File

@ -885,6 +885,16 @@ class PythonDomain(Domain):
if type != 'module': # modules are already handled if type != 'module': # modules are already handled
yield (refname, refname, type, docname, refname, 1) yield (refname, refname, type, docname, refname, 1)
def get_full_qualified_name(self, node):
# type: (nodes.Node) -> unicode
modname = node.get('py:module')
clsname = node.get('py:class')
target = node.get('reftarget')
if target is None:
return None
else:
return '.'.join(filter(None, [modname, clsname, target]))
def setup(app): def setup(app):
# type: (Sphinx) -> Dict[unicode, Any] # type: (Sphinx) -> Dict[unicode, Any]

View File

@ -292,6 +292,10 @@ def missing_reference(app, env, node, contnode):
# until Sphinx-1.6, cmdoptions are stored as std:option # until Sphinx-1.6, cmdoptions are stored as std:option
objtypes.append('std:option') objtypes.append('std:option')
to_try = [(inventories.main_inventory, target)] to_try = [(inventories.main_inventory, target)]
if domain:
full_qualified_name = env.get_domain(domain).get_full_qualified_name(node)
if full_qualified_name:
to_try.append((inventories.main_inventory, full_qualified_name))
in_set = None in_set = None
if ':' in target: if ':' in target:
# first part may be the foreign doc set name # first part may be the foreign doc set name
@ -299,6 +303,10 @@ def missing_reference(app, env, node, contnode):
if setname in inventories.named_inventory: if setname in inventories.named_inventory:
in_set = setname in_set = setname
to_try.append((inventories.named_inventory[setname], newtarget)) to_try.append((inventories.named_inventory[setname], newtarget))
if domain:
full_qualified_name = env.get_domain(domain).get_full_qualified_name(node)
if full_qualified_name:
to_try.append((inventories.named_inventory[setname], full_qualified_name))
for inventory, target in to_try: for inventory, target in to_try:
for objtype in objtypes: for objtype in objtypes:
if objtype not in inventory or target not in inventory[objtype]: if objtype not in inventory or target not in inventory[objtype]:

View File

@ -10,9 +10,12 @@
""" """
import pytest import pytest
from mock import Mock
from six import text_type from six import text_type
from docutils import nodes
from sphinx import addnodes from sphinx import addnodes
from sphinx.domains.python import py_sig_re, _pseudo_parse_arglist from sphinx.domains.python import py_sig_re, _pseudo_parse_arglist, PythonDomain
from util import assert_node from util import assert_node
@ -28,7 +31,6 @@ def parse(sig):
def test_function_signatures(): def test_function_signatures():
rv = parse('func(a=1) -> int object') rv = parse('func(a=1) -> int object')
assert text_type(rv) == u'a=1' assert text_type(rv) == u'a=1'
@ -165,3 +167,31 @@ def test_domain_py_find_obj(app, status, warning):
[(u'NestedParentA.NestedChildA.subchild_1', (u'roles', u'method'))]) [(u'NestedParentA.NestedChildA.subchild_1', (u'roles', u'method'))])
assert (find_obj(None, u'NestedParentA.NestedChildA', u'subchild_1', u'meth') == assert (find_obj(None, u'NestedParentA.NestedChildA', u'subchild_1', u'meth') ==
[(u'NestedParentA.NestedChildA.subchild_1', (u'roles', u'method'))]) [(u'NestedParentA.NestedChildA.subchild_1', (u'roles', u'method'))])
def test_get_full_qualified_name():
env = Mock(domaindata={})
domain = PythonDomain(env)
# non-python references
node = nodes.reference()
assert domain.get_full_qualified_name(node) is None
# simple reference
node = nodes.reference(reftarget='func')
assert domain.get_full_qualified_name(node) == 'func'
# with py:module context
kwargs = {'py:module': 'module1'}
node = nodes.reference(reftarget='func', **kwargs)
assert domain.get_full_qualified_name(node) == 'module1.func'
# with py:class context
kwargs = {'py:class': 'Class'}
node = nodes.reference(reftarget='func', **kwargs)
assert domain.get_full_qualified_name(node) == 'Class.func'
# with both py:module and py:class context
kwargs = {'py:module': 'module1', 'py:class': 'Class'}
node = nodes.reference(reftarget='func', **kwargs)
assert domain.get_full_qualified_name(node) == 'module1.Class.func'

View File

@ -145,6 +145,18 @@ def test_missing_reference(tempdir, app, status, warning):
assert rn is None assert rn is None
assert contnode[0].astext() == 'py3k:unknown' assert contnode[0].astext() == 'py3k:unknown'
# no context data
kwargs = {}
node, contnode = fake_node('py', 'func', 'func', 'func()', **kwargs)
rn = missing_reference(app, app.env, node, contnode)
assert rn is None
# context data (like py:module) help to search objects
kwargs = {'py:module': 'module1'}
node, contnode = fake_node('py', 'func', 'func', 'func()', **kwargs)
rn = missing_reference(app, app.env, node, contnode)
assert rn[0].astext() == 'func()'
# check relative paths # check relative paths
rn = reference_check('py', 'mod', 'py3krel:module1', 'foo') rn = reference_check('py', 'mod', 'py3krel:module1', 'foo')
assert rn['refuri'] == 'py3k/foo.html#module-module1' assert rn['refuri'] == 'py3k/foo.html#module-module1'