mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
autodoc: Support type union operator (PEP-604) (refs: #8775)
Upgrade autodoc to support type union operator introduced in PEP-604. It's available only with python 3.10+.
This commit is contained in:
parent
be20f17892
commit
7318d1dfd4
1
CHANGES
1
CHANGES
@ -38,6 +38,7 @@ Features added
|
||||
info-field-list
|
||||
* #8514: autodoc: Default values of overloaded functions are taken from actual
|
||||
implementation if they're ellipsis
|
||||
* #8775: autodoc: Support type union operator (PEP-604) in Python 3.10 or above
|
||||
* #8619: html: kbd role generates customizable HTML tags for compound keys
|
||||
* #8634: html: Allow to change the order of JS/CSS via ``priority`` parameter
|
||||
for :meth:`Sphinx.add_js_file()` and :meth:`Sphinx.add_css_file()`
|
||||
|
@ -30,6 +30,11 @@ else:
|
||||
ref = _ForwardRef(self.arg)
|
||||
return ref._eval_type(globalns, localns)
|
||||
|
||||
if sys.version_info > (3, 10):
|
||||
from types import Union as types_Union
|
||||
else:
|
||||
types_Union = None
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Type # NOQA # for python3.5.1
|
||||
@ -100,6 +105,12 @@ def restify(cls: Optional["Type"]) -> str:
|
||||
return ':class:`struct.Struct`'
|
||||
elif inspect.isNewType(cls):
|
||||
return ':class:`%s`' % cls.__name__
|
||||
elif types_Union and isinstance(cls, types_Union):
|
||||
if len(cls.__args__) > 1 and None in cls.__args__:
|
||||
args = ' | '.join(restify(a) for a in cls.__args__ if a)
|
||||
return 'Optional[%s]' % args
|
||||
else:
|
||||
return ' | '.join(restify(a) for a in cls.__args__)
|
||||
elif cls.__module__ in ('__builtin__', 'builtins'):
|
||||
return ':class:`%s`' % cls.__name__
|
||||
else:
|
||||
@ -336,6 +347,8 @@ def _stringify_py37(annotation: Any) -> str:
|
||||
elif hasattr(annotation, '__origin__'):
|
||||
# instantiated generic provided by a user
|
||||
qualname = stringify(annotation.__origin__)
|
||||
elif types_Union and isinstance(annotation, types_Union): # types.Union (for py3.10+)
|
||||
qualname = 'types.Union'
|
||||
else:
|
||||
# we weren't able to extract the base type, appending arguments would
|
||||
# only make them appear twice
|
||||
@ -355,6 +368,12 @@ def _stringify_py37(annotation: Any) -> str:
|
||||
else:
|
||||
args = ', '.join(stringify(a) for a in annotation.__args__)
|
||||
return 'Union[%s]' % args
|
||||
elif qualname == 'types.Union':
|
||||
if len(annotation.__args__) > 1 and None in annotation.__args__:
|
||||
args = ' | '.join(stringify(a) for a in annotation.__args__ if a)
|
||||
return 'Optional[%s]' % args
|
||||
else:
|
||||
return ' | '.join(stringify(a) for a in annotation.__args__)
|
||||
elif qualname == 'Callable':
|
||||
args = ', '.join(stringify(a) for a in annotation.__args__[:-1])
|
||||
returns = stringify(annotation.__args__[-1])
|
||||
|
16
tests/roots/test-ext-autodoc/target/pep604.py
Normal file
16
tests/roots/test-ext-autodoc/target/pep604.py
Normal file
@ -0,0 +1,16 @@
|
||||
from __future__ import annotations
|
||||
|
||||
attr: int | str #: docstring
|
||||
|
||||
|
||||
def sum(x: int | str, y: int | str) -> int | str:
|
||||
"""docstring"""
|
||||
|
||||
|
||||
class Foo:
|
||||
"""docstring"""
|
||||
|
||||
attr: int | str #: docstring
|
||||
|
||||
def meth(self, x: int | str, y: int | str) -> int | str:
|
||||
"""docstring"""
|
@ -2237,6 +2237,50 @@ def test_name_mangling(app):
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 10), reason='python 3.10+ is required.')
|
||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||
def test_type_union_operator(app):
|
||||
options = {'members': None}
|
||||
actual = do_autodoc(app, 'module', 'target.pep604', options)
|
||||
assert list(actual) == [
|
||||
'',
|
||||
'.. py:module:: target.pep604',
|
||||
'',
|
||||
'',
|
||||
'.. py:class:: Foo()',
|
||||
' :module: target.pep604',
|
||||
'',
|
||||
' docstring',
|
||||
'',
|
||||
'',
|
||||
' .. py:attribute:: Foo.attr',
|
||||
' :module: target.pep604',
|
||||
' :type: int | str',
|
||||
'',
|
||||
' docstring',
|
||||
'',
|
||||
'',
|
||||
' .. py:method:: Foo.meth(x: int | str, y: int | str) -> int | str',
|
||||
' :module: target.pep604',
|
||||
'',
|
||||
' docstring',
|
||||
'',
|
||||
'',
|
||||
'.. py:data:: attr',
|
||||
' :module: target.pep604',
|
||||
' :type: int | str',
|
||||
'',
|
||||
' docstring',
|
||||
'',
|
||||
'',
|
||||
'.. py:function:: sum(x: int | str, y: int | str) -> int | str',
|
||||
' :module: target.pep604',
|
||||
'',
|
||||
' docstring',
|
||||
'',
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 6), reason='python 3.6+ is required.')
|
||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||
def test_hide_value(app):
|
||||
|
@ -117,6 +117,13 @@ def test_restify_type_ForwardRef():
|
||||
assert restify(ForwardRef("myint")) == ":class:`myint`"
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 10), reason='python 3.10+ is required.')
|
||||
def test_restify_type_union_operator():
|
||||
assert restify(int | None) == "Optional[:class:`int`]" # type: ignore
|
||||
assert restify(int | str) == ":class:`int` | :class:`str`" # type: ignore
|
||||
assert restify(int | str | None) == "Optional[:class:`int` | :class:`str`]" # type: ignore
|
||||
|
||||
|
||||
def test_restify_broken_type_hints():
|
||||
assert restify(BrokenType) == ':class:`tests.test_util_typing.BrokenType`'
|
||||
|
||||
@ -206,5 +213,12 @@ def test_stringify_type_hints_alias():
|
||||
assert stringify(MyTuple) == "Tuple[str, str]" # type: ignore
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 10), reason='python 3.10+ is required.')
|
||||
def test_stringify_type_union_operator():
|
||||
assert stringify(int | None) == "Optional[int]" # type: ignore
|
||||
assert stringify(int | str) == "int | str" # type: ignore
|
||||
assert stringify(int | str | None) == "Optional[int | str]" # type: ignore
|
||||
|
||||
|
||||
def test_stringify_broken_type_hints():
|
||||
assert stringify(BrokenType) == 'tests.test_util_typing.BrokenType'
|
||||
|
Loading…
Reference in New Issue
Block a user