From 30c594fbc592a741956c067f5188f9bf6ecd25da Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 19 Dec 2020 16:28:48 +0900 Subject: [PATCH] Fix #8365: py domain: :type: and :rtype: gives false ambiguous warnings The searching context like py:module and py:class are missing in the pending_xref nodes generated from info-field-lists. This sets these searching context info to them. --- CHANGES | 2 ++ sphinx/domains/python.py | 2 ++ sphinx/util/docfields.py | 1 + tests/test_domain_py.py | 47 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+) diff --git a/CHANGES b/CHANGES index 484e654eda5..047eeb70c88 100644 --- a/CHANGES +++ b/CHANGES @@ -81,6 +81,8 @@ Bugs fixed * #8131: linkcheck: Use GET when HEAD requests cause Too Many Redirects, to accommodate infinite redirect loops on HEAD * #8437: Makefile: ``make clean`` with empty BUILDDIR is dangerous +* #8365: py domain: ``:type:`` and ``:rtype:`` gives false ambiguous class + lookup warnings * #8352: std domain: Failed to parse an option that starts with bracket * #8519: LaTeX: Prevent page brake in the middle of a seealso diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py index 79d7e4f466d..c4d134d0874 100644 --- a/sphinx/domains/python.py +++ b/sphinx/domains/python.py @@ -272,6 +272,8 @@ def make_xref(self, rolename: str, domain: str, target: str, result = super().make_xref(rolename, domain, target, # type: ignore innernode, contnode, env) result['refspecific'] = True + result['py:module'] = env.ref_context.get('py:module') + result['py:class'] = env.ref_context.get('py:class') if target.startswith(('.', '~')): prefix, result['reftarget'] = target[0], target[1:] if prefix == '.': diff --git a/sphinx/util/docfields.py b/sphinx/util/docfields.py index 404bb127f82..9a57ccff75a 100644 --- a/sphinx/util/docfields.py +++ b/sphinx/util/docfields.py @@ -295,6 +295,7 @@ def transform(self, node: nodes.field_list) -> None: self.directive.domain, target, contnode=content[0], + env=self.directive.state.document.settings.env ) if _is_single_paragraph(field_body): paragraph = cast(nodes.paragraph, field_body[0]) diff --git a/tests/test_domain_py.py b/tests/test_domain_py.py index 2dc97bed99e..f95521e2e91 100644 --- a/tests/test_domain_py.py +++ b/tests/test_domain_py.py @@ -774,6 +774,53 @@ def test_pydecoratormethod_signature(app): assert domain.objects['deco'] == ('index', 'deco', 'method') +def test_info_field_list(app): + text = (".. py:module:: example\n" + ".. py:class:: Class\n" + "\n" + " :param str name: blah blah\n" + " :param age: blah blah\n" + " :type age: int\n") + doctree = restructuredtext.parse(app, text) + print(doctree) + + assert_node(doctree, (nodes.target, + addnodes.index, + addnodes.index, + [desc, ([desc_signature, ([desc_annotation, "class "], + [desc_addname, "example."], + [desc_name, "Class"])], + [desc_content, nodes.field_list, nodes.field])])) + assert_node(doctree[3][1][0][0], + ([nodes.field_name, "Parameters"], + [nodes.field_body, nodes.bullet_list, ([nodes.list_item, nodes.paragraph], + [nodes.list_item, nodes.paragraph])])) + + # :param str name: + assert_node(doctree[3][1][0][0][1][0][0][0], + ([addnodes.literal_strong, "name"], + " (", + [pending_xref, addnodes.literal_emphasis, "str"], + ")", + " -- ", + "blah blah")) + assert_node(doctree[3][1][0][0][1][0][0][0][2], pending_xref, + refdomain="py", reftype="class", reftarget="str", + **{"py:module": "example", "py:class": "Class"}) + + # :param age: + :type age: + assert_node(doctree[3][1][0][0][1][0][1][0], + ([addnodes.literal_strong, "age"], + " (", + [pending_xref, addnodes.literal_emphasis, "int"], + ")", + " -- ", + "blah blah")) + assert_node(doctree[3][1][0][0][1][0][1][0][2], pending_xref, + refdomain="py", reftype="class", reftarget="int", + **{"py:module": "example", "py:class": "Class"}) + + @pytest.mark.sphinx(freshenv=True) def test_module_index(app): text = (".. py:module:: docutils\n"