diff --git a/CHANGES b/CHANGES index 9e8bc1151e7..a247f7eb292 100644 --- a/CHANGES +++ b/CHANGES @@ -16,6 +16,9 @@ Features added Bugs fixed ---------- +* #9630: autodoc: Failed to build cross references if :confval:`primary_domain` + is not 'py' + Testing -------- diff --git a/sphinx/util/typing.py b/sphinx/util/typing.py index 8912de8cdc0..7380f478392 100644 --- a/sphinx/util/typing.py +++ b/sphinx/util/typing.py @@ -110,18 +110,18 @@ def restify(cls: Optional[Type]) -> str: try: if cls is None or cls is NoneType: - return ':obj:`None`' + return ':py:obj:`None`' elif cls is Ellipsis: return '...' elif cls in INVALID_BUILTIN_CLASSES: - return ':class:`%s`' % INVALID_BUILTIN_CLASSES[cls] + return ':py:class:`%s`' % INVALID_BUILTIN_CLASSES[cls] elif inspect.isNewType(cls): if sys.version_info > (3, 10): # newtypes have correct module info since Python 3.10+ print(cls, type(cls), dir(cls)) - return ':class:`%s.%s`' % (cls.__module__, cls.__name__) + return ':py:class:`%s.%s`' % (cls.__module__, cls.__name__) else: - return ':class:`%s`' % cls.__name__ + return ':py:class:`%s`' % cls.__name__ elif UnionType and isinstance(cls, UnionType): if len(cls.__args__) > 1 and None in cls.__args__: args = ' | '.join(restify(a) for a in cls.__args__ if a) @@ -130,12 +130,12 @@ def restify(cls: Optional[Type]) -> str: return ' | '.join(restify(a) for a in cls.__args__) elif cls.__module__ in ('__builtin__', 'builtins'): if hasattr(cls, '__args__'): - return ':class:`%s`\\ [%s]' % ( + return ':py:class:`%s`\\ [%s]' % ( cls.__name__, ', '.join(restify(arg) for arg in cls.__args__), ) else: - return ':class:`%s`' % cls.__name__ + return ':py:class:`%s`' % cls.__name__ else: if sys.version_info >= (3, 7): # py37+ return _restify_py37(cls) @@ -155,20 +155,20 @@ def _restify_py37(cls: Optional[Type]) -> str: if len(cls.__args__) > 1 and cls.__args__[-1] is NoneType: if len(cls.__args__) > 2: args = ', '.join(restify(a) for a in cls.__args__[:-1]) - return ':obj:`~typing.Optional`\\ [:obj:`~typing.Union`\\ [%s]]' % args + return ':py:obj:`~typing.Optional`\\ [:obj:`~typing.Union`\\ [%s]]' % args else: - return ':obj:`~typing.Optional`\\ [%s]' % restify(cls.__args__[0]) + return ':py:obj:`~typing.Optional`\\ [%s]' % restify(cls.__args__[0]) else: args = ', '.join(restify(a) for a in cls.__args__) - return ':obj:`~typing.Union`\\ [%s]' % args + return ':py:obj:`~typing.Union`\\ [%s]' % args elif inspect.isgenericalias(cls): if isinstance(cls.__origin__, typing._SpecialForm): text = restify(cls.__origin__) # type: ignore elif getattr(cls, '_name', None): if cls.__module__ == 'typing': - text = ':class:`~%s.%s`' % (cls.__module__, cls._name) + text = ':py:class:`~%s.%s`' % (cls.__module__, cls._name) else: - text = ':class:`%s.%s`' % (cls.__module__, cls._name) + text = ':py:class:`%s.%s`' % (cls.__module__, cls._name) else: text = restify(cls.__origin__) @@ -188,20 +188,20 @@ def _restify_py37(cls: Optional[Type]) -> str: return text elif isinstance(cls, typing._SpecialForm): - return ':obj:`~%s.%s`' % (cls.__module__, cls._name) + return ':py:obj:`~%s.%s`' % (cls.__module__, cls._name) elif hasattr(cls, '__qualname__'): if cls.__module__ == 'typing': - return ':class:`~%s.%s`' % (cls.__module__, cls.__qualname__) + return ':py:class:`~%s.%s`' % (cls.__module__, cls.__qualname__) else: - return ':class:`%s.%s`' % (cls.__module__, cls.__qualname__) + return ':py:class:`%s.%s`' % (cls.__module__, cls.__qualname__) elif isinstance(cls, ForwardRef): - return ':class:`%s`' % cls.__forward_arg__ + return ':py:class:`%s`' % cls.__forward_arg__ else: # not a class (ex. TypeVar) if cls.__module__ == 'typing': - return ':obj:`~%s.%s`' % (cls.__module__, cls.__name__) + return ':py:obj:`~%s.%s`' % (cls.__module__, cls.__name__) else: - return ':obj:`%s.%s`' % (cls.__module__, cls.__name__) + return ':py:obj:`%s.%s`' % (cls.__module__, cls.__name__) def _restify_py36(cls: Optional[Type]) -> str: @@ -225,9 +225,9 @@ def _restify_py36(cls: Optional[Type]) -> str: if (isinstance(cls, typing.TupleMeta) and # type: ignore not hasattr(cls, '__tuple_params__')): if module == 'typing': - reftext = ':class:`~typing.%s`' % qualname + reftext = ':py:class:`~typing.%s`' % qualname else: - reftext = ':class:`%s`' % qualname + reftext = ':py:class:`%s`' % qualname params = cls.__args__ if params: @@ -237,9 +237,9 @@ def _restify_py36(cls: Optional[Type]) -> str: return reftext elif isinstance(cls, typing.GenericMeta): if module == 'typing': - reftext = ':class:`~typing.%s`' % qualname + reftext = ':py:class:`~typing.%s`' % qualname else: - reftext = ':class:`%s`' % qualname + reftext = ':py:class:`%s`' % qualname if cls.__args__ is None or len(cls.__args__) <= 2: params = cls.__args__ @@ -262,38 +262,38 @@ def _restify_py36(cls: Optional[Type]) -> str: if len(params) > 1 and params[-1] is NoneType: if len(params) > 2: param_str = ", ".join(restify(p) for p in params[:-1]) - return (':obj:`~typing.Optional`\\ ' - '[:obj:`~typing.Union`\\ [%s]]' % param_str) + return (':py:obj:`~typing.Optional`\\ ' + '[:py:obj:`~typing.Union`\\ [%s]]' % param_str) else: - return ':obj:`~typing.Optional`\\ [%s]' % restify(params[0]) + return ':py:obj:`~typing.Optional`\\ [%s]' % restify(params[0]) else: param_str = ', '.join(restify(p) for p in params) - return ':obj:`~typing.Union`\\ [%s]' % param_str + return ':py:obj:`~typing.Union`\\ [%s]' % param_str else: - return ':obj:`Union`' + return ':py:obj:`Union`' elif hasattr(cls, '__qualname__'): if cls.__module__ == 'typing': - return ':class:`~%s.%s`' % (cls.__module__, cls.__qualname__) + return ':py:class:`~%s.%s`' % (cls.__module__, cls.__qualname__) else: - return ':class:`%s.%s`' % (cls.__module__, cls.__qualname__) + return ':py:class:`%s.%s`' % (cls.__module__, cls.__qualname__) elif hasattr(cls, '_name'): # SpecialForm if cls.__module__ == 'typing': - return ':obj:`~%s.%s`' % (cls.__module__, cls._name) + return ':py:obj:`~%s.%s`' % (cls.__module__, cls._name) else: - return ':obj:`%s.%s`' % (cls.__module__, cls._name) + return ':py:obj:`%s.%s`' % (cls.__module__, cls._name) elif hasattr(cls, '__name__'): # not a class (ex. TypeVar) if cls.__module__ == 'typing': - return ':obj:`~%s.%s`' % (cls.__module__, cls.__name__) + return ':py:obj:`~%s.%s`' % (cls.__module__, cls.__name__) else: - return ':obj:`%s.%s`' % (cls.__module__, cls.__name__) + return ':py:obj:`%s.%s`' % (cls.__module__, cls.__name__) else: # others (ex. Any) if cls.__module__ == 'typing': - return ':obj:`~%s.%s`' % (cls.__module__, qualname) + return ':py:obj:`~%s.%s`' % (cls.__module__, qualname) else: - return ':obj:`%s.%s`' % (cls.__module__, qualname) + return ':py:obj:`%s.%s`' % (cls.__module__, qualname) def stringify(annotation: Any) -> str: diff --git a/tests/test_ext_autodoc.py b/tests/test_ext_autodoc.py index 299c1c68170..15584200763 100644 --- a/tests/test_ext_autodoc.py +++ b/tests/test_ext_autodoc.py @@ -984,7 +984,7 @@ def test_autodoc_inner_class(app): ' .. py:attribute:: Outer.factory', ' :module: target', '', - ' alias of :class:`dict`' + ' alias of :py:class:`dict`' ] actual = do_autodoc(app, 'class', 'target.Outer.Inner', options) @@ -1009,7 +1009,7 @@ def test_autodoc_inner_class(app): '', '.. py:class:: InnerChild()', ' :module: target', '', - ' Bases: :class:`target.Outer.Inner`', + ' Bases: :py:class:`target.Outer.Inner`', '', ' InnerChild docstring', '', @@ -1750,7 +1750,7 @@ def test_autodoc_typed_instance_variables(app): '.. py:attribute:: Alias', ' :module: target.typed_vars', '', - ' alias of :class:`target.typed_vars.Derived`', + ' alias of :py:class:`target.typed_vars.Derived`', '', '.. py:class:: Class()', ' :module: target.typed_vars', @@ -1915,12 +1915,12 @@ def test_autodoc_GenericAlias(app): ' .. py:attribute:: Class.T', ' :module: target.genericalias', '', - ' alias of :class:`~typing.List`\\ [:class:`int`]', + ' alias of :py:class:`~typing.List`\\ [:py:class:`int`]', '', '.. py:attribute:: T', ' :module: target.genericalias', '', - ' alias of :class:`~typing.List`\\ [:class:`int`]', + ' alias of :py:class:`~typing.List`\\ [:py:class:`int`]', ] else: assert list(actual) == [ @@ -1937,7 +1937,7 @@ def test_autodoc_GenericAlias(app): '', ' A list of int', '', - ' alias of :class:`~typing.List`\\ [:class:`int`]', + ' alias of :py:class:`~typing.List`\\ [:py:class:`int`]', '', '', '.. py:data:: T', @@ -1945,7 +1945,7 @@ def test_autodoc_GenericAlias(app): '', ' A list of int', '', - ' alias of :class:`~typing.List`\\ [:class:`int`]', + ' alias of :py:class:`~typing.List`\\ [:py:class:`int`]', '', ] @@ -1977,7 +1977,7 @@ def test_autodoc_TypeVar(app): '', ' T6', '', - ' alias of :class:`int`', + ' alias of :py:class:`int`', '', '', '.. py:data:: T1', @@ -2017,7 +2017,7 @@ def test_autodoc_TypeVar(app): '', ' T6', '', - ' alias of :class:`int`', + ' alias of :py:class:`int`', '', '', '.. py:data:: T7', @@ -2025,7 +2025,7 @@ def test_autodoc_TypeVar(app): '', ' T7', '', - " alias of TypeVar('T7', bound=\\ :class:`int`)", + " alias of TypeVar('T7', bound=\\ :py:class:`int`)", '', ] diff --git a/tests/test_ext_autodoc_autoattribute.py b/tests/test_ext_autodoc_autoattribute.py index 20317b8da39..a9392163a9d 100644 --- a/tests/test_ext_autodoc_autoattribute.py +++ b/tests/test_ext_autodoc_autoattribute.py @@ -167,7 +167,7 @@ def test_autoattribute_GenericAlias(app): '', ' A list of int', '', - ' alias of :class:`~typing.List`\\ [:class:`int`]', + ' alias of :py:class:`~typing.List`\\ [:py:class:`int`]', '', ] @@ -182,7 +182,7 @@ def test_autoattribute_NewType(app): '', ' T6', '', - ' alias of :class:`int`', + ' alias of :py:class:`int`', '', ] diff --git a/tests/test_ext_autodoc_autoclass.py b/tests/test_ext_autodoc_autoclass.py index 24617bf0a5f..0470bd6fd1f 100644 --- a/tests/test_ext_autodoc_autoclass.py +++ b/tests/test_ext_autodoc_autoclass.py @@ -265,8 +265,8 @@ def test_show_inheritance_for_subclass_of_generic_type(app): '.. py:class:: Quux(iterable=(), /)', ' :module: target.classes', '', - ' Bases: :class:`~typing.List`\\ ' - '[:obj:`~typing.Union`\\ [:class:`int`, :class:`float`]]', + ' Bases: :py:class:`~typing.List`\\ ' + '[:py:obj:`~typing.Union`\\ [:py:class:`int`, :py:class:`float`]]', '', ' A subclass of List[Union[int, float]]', '', @@ -296,7 +296,7 @@ def autodoc_process_bases(app, name, obj, options, bases): '.. py:class:: Quux(*args, **kwds)', ' :module: target.classes', '', - ' Bases: :class:`int`, :class:`str`', + ' Bases: :py:class:`int`, :py:class:`str`', '', ' A subclass of List[Union[int, float]]', '', @@ -307,7 +307,7 @@ def autodoc_process_bases(app, name, obj, options, bases): '.. py:class:: Quux(iterable=(), /)', ' :module: target.classes', '', - ' Bases: :class:`int`, :class:`str`', + ' Bases: :py:class:`int`, :py:class:`str`', '', ' A subclass of List[Union[int, float]]', '', @@ -375,7 +375,7 @@ def autodoc_process_docstring(*args): '.. py:attribute:: Alias', ' :module: target.classes', '', - ' alias of :class:`target.classes.Foo`', + ' alias of :py:class:`target.classes.Foo`', ] diff --git a/tests/test_ext_autodoc_autodata.py b/tests/test_ext_autodoc_autodata.py index d01e45fc10a..f983726adc0 100644 --- a/tests/test_ext_autodoc_autodata.py +++ b/tests/test_ext_autodoc_autodata.py @@ -96,7 +96,7 @@ def test_autodata_GenericAlias(app): '', ' A list of int', '', - ' alias of :class:`~typing.List`\\ [:class:`int`]', + ' alias of :py:class:`~typing.List`\\ [:py:class:`int`]', '', ] @@ -111,7 +111,7 @@ def test_autodata_NewType(app): '', ' T6', '', - ' alias of :class:`int`', + ' alias of :py:class:`int`', '', ] diff --git a/tests/test_util_typing.py b/tests/test_util_typing.py index bbee68f82cc..ad57a347e5e 100644 --- a/tests/test_util_typing.py +++ b/tests/test_util_typing.py @@ -41,66 +41,69 @@ class BrokenType: 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(TracebackType) == ":class:`types.TracebackType`" - assert restify(Any) == ":obj:`~typing.Any`" + assert restify(int) == ":py:class:`int`" + assert restify(str) == ":py:class:`str`" + assert restify(None) == ":py:obj:`None`" + assert restify(Integral) == ":py:class:`numbers.Integral`" + assert restify(Struct) == ":py:class:`struct.Struct`" + assert restify(TracebackType) == ":py:class:`types.TracebackType`" + assert restify(Any) == ":py:obj:`~typing.Any`" def test_restify_type_hints_containers(): - assert restify(List) == ":class:`~typing.List`" - assert restify(Dict) == ":class:`~typing.Dict`" - assert restify(List[int]) == ":class:`~typing.List`\\ [:class:`int`]" - assert restify(List[str]) == ":class:`~typing.List`\\ [:class:`str`]" - assert restify(Dict[str, float]) == (":class:`~typing.Dict`\\ " - "[:class:`str`, :class:`float`]") - assert restify(Tuple[str, str, str]) == (":class:`~typing.Tuple`\\ " - "[:class:`str`, :class:`str`, :class:`str`]") - assert restify(Tuple[str, ...]) == ":class:`~typing.Tuple`\\ [:class:`str`, ...]" - assert restify(Tuple[()]) == ":class:`~typing.Tuple`\\ [()]" - assert restify(List[Dict[str, Tuple]]) == (":class:`~typing.List`\\ " - "[:class:`~typing.Dict`\\ " - "[:class:`str`, :class:`~typing.Tuple`]]") - assert restify(MyList[Tuple[int, int]]) == (":class:`tests.test_util_typing.MyList`\\ " - "[:class:`~typing.Tuple`\\ " - "[:class:`int`, :class:`int`]]") - assert restify(Generator[None, None, None]) == (":class:`~typing.Generator`\\ " - "[:obj:`None`, :obj:`None`, :obj:`None`]") + assert restify(List) == ":py:class:`~typing.List`" + assert restify(Dict) == ":py:class:`~typing.Dict`" + assert restify(List[int]) == ":py:class:`~typing.List`\\ [:py:class:`int`]" + assert restify(List[str]) == ":py:class:`~typing.List`\\ [:py:class:`str`]" + assert restify(Dict[str, float]) == (":py:class:`~typing.Dict`\\ " + "[:py:class:`str`, :py:class:`float`]") + assert restify(Tuple[str, str, str]) == (":py:class:`~typing.Tuple`\\ " + "[:py:class:`str`, :py:class:`str`, " + ":py:class:`str`]") + assert restify(Tuple[str, ...]) == ":py:class:`~typing.Tuple`\\ [:py:class:`str`, ...]" + assert restify(Tuple[()]) == ":py:class:`~typing.Tuple`\\ [()]" + assert restify(List[Dict[str, Tuple]]) == (":py:class:`~typing.List`\\ " + "[:py:class:`~typing.Dict`\\ " + "[:py:class:`str`, :py:class:`~typing.Tuple`]]") + assert restify(MyList[Tuple[int, int]]) == (":py:class:`tests.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`]") def test_restify_type_hints_Callable(): - assert restify(Callable) == ":class:`~typing.Callable`" + assert restify(Callable) == ":py:class:`~typing.Callable`" if sys.version_info >= (3, 7): - assert restify(Callable[[str], int]) == (":class:`~typing.Callable`\\ " - "[[:class:`str`], :class:`int`]") - assert restify(Callable[..., int]) == (":class:`~typing.Callable`\\ " - "[[...], :class:`int`]") + 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`]") else: - assert restify(Callable[[str], int]) == (":class:`~typing.Callable`\\ " - "[:class:`str`, :class:`int`]") - assert restify(Callable[..., int]) == (":class:`~typing.Callable`\\ " - "[..., :class:`int`]") + 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`]") def test_restify_type_hints_Union(): - assert restify(Optional[int]) == ":obj:`~typing.Optional`\\ [:class:`int`]" - assert restify(Union[str, None]) == ":obj:`~typing.Optional`\\ [:class:`str`]" - assert restify(Union[int, str]) == ":obj:`~typing.Union`\\ [:class:`int`, :class:`str`]" + assert restify(Optional[int]) == ":py:obj:`~typing.Optional`\\ [:py:class:`int`]" + assert restify(Union[str, None]) == ":py:obj:`~typing.Optional`\\ [:py:class:`str`]" + assert restify(Union[int, str]) == (":py:obj:`~typing.Union`\\ " + "[:py:class:`int`, :py:class:`str`]") if sys.version_info >= (3, 7): - assert restify(Union[int, Integral]) == (":obj:`~typing.Union`\\ " - "[:class:`int`, :class:`numbers.Integral`]") + assert restify(Union[int, Integral]) == (":py:obj:`~typing.Union`\\ " + "[:py:class:`int`, :py:class:`numbers.Integral`]") assert (restify(Union[MyClass1, MyClass2]) == - (":obj:`~typing.Union`\\ " - "[:class:`tests.test_util_typing.MyClass1`, " - ":class:`tests.test_util_typing.`]")) + (":py:obj:`~typing.Union`\\ " + "[:py:class:`tests.test_util_typing.MyClass1`, " + ":py:class:`tests.test_util_typing.`]")) else: - assert restify(Union[int, Integral]) == ":class:`numbers.Integral`" - assert restify(Union[MyClass1, MyClass2]) == ":class:`tests.test_util_typing.MyClass1`" + assert restify(Union[int, Integral]) == ":py:class:`numbers.Integral`" + assert restify(Union[MyClass1, MyClass2]) == ":py:class:`tests.test_util_typing.MyClass1`" @pytest.mark.skipif(sys.version_info < (3, 7), reason='python 3.7+ is required.') @@ -109,58 +112,61 @@ def test_restify_type_hints_typevars(): 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:`~typing.List`\\ [:obj:`tests.test_util_typing.T`]" + assert restify(T) == ":py:obj:`tests.test_util_typing.T`" + assert restify(T_co) == ":py:obj:`tests.test_util_typing.T_co`" + assert restify(T_contra) == ":py:obj:`tests.test_util_typing.T_contra`" + assert restify(List[T]) == ":py:class:`~typing.List`\\ [:py:obj:`tests.test_util_typing.T`]" if sys.version_info >= (3, 10): - assert restify(MyInt) == ":class:`tests.test_util_typing.MyInt`" + assert restify(MyInt) == ":py:class:`tests.test_util_typing.MyInt`" else: - assert restify(MyInt) == ":class:`MyInt`" + assert restify(MyInt) == ":py: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.`" + assert restify(MyClass1) == ":py:class:`tests.test_util_typing.MyClass1`" + assert restify(MyClass2) == ":py:class:`tests.test_util_typing.`" def test_restify_type_hints_alias(): MyStr = str MyTuple = Tuple[str, str] - assert restify(MyStr) == ":class:`str`" - assert restify(MyTuple) == ":class:`~typing.Tuple`\\ [:class:`str`, :class:`str`]" + assert restify(MyStr) == ":py:class:`str`" + assert restify(MyTuple) == ":py:class:`~typing.Tuple`\\ [:py:class:`str`, :py:class:`str`]" @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`" + assert restify(ForwardRef("myint")) == ":py:class:`myint`" @pytest.mark.skipif(sys.version_info < (3, 8), reason='python 3.8+ is required.') def test_restify_type_Literal(): from typing import Literal # type: ignore - assert restify(Literal[1, "2", "\r"]) == ":obj:`~typing.Literal`\\ [1, '2', '\\r']" + assert restify(Literal[1, "2", "\r"]) == ":py:obj:`~typing.Literal`\\ [1, '2', '\\r']" @pytest.mark.skipif(sys.version_info < (3, 9), reason='python 3.9+ is required.') def test_restify_pep_585(): - assert restify(list[str]) == ":class:`list`\\ [:class:`str`]" # type: ignore - assert restify(dict[str, str]) == ":class:`dict`\\ [:class:`str`, :class:`str`]" # type: ignore - assert restify(dict[str, tuple[int, ...]]) == \ - ":class:`dict`\\ [:class:`str`, :class:`tuple`\\ [:class:`int`, ...]]" # type: ignore + assert restify(list[str]) == ":py:class:`list`\\ [:py:class:`str`]" # type: ignore + assert restify(dict[str, str]) == (":py:class:`dict`\\ " # type: ignore + "[:py:class:`str`, :py:class:`str`]") + assert restify(dict[str, tuple[int, ...]]) == (":py:class:`dict`\\ " # type: ignore + "[:py:class:`str`, :py:class:`tuple`\\ " + "[:py:class:`int`, ...]]") @pytest.mark.skipif(sys.version_info < (3, 10), reason='python 3.10+ is required.') def test_restify_type_union_operator(): - assert restify(int | None) == ":class:`int` | :obj:`None`" # type: ignore - assert restify(int | str) == ":class:`int` | :class:`str`" # type: ignore - assert restify(int | str | None) == ":class:`int` | :class:`str` | :obj:`None`" # type: ignore + assert restify(int | None) == ":py:class:`int` | :py:obj:`None`" # type: ignore + assert restify(int | str) == ":py:class:`int` | :py:class:`str`" # type: ignore + assert restify(int | str | None) == (":py:class:`int` | :py:class:`str` | " # type: ignore + ":py:obj:`None`") def test_restify_broken_type_hints(): - assert restify(BrokenType) == ':class:`tests.test_util_typing.BrokenType`' + assert restify(BrokenType) == ':py:class:`tests.test_util_typing.BrokenType`' def test_stringify():