mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Properly format `collections.abc.Callable` (#12314)
This commit is contained in:
@@ -178,7 +178,7 @@ def _is_annotated_form(obj: Any) -> TypeGuard[Annotated[Any, ...]]:
|
||||
return typing.get_origin(obj) is Annotated or str(obj).startswith('typing.Annotated')
|
||||
|
||||
|
||||
def _get_typing_internal_name(obj: Any) -> str | None:
|
||||
def _typing_internal_name(obj: Any) -> str | None:
|
||||
if sys.version_info[:2] >= (3, 10):
|
||||
return obj.__name__
|
||||
return getattr(obj, '_name', None)
|
||||
@@ -252,7 +252,7 @@ def restify(cls: Any, mode: _RestifyMode = 'fully-qualified-except-typing') -> s
|
||||
# *cls* is defined in ``typing``, and thus ``__args__`` must exist
|
||||
return ' | '.join(restify(a, mode) for a in cls.__args__)
|
||||
elif inspect.isgenericalias(cls):
|
||||
cls_name = _get_typing_internal_name(cls)
|
||||
cls_name = _typing_internal_name(cls)
|
||||
|
||||
if isinstance(cls.__origin__, typing._SpecialForm):
|
||||
# ClassVar; Concatenate; Final; Literal; Unpack; TypeGuard
|
||||
@@ -271,12 +271,15 @@ def restify(cls: Any, mode: _RestifyMode = 'fully-qualified-except-typing') -> s
|
||||
return text
|
||||
|
||||
# Callable has special formatting
|
||||
if cls_module_is_typing and _get_typing_internal_name(cls) == 'Callable':
|
||||
if (
|
||||
(cls_module_is_typing and _typing_internal_name(cls) == 'Callable')
|
||||
or (cls.__module__ == 'collections.abc' and cls.__name__ == 'Callable')
|
||||
):
|
||||
args = ', '.join(restify(a, mode) for a in __args__[:-1])
|
||||
returns = restify(__args__[-1], mode)
|
||||
return fr'{text}\ [[{args}], {returns}]'
|
||||
|
||||
if cls_module_is_typing and _get_typing_internal_name(cls.__origin__) == 'Literal':
|
||||
if cls_module_is_typing and _typing_internal_name(cls.__origin__) == 'Literal':
|
||||
args = ', '.join(_format_literal_arg_restify(a, mode=mode)
|
||||
for a in cls.__args__)
|
||||
return fr'{text}\ [{args}]'
|
||||
@@ -285,7 +288,7 @@ def restify(cls: Any, mode: _RestifyMode = 'fully-qualified-except-typing') -> s
|
||||
args = ', '.join(restify(a, mode) for a in __args__)
|
||||
return fr'{text}\ [{args}]'
|
||||
elif isinstance(cls, typing._SpecialForm):
|
||||
cls_name = _get_typing_internal_name(cls)
|
||||
cls_name = _typing_internal_name(cls)
|
||||
return f':py:obj:`~{cls.__module__}.{cls_name}`'
|
||||
elif sys.version_info[:2] >= (3, 11) and cls is typing.Any:
|
||||
# handle bpo-46998
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
"""Tests util.typing functions."""
|
||||
|
||||
import sys
|
||||
import typing as t
|
||||
from collections import abc
|
||||
from contextvars import Context, ContextVar, Token
|
||||
from enum import Enum
|
||||
from numbers import Integral
|
||||
@@ -29,10 +31,7 @@ from types import (
|
||||
)
|
||||
from typing import (
|
||||
Any,
|
||||
Callable,
|
||||
Dict,
|
||||
Generator,
|
||||
Iterator,
|
||||
List,
|
||||
NewType,
|
||||
Optional,
|
||||
@@ -173,20 +172,29 @@ def test_restify_type_hints_containers():
|
||||
assert restify(MyList[Tuple[int, int]]) == (":py:class:`tests.test_util.test_util_typing.MyList`\\ "
|
||||
"[:py:class:`~typing.Tuple`\\ "
|
||||
"[:py:class:`int`, :py:class:`int`]]")
|
||||
assert restify(Generator[None, None, None]) == (":py:class:`~typing.Generator`\\ "
|
||||
"[:py:obj:`None`, :py:obj:`None`, "
|
||||
":py:obj:`None`]")
|
||||
assert restify(Iterator[None]) == (":py:class:`~typing.Iterator`\\ "
|
||||
"[:py:obj:`None`]")
|
||||
assert restify(t.Generator[None, None, None]) == (":py:class:`~typing.Generator`\\ "
|
||||
"[:py:obj:`None`, :py:obj:`None`, "
|
||||
":py:obj:`None`]")
|
||||
assert restify(abc.Generator[None, None, None]) == (":py:class:`collections.abc.Generator`\\ "
|
||||
"[:py:obj:`None`, :py:obj:`None`, "
|
||||
":py:obj:`None`]")
|
||||
assert restify(t.Iterator[None]) == (":py:class:`~typing.Iterator`\\ "
|
||||
"[:py:obj:`None`]")
|
||||
assert restify(abc.Iterator[None]) == (":py:class:`collections.abc.Iterator`\\ "
|
||||
"[:py:obj:`None`]")
|
||||
|
||||
|
||||
def test_restify_type_hints_Callable():
|
||||
assert restify(Callable) == ":py:class:`~typing.Callable`"
|
||||
|
||||
assert restify(Callable[[str], int]) == (":py:class:`~typing.Callable`\\ "
|
||||
"[[:py:class:`str`], :py:class:`int`]")
|
||||
assert restify(Callable[..., int]) == (":py:class:`~typing.Callable`\\ "
|
||||
"[[...], :py:class:`int`]")
|
||||
assert restify(t.Callable) == ":py:class:`~typing.Callable`"
|
||||
assert restify(t.Callable[[str], int]) == (":py:class:`~typing.Callable`\\ "
|
||||
"[[:py:class:`str`], :py:class:`int`]")
|
||||
assert restify(t.Callable[..., int]) == (":py:class:`~typing.Callable`\\ "
|
||||
"[[...], :py:class:`int`]")
|
||||
assert restify(abc.Callable) == ":py:class:`collections.abc.Callable`"
|
||||
assert restify(abc.Callable[[str], int]) == (":py:class:`collections.abc.Callable`\\ "
|
||||
"[[:py:class:`str`], :py:class:`int`]")
|
||||
assert restify(abc.Callable[..., int]) == (":py:class:`collections.abc.Callable`\\ "
|
||||
"[[...], :py:class:`int`]")
|
||||
|
||||
|
||||
def test_restify_type_hints_Union():
|
||||
@@ -409,13 +417,21 @@ def test_stringify_type_hints_containers():
|
||||
assert stringify_annotation(MyList[Tuple[int, int]], "fully-qualified") == "tests.test_util.test_util_typing.MyList[typing.Tuple[int, int]]"
|
||||
assert stringify_annotation(MyList[Tuple[int, int]], "smart") == "~tests.test_util.test_util_typing.MyList[~typing.Tuple[int, int]]"
|
||||
|
||||
assert stringify_annotation(Generator[None, None, None], 'fully-qualified-except-typing') == "Generator[None, None, None]"
|
||||
assert stringify_annotation(Generator[None, None, None], "fully-qualified") == "typing.Generator[None, None, None]"
|
||||
assert stringify_annotation(Generator[None, None, None], "smart") == "~typing.Generator[None, None, None]"
|
||||
assert stringify_annotation(t.Generator[None, None, None], 'fully-qualified-except-typing') == "Generator[None, None, None]"
|
||||
assert stringify_annotation(t.Generator[None, None, None], "fully-qualified") == "typing.Generator[None, None, None]"
|
||||
assert stringify_annotation(t.Generator[None, None, None], "smart") == "~typing.Generator[None, None, None]"
|
||||
|
||||
assert stringify_annotation(Iterator[None], 'fully-qualified-except-typing') == "Iterator[None]"
|
||||
assert stringify_annotation(Iterator[None], "fully-qualified") == "typing.Iterator[None]"
|
||||
assert stringify_annotation(Iterator[None], "smart") == "~typing.Iterator[None]"
|
||||
assert stringify_annotation(abc.Generator[None, None, None], 'fully-qualified-except-typing') == "collections.abc.Generator[None, None, None]"
|
||||
assert stringify_annotation(abc.Generator[None, None, None], "fully-qualified") == "collections.abc.Generator[None, None, None]"
|
||||
assert stringify_annotation(abc.Generator[None, None, None], "smart") == "~collections.abc.Generator[None, None, None]"
|
||||
|
||||
assert stringify_annotation(t.Iterator[None], 'fully-qualified-except-typing') == "Iterator[None]"
|
||||
assert stringify_annotation(t.Iterator[None], "fully-qualified") == "typing.Iterator[None]"
|
||||
assert stringify_annotation(t.Iterator[None], "smart") == "~typing.Iterator[None]"
|
||||
|
||||
assert stringify_annotation(abc.Iterator[None], 'fully-qualified-except-typing') == "collections.abc.Iterator[None]"
|
||||
assert stringify_annotation(abc.Iterator[None], "fully-qualified") == "collections.abc.Iterator[None]"
|
||||
assert stringify_annotation(abc.Iterator[None], "smart") == "~collections.abc.Iterator[None]"
|
||||
|
||||
|
||||
def test_stringify_type_hints_pep_585():
|
||||
@@ -489,17 +505,29 @@ def test_stringify_type_hints_string():
|
||||
|
||||
|
||||
def test_stringify_type_hints_Callable():
|
||||
assert stringify_annotation(Callable, 'fully-qualified-except-typing') == "Callable"
|
||||
assert stringify_annotation(Callable, "fully-qualified") == "typing.Callable"
|
||||
assert stringify_annotation(Callable, "smart") == "~typing.Callable"
|
||||
assert stringify_annotation(t.Callable, 'fully-qualified-except-typing') == "Callable"
|
||||
assert stringify_annotation(t.Callable, "fully-qualified") == "typing.Callable"
|
||||
assert stringify_annotation(t.Callable, "smart") == "~typing.Callable"
|
||||
|
||||
assert stringify_annotation(Callable[[str], int], 'fully-qualified-except-typing') == "Callable[[str], int]"
|
||||
assert stringify_annotation(Callable[[str], int], "fully-qualified") == "typing.Callable[[str], int]"
|
||||
assert stringify_annotation(Callable[[str], int], "smart") == "~typing.Callable[[str], int]"
|
||||
assert stringify_annotation(t.Callable[[str], int], 'fully-qualified-except-typing') == "Callable[[str], int]"
|
||||
assert stringify_annotation(t.Callable[[str], int], "fully-qualified") == "typing.Callable[[str], int]"
|
||||
assert stringify_annotation(t.Callable[[str], int], "smart") == "~typing.Callable[[str], int]"
|
||||
|
||||
assert stringify_annotation(Callable[..., int], 'fully-qualified-except-typing') == "Callable[[...], int]"
|
||||
assert stringify_annotation(Callable[..., int], "fully-qualified") == "typing.Callable[[...], int]"
|
||||
assert stringify_annotation(Callable[..., int], "smart") == "~typing.Callable[[...], int]"
|
||||
assert stringify_annotation(t.Callable[..., int], 'fully-qualified-except-typing') == "Callable[[...], int]"
|
||||
assert stringify_annotation(t.Callable[..., int], "fully-qualified") == "typing.Callable[[...], int]"
|
||||
assert stringify_annotation(t.Callable[..., int], "smart") == "~typing.Callable[[...], int]"
|
||||
|
||||
assert stringify_annotation(abc.Callable, 'fully-qualified-except-typing') == "collections.abc.Callable"
|
||||
assert stringify_annotation(abc.Callable, "fully-qualified") == "collections.abc.Callable"
|
||||
assert stringify_annotation(abc.Callable, "smart") == "~collections.abc.Callable"
|
||||
|
||||
assert stringify_annotation(abc.Callable[[str], int], 'fully-qualified-except-typing') == "collections.abc.Callable[[str], int]"
|
||||
assert stringify_annotation(abc.Callable[[str], int], "fully-qualified") == "collections.abc.Callable[[str], int]"
|
||||
assert stringify_annotation(abc.Callable[[str], int], "smart") == "~collections.abc.Callable[[str], int]"
|
||||
|
||||
assert stringify_annotation(abc.Callable[..., int], 'fully-qualified-except-typing') == "collections.abc.Callable[[...], int]"
|
||||
assert stringify_annotation(abc.Callable[..., int], "fully-qualified") == "collections.abc.Callable[[...], int]"
|
||||
assert stringify_annotation(abc.Callable[..., int], "smart") == "~collections.abc.Callable[[...], int]"
|
||||
|
||||
|
||||
def test_stringify_type_hints_Union():
|
||||
|
||||
Reference in New Issue
Block a user