Fix `:paramtype:` reference targets (#11964)

This commit is contained in:
Bénédikt Tran 2024-02-14 00:04:49 +01:00 committed by GitHub
parent a408ec5f51
commit b587eb243a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 106 additions and 1 deletions

View File

@ -77,6 +77,8 @@ Bugs fixed
* #11925: Blacklist the ``sphinxprettysearchresults`` extension; the functionality * #11925: Blacklist the ``sphinxprettysearchresults`` extension; the functionality
it provides was merged into Sphinx v2.0.0. it provides was merged into Sphinx v2.0.0.
Patch by James Addison. Patch by James Addison.
* #11962: Fix target resolution when using ``:paramtype:`` fields.
Patch by Bénédikt Tran.
Testing Testing
------- -------

View File

@ -339,7 +339,7 @@ def _patch_python_domain() -> None:
PyObject.doc_field_types.append( PyObject.doc_field_types.append(
PyTypedField('keyword', label=_('Keyword Arguments'), PyTypedField('keyword', label=_('Keyword Arguments'),
names=('keyword', 'kwarg', 'kwparam'), names=('keyword', 'kwarg', 'kwparam'),
typerolename='obj', typenames=('paramtype', 'kwtype'), typerolename='class', typenames=('paramtype', 'kwtype'),
can_collapse=True)) can_collapse=True))

View File

@ -0,0 +1,15 @@
import os
import sys
sys.path.insert(0, os.path.abspath('.'))
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.napoleon',
'sphinx.ext.intersphinx'
]
# Python inventory is manually created in the test
# in order to avoid creating a real HTTP connection
intersphinx_mapping = {}
intersphinx_cache_limit = 0
intersphinx_disabled_reftypes = []

View File

@ -0,0 +1,8 @@
test-ext-napoleon
=================
.. automodule:: pkg.bar
:members:
.. automodule:: pkg.foo
:members:

View File

@ -0,0 +1,10 @@
class Bar:
"""The bar."""
def list(self) -> None:
"""A list method."""
@staticmethod
def int() -> float:
"""An int method."""
return 1.0

View File

@ -0,0 +1,27 @@
class Foo:
"""The foo."""
def do(
self,
*,
keyword_paramtype,
keyword_kwtype,
kwarg_paramtype,
kwarg_kwtype,
kwparam_paramtype,
kwparam_kwtype,
):
"""Some method.
:keyword keyword_paramtype: some param
:paramtype keyword_paramtype: list[int]
:keyword keyword_kwtype: some param
:kwtype keyword_kwtype: list[int]
:kwarg kwarg_paramtype: some param
:paramtype kwarg_paramtype: list[int]
:kwarg kwarg_kwtype: some param
:kwtype kwarg_kwtype: list[int]
:kwparam kwparam_paramtype: some param
:paramtype kwparam_paramtype: list[int]
:kwparam kwparam_kwtype: some param
:kwtype kwparam_kwtype: list[int]
"""

View File

@ -1,13 +1,17 @@
"""Tests for :mod:`sphinx.ext.napoleon.docstring` module.""" """Tests for :mod:`sphinx.ext.napoleon.docstring` module."""
import re import re
import zlib
from collections import namedtuple from collections import namedtuple
from inspect import cleandoc from inspect import cleandoc
from itertools import product
from textwrap import dedent from textwrap import dedent
from unittest import mock from unittest import mock
import pytest import pytest
from html5lib import HTMLParser
from sphinx.ext.intersphinx import load_mappings, normalize_intersphinx_mapping
from sphinx.ext.napoleon import Config from sphinx.ext.napoleon import Config
from sphinx.ext.napoleon.docstring import ( from sphinx.ext.napoleon.docstring import (
GoogleDocstring, GoogleDocstring,
@ -2659,3 +2663,42 @@ def test_napoleon_and_autodoc_typehints_description_documented_params(app, statu
'\n' '\n'
' * ****kwargs** (*int*) -- Extra arguments.\n' ' * ****kwargs** (*int*) -- Extra arguments.\n'
) )
@pytest.mark.sphinx('html', testroot='ext-napoleon-paramtype', freshenv=True)
def test_napoleon_keyword_and_paramtype(app, tmp_path):
inv_file = tmp_path / 'objects.inv'
inv_file.write_bytes(b'''\
# Sphinx inventory version 2
# Project: Intersphinx Test
# Version: 42
# The remainder of this file is compressed using zlib.
''' + zlib.compress(b'''\
None py:data 1 none.html -
list py:class 1 list.html -
int py:class 1 int.html -
''')) # NoQA: W291
app.config.intersphinx_mapping = {'python': ('127.0.0.1:5555', str(inv_file))}
normalize_intersphinx_mapping(app, app.config)
load_mappings(app)
app.build(force_all=True)
buffer = (app.outdir / 'index.html').read_bytes()
etree = HTMLParser(namespaceHTMLElements=False).parse(buffer)
for name, typename in product(('keyword', 'kwarg', 'kwparam'), ('paramtype', 'kwtype')):
param = f'{name}_{typename}'
li_ = list(etree.findall(f'.//li/p/strong[.="{param}"]/../..'))
assert len(li_) == 1
li = li_[0]
text = li.text or ''.join(li.itertext())
assert text == f'{param} (list[int]) \u2013 some param'
a_ = list(li.findall('.//a[@class="reference external"]'))
assert len(a_) == 2
for a, uri in zip(a_, ('list.html', 'int.html')):
assert a.attrib['href'] == f'127.0.0.1:5555/{uri}'
assert a.attrib['title'] == '(in Intersphinx Test v42)'