summaryrefslogtreecommitdiff
path: root/tests/test_util_typing.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_util_typing.py')
-rw-r--r--tests/test_util_typing.py118
1 files changed, 108 insertions, 10 deletions
diff --git a/tests/test_util_typing.py b/tests/test_util_typing.py
index 41d2a19c2..9da505814 100644
--- a/tests/test_util_typing.py
+++ b/tests/test_util_typing.py
@@ -4,17 +4,19 @@
Tests util.typing functions.
- :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
+ :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import sys
from numbers import Integral
-from typing import Any, Dict, List, TypeVar, Union, Callable, Tuple, Optional, Generic
+from struct import Struct
+from typing import (Any, Callable, Dict, Generator, List, NewType, Optional, Tuple, TypeVar,
+ Union)
import pytest
-from sphinx.util.typing import stringify
+from sphinx.util.typing import restify, stringify
class MyClass1:
@@ -24,17 +26,107 @@ class MyClass1:
class MyClass2(MyClass1):
__qualname__ = '<MyClass2>'
+
T = TypeVar('T')
+MyInt = NewType('MyInt', int)
+
class MyList(List[T]):
pass
+class BrokenType:
+ __args__ = int
+
+
+def test_restify():
+ assert restify(int) == ":class:`int`"
+ assert restify(str) == ":class:`str`"
+ assert restify(None) == ":obj:`None`"
+ assert restify(Integral) == ":class:`numbers.Integral`"
+ assert restify(Struct) == ":class:`struct.Struct`"
+ assert restify(Any) == ":obj:`Any`"
+
+
+def test_restify_type_hints_containers():
+ assert restify(List) == ":class:`List`"
+ assert restify(Dict) == ":class:`Dict`"
+ assert restify(List[int]) == ":class:`List`\\ [:class:`int`]"
+ assert restify(List[str]) == ":class:`List`\\ [:class:`str`]"
+ assert restify(Dict[str, float]) == ":class:`Dict`\\ [:class:`str`, :class:`float`]"
+ assert restify(Tuple[str, str, str]) == ":class:`Tuple`\\ [:class:`str`, :class:`str`, :class:`str`]"
+ assert restify(Tuple[str, ...]) == ":class:`Tuple`\\ [:class:`str`, ...]"
+ assert restify(List[Dict[str, Tuple]]) == ":class:`List`\\ [:class:`Dict`\\ [:class:`str`, :class:`Tuple`]]"
+ assert restify(MyList[Tuple[int, int]]) == ":class:`tests.test_util_typing.MyList`\\ [:class:`Tuple`\\ [:class:`int`, :class:`int`]]"
+ assert restify(Generator[None, None, None]) == ":class:`Generator`\\ [:obj:`None`, :obj:`None`, :obj:`None`]"
+
+
+def test_restify_type_hints_Callable():
+ assert restify(Callable) == ":class:`Callable`"
+
+ if sys.version_info >= (3, 7):
+ assert restify(Callable[[str], int]) == ":class:`Callable`\\ [[:class:`str`], :class:`int`]"
+ assert restify(Callable[..., int]) == ":class:`Callable`\\ [[...], :class:`int`]"
+ else:
+ assert restify(Callable[[str], int]) == ":class:`Callable`\\ [:class:`str`, :class:`int`]"
+ assert restify(Callable[..., int]) == ":class:`Callable`\\ [..., :class:`int`]"
+
+
+def test_restify_type_hints_Union():
+ assert restify(Optional[int]) == ":obj:`Optional`\\ [:class:`int`]"
+ assert restify(Union[str, None]) == ":obj:`Optional`\\ [:class:`str`]"
+ assert restify(Union[int, str]) == ":obj:`Union`\\ [:class:`int`, :class:`str`]"
+
+ if sys.version_info >= (3, 7):
+ assert restify(Union[int, Integral]) == ":obj:`Union`\\ [:class:`int`, :class:`numbers.Integral`]"
+ assert (restify(Union[MyClass1, MyClass2]) ==
+ ":obj:`Union`\\ [:class:`tests.test_util_typing.MyClass1`, :class:`tests.test_util_typing.<MyClass2>`]")
+ else:
+ assert restify(Union[int, Integral]) == ":class:`numbers.Integral`"
+ assert restify(Union[MyClass1, MyClass2]) == ":class:`tests.test_util_typing.MyClass1`"
+
+
+@pytest.mark.skipif(sys.version_info < (3, 7), reason='python 3.7+ is required.')
+def test_restify_type_hints_typevars():
+ T = TypeVar('T')
+ T_co = TypeVar('T_co', covariant=True)
+ T_contra = TypeVar('T_contra', contravariant=True)
+
+ assert restify(T) == ":obj:`tests.test_util_typing.T`"
+ assert restify(T_co) == ":obj:`tests.test_util_typing.T_co`"
+ assert restify(T_contra) == ":obj:`tests.test_util_typing.T_contra`"
+ assert restify(List[T]) == ":class:`List`\\ [:obj:`tests.test_util_typing.T`]"
+ assert restify(MyInt) == ":class:`MyInt`"
+
+
+def test_restify_type_hints_custom_class():
+ assert restify(MyClass1) == ":class:`tests.test_util_typing.MyClass1`"
+ assert restify(MyClass2) == ":class:`tests.test_util_typing.<MyClass2>`"
+
+
+def test_restify_type_hints_alias():
+ MyStr = str
+ MyTuple = Tuple[str, str]
+ assert restify(MyStr) == ":class:`str`"
+ assert restify(MyTuple) == ":class:`Tuple`\\ [:class:`str`, :class:`str`]" # type: ignore
+
+
+@pytest.mark.skipif(sys.version_info < (3, 7), reason='python 3.7+ is required.')
+def test_restify_type_ForwardRef():
+ from typing import ForwardRef # type: ignore
+ assert restify(ForwardRef("myint")) == ":class:`myint`"
+
+
+def test_restify_broken_type_hints():
+ assert restify(BrokenType) == ':class:`tests.test_util_typing.BrokenType`'
+
+
def test_stringify():
assert stringify(int) == "int"
assert stringify(str) == "str"
assert stringify(None) == "None"
assert stringify(Integral) == "numbers.Integral"
+ assert restify(Struct) == ":class:`struct.Struct`"
assert stringify(Any) == "Any"
@@ -47,13 +139,14 @@ def test_stringify_type_hints_containers():
assert stringify(Tuple[str, str, str]) == "Tuple[str, str, str]"
assert stringify(Tuple[str, ...]) == "Tuple[str, ...]"
assert stringify(List[Dict[str, Tuple]]) == "List[Dict[str, Tuple]]"
- assert stringify(MyList[Tuple[int, int]]) == "test_util_typing.MyList[Tuple[int, int]]"
+ assert stringify(MyList[Tuple[int, int]]) == "tests.test_util_typing.MyList[Tuple[int, int]]"
+ assert stringify(Generator[None, None, None]) == "Generator[None, None, None]"
@pytest.mark.skipif(sys.version_info < (3, 9), reason='python 3.9+ is required.')
def test_stringify_Annotated():
- from typing import Annotated
- assert stringify(Annotated[str, "foo", "bar"]) == "str"
+ from typing import Annotated # type: ignore
+ assert stringify(Annotated[str, "foo", "bar"]) == "str" # NOQA
def test_stringify_type_hints_string():
@@ -83,10 +176,10 @@ def test_stringify_type_hints_Union():
if sys.version_info >= (3, 7):
assert stringify(Union[int, Integral]) == "Union[int, numbers.Integral]"
assert (stringify(Union[MyClass1, MyClass2]) ==
- "Union[test_util_typing.MyClass1, test_util_typing.<MyClass2>]")
+ "Union[tests.test_util_typing.MyClass1, tests.test_util_typing.<MyClass2>]")
else:
assert stringify(Union[int, Integral]) == "numbers.Integral"
- assert stringify(Union[MyClass1, MyClass2]) == "test_util_typing.MyClass1"
+ assert stringify(Union[MyClass1, MyClass2]) == "tests.test_util_typing.MyClass1"
def test_stringify_type_hints_typevars():
@@ -98,11 +191,12 @@ def test_stringify_type_hints_typevars():
assert stringify(T_co) == "T_co"
assert stringify(T_contra) == "T_contra"
assert stringify(List[T]) == "List[T]"
+ assert stringify(MyInt) == "MyInt"
def test_stringify_type_hints_custom_class():
- assert stringify(MyClass1) == "test_util_typing.MyClass1"
- assert stringify(MyClass2) == "test_util_typing.<MyClass2>"
+ assert stringify(MyClass1) == "tests.test_util_typing.MyClass1"
+ assert stringify(MyClass2) == "tests.test_util_typing.<MyClass2>"
def test_stringify_type_hints_alias():
@@ -110,3 +204,7 @@ def test_stringify_type_hints_alias():
MyTuple = Tuple[str, str]
assert stringify(MyStr) == "str"
assert stringify(MyTuple) == "Tuple[str, str]" # type: ignore
+
+
+def test_stringify_broken_type_hints():
+ assert stringify(BrokenType) == 'tests.test_util_typing.BrokenType'