Skip to content

Commit 83442be

Browse files
authored
Group the type alias cross-referencing test with Python domain tests (#14021)
1 parent fcc9ca0 commit 83442be

File tree

10 files changed

+220
-137
lines changed

10 files changed

+220
-137
lines changed

tests/roots/test-domain-py-xref-type-alias/conf.py

Whitespace-only changes.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
Type Alias Cross-Reference Test
2+
===============================
3+
4+
This tests that type aliases in function signatures can be cross-referenced properly.
5+
6+
7+
.. py:module:: alias_module
8+
9+
Module to test type alias cross-reference resolution.
10+
11+
12+
.. py:data:: Handler
13+
:module: alias_module
14+
15+
A generic type alias for error handlers
16+
17+
alias of :py:class:`type`\ [:py:class:`Exception`]
18+
19+
20+
.. py:type:: HandlerType
21+
:module: alias_module
22+
:canonical: type[Exception]
23+
24+
A PEP 695 type alias for error handlers
25+
26+
27+
.. py:data:: pathlike
28+
:module: alias_module
29+
:value: str | pathlib.Path
30+
31+
Any type of path
32+
33+
34+
.. py:function:: process_error(handler: Handler, other: ~alias_module.HandlerType) -> str
35+
:module: alias_module
36+
37+
Process an error with a custom handler type.
38+
39+
Tests generic type alias cross-reference resolution.
40+
41+
42+
.. py:function:: read_file(path: pathlike) -> bytes
43+
:module: alias_module
44+
45+
Read a file and return its contents.
46+
47+
Tests Union type alias cross-reference resolution.

tests/roots/test-ext-autodoc-type-alias-xref/alias_module.py

Lines changed: 0 additions & 33 deletions
This file was deleted.

tests/roots/test-ext-autodoc-type-alias-xref/conf.py

Lines changed: 0 additions & 11 deletions
This file was deleted.

tests/roots/test-ext-autodoc-type-alias-xref/index.rst

Lines changed: 0 additions & 7 deletions
This file was deleted.

tests/roots/test-ext-autodoc/conf.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,10 @@
99
'dummy',
1010
]
1111

12+
autodoc_type_aliases = {
13+
'buffer_like': 'buffer_like',
14+
'pathlike': 'pathlike',
15+
'Handler': 'Handler',
16+
}
17+
1218
nitpicky = True

tests/roots/test-ext-autodoc/target/pep695.py

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,19 @@
1+
from __future__ import annotations
2+
3+
import pathlib
14
from typing import NewType, TypeAliasType
25

36
import typing_extensions
47

8+
#: Some buffer-like object
9+
buffer_like = bytes | bytearray | memoryview
10+
11+
#: Any type of path
12+
pathlike = str | pathlib.Path
13+
14+
#: A generic type alias
15+
Handler = type[Exception]
16+
517

618
class Foo:
719
"""This is class Foo."""
@@ -10,10 +22,13 @@ class Foo:
1022
type Pep695Alias = Foo
1123
"""This is PEP695 type alias."""
1224

13-
TypeAliasTypeExplicit = TypeAliasType('TypeAliasTypeExplicit', Foo) # noqa: UP040
25+
TypeAliasTypeExplicit = TypeAliasType('TypeAliasTypeExplicit', Foo) # NoQA: UP040
1426
"""This is an explicitly constructed typing.TypeAlias."""
1527

16-
TypeAliasTypeExtension = typing_extensions.TypeAliasType('TypeAliasTypeExtension', Foo) # noqa: UP040
28+
HandlerTypeAliasType = TypeAliasType('HandlerTypeAliasType', type[Exception]) # NoQA: UP040
29+
"""This is an explicitly constructed generic alias typing.TypeAlias."""
30+
31+
TypeAliasTypeExtension = typing_extensions.TypeAliasType('TypeAliasTypeExtension', Foo) # NoQA: UP040
1732
"""This is an explicitly constructed typing_extensions.TypeAlias."""
1833

1934
#: This is PEP695 complex type alias with doc comment.
@@ -32,3 +47,24 @@ class Foo:
3247
def ret_pep695(a: Pep695Alias) -> Pep695Alias:
3348
"""This fn accepts and returns PEP695 alias."""
3449
...
50+
51+
52+
def read_file(path: pathlike) -> bytes:
53+
"""Read a file and return its contents.
54+
55+
Tests Union type alias cross-reference resolution.
56+
"""
57+
58+
59+
def process_error(handler: Handler, other: HandlerTypeAliasType) -> str:
60+
"""Process an error with a custom handler type.
61+
62+
Tests generic type alias cross-reference resolution.
63+
"""
64+
65+
66+
def buffer_len(data: buffer_like) -> int:
67+
"""Return length of a buffer-like object.
68+
69+
Tests Union type alias cross-reference resolution.
70+
"""

tests/test_domains/test_domain_py.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
if TYPE_CHECKING:
4343
from sphinx.application import Sphinx
4444
from sphinx.environment import BuildEnvironment
45+
from sphinx.testing.util import SphinxTestApp
4546

4647

4748
def parse(sig: str, *, env: BuildEnvironment) -> str:
@@ -1819,3 +1820,77 @@ def test_pytype_canonical(app):
18191820

18201821
doctree = restructuredtext.parse(app, text)
18211822
assert not app.warning.getvalue()
1823+
1824+
1825+
@pytest.mark.sphinx('html', testroot='domain-py-xref-type-alias')
1826+
def test_type_alias_xref_resolution(app: SphinxTestApp) -> None:
1827+
"""Test that type aliases in function signatures can be cross-referenced.
1828+
1829+
This tests the fix for issue https://github.com/sphinx-doc/sphinx/issues/10785
1830+
where type aliases documented as :py:data: but referenced as :py:class: in
1831+
function signatures would not resolve properly.
1832+
1833+
Tests both a Union type alias and a generic type alias to ensure our
1834+
domain fallback mechanism works for various type alias patterns.
1835+
"""
1836+
app.config.nitpicky = True
1837+
app.build()
1838+
1839+
# In nitpicky mode, check that no warnings were generated for type alias cross-references
1840+
warnings_text = app.warning.getvalue()
1841+
assert 'py:class reference target not found: pathlike' not in warnings_text, (
1842+
f'Type alias cross-reference failed in nitpicky mode. Warnings: {warnings_text}'
1843+
)
1844+
assert 'py:class reference target not found: Handler' not in warnings_text, (
1845+
f'Type alias cross-reference failed for Handler. Warnings: {warnings_text}'
1846+
)
1847+
1848+
# Core functionality test: Verify type alias links are generated in function signatures
1849+
html_content = (app.outdir / 'index.html').read_text(encoding='utf8')
1850+
1851+
# Both type aliases should be documented and have anchors
1852+
assert 'id="alias_module.pathlike"' in html_content, (
1853+
'pathlike type alias definition anchor not found in HTML'
1854+
)
1855+
assert 'id="alias_module.Handler"' in html_content, (
1856+
'Handler type alias definition anchor not found in HTML'
1857+
)
1858+
1859+
# The critical test: type aliases in function signatures should be clickable links
1860+
# This tests the original issue - function signature type annotations should resolve
1861+
assert (
1862+
'<a class="reference internal" href="#alias_module.pathlike"' in html_content
1863+
), 'pathlike type alias not linked in function signature'
1864+
1865+
assert (
1866+
'<a class="reference internal" href="#alias_module.Handler"' in html_content
1867+
), 'Handler type alias not linked in function signature'
1868+
1869+
# Verify the links are specifically in the function signature contexts
1870+
# Test pathlike in read_file function signature
1871+
read_file_match = re.search(
1872+
r'<span class="pre">read_file</span>.*?</dt>', html_content, re.DOTALL
1873+
)
1874+
assert read_file_match is not None, 'Could not find read_file function signature'
1875+
read_file_signature = read_file_match.group(0)
1876+
assert (
1877+
'<a class="reference internal" href="#alias_module.pathlike"'
1878+
in read_file_signature
1879+
), 'pathlike type alias link not found in read_file function signature'
1880+
1881+
# Test Handler in process_error function signature
1882+
process_error_match = re.search(
1883+
r'<span class="pre">process_error</span>.*?</dt>', html_content, re.DOTALL
1884+
)
1885+
assert process_error_match is not None, (
1886+
'Could not find process_error function signature'
1887+
)
1888+
process_error_signature = process_error_match.group(0)
1889+
assert (
1890+
'<a class="reference internal" href="#alias_module.Handler"'
1891+
in process_error_signature
1892+
), 'Handler type alias link not found in process_error function signature'
1893+
assert (
1894+
'<a class="reference internal" href="#alias_module.HandlerType"'
1895+
in process_error_signature
1896+
), 'HandlerType type alias link not found in process_error function signature'

tests/test_ext_autodoc/test_ext_autodoc.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import itertools
1010
import logging
11+
import pathlib
1112
import sys
1213
from typing import TYPE_CHECKING
1314
from warnings import catch_warnings
@@ -2607,6 +2608,21 @@ def test_autodoc_pep695_type_alias(app):
26072608
' This is class Foo.',
26082609
'',
26092610
'',
2611+
'.. py:data:: Handler',
2612+
' :module: target.pep695',
2613+
'',
2614+
' A generic type alias',
2615+
'',
2616+
' alias of :py:class:`type`\\ [:py:class:`Exception`]',
2617+
'',
2618+
'',
2619+
'.. py:type:: HandlerTypeAliasType',
2620+
' :module: target.pep695',
2621+
' :canonical: type[Exception]',
2622+
'',
2623+
' This is an explicitly constructed generic alias typing.TypeAlias.',
2624+
'',
2625+
'',
26102626
'.. py:type:: Pep695Alias',
26112627
' :module: target.pep695',
26122628
' :canonical: ~target.pep695.Foo',
@@ -2649,6 +2665,44 @@ def test_autodoc_pep695_type_alias(app):
26492665
' This is an explicitly constructed typing_extensions.TypeAlias.',
26502666
'',
26512667
'',
2668+
'.. py:function:: buffer_len(data: buffer_like) -> int',
2669+
' :module: target.pep695',
2670+
'',
2671+
' Return length of a buffer-like object.',
2672+
'',
2673+
' Tests Union type alias cross-reference resolution.',
2674+
'',
2675+
'',
2676+
'.. py:data:: buffer_like',
2677+
' :module: target.pep695',
2678+
' :value: bytes | bytearray | memoryview',
2679+
'',
2680+
' Some buffer-like object',
2681+
'',
2682+
'',
2683+
'.. py:data:: pathlike',
2684+
' :module: target.pep695',
2685+
f' :value: str | {pathlib.Path.__module__}.Path',
2686+
'',
2687+
' Any type of path',
2688+
'',
2689+
'',
2690+
'.. py:function:: process_error(handler: Handler, other: ~target.pep695.HandlerTypeAliasType) -> str',
2691+
' :module: target.pep695',
2692+
'',
2693+
' Process an error with a custom handler type.',
2694+
'',
2695+
' Tests generic type alias cross-reference resolution.',
2696+
'',
2697+
'',
2698+
'.. py:function:: read_file(path: pathlike) -> bytes',
2699+
' :module: target.pep695',
2700+
'',
2701+
' Read a file and return its contents.',
2702+
'',
2703+
' Tests Union type alias cross-reference resolution.',
2704+
'',
2705+
'',
26522706
'.. py:function:: ret_pep695(a: ~target.pep695.Pep695Alias) -> ~target.pep695.Pep695Alias',
26532707
' :module: target.pep695',
26542708
'',

0 commit comments

Comments
 (0)