Skip to content

Commit

Permalink
Merge pull request #9415 from tk0miya/9362_AttributeError_for_subclas…
Browse files Browse the repository at this point in the history
…s_of_empty_tuple

Fix #9362: autodoc: AttributeError is raised for a subclass of Tuple[()]
  • Loading branch information
tk0miya committed Jul 8, 2021
2 parents be1dfb5 + 007dee7 commit 8c62099
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 20 deletions.
1 change: 1 addition & 0 deletions CHANGES
Expand Up @@ -88,6 +88,7 @@ Bugs fixed
attribute not having any comment
* #9364: autodoc: single element tuple on the default argument value is wrongly
rendered
* #9362: autodoc: AttributeError is raised on processing a subclass of Tuple[()]
* #9317: html: Pushing left key causes visiting the next page at the first page
* #9381: html: URL for html_favicon and html_log does not work
* #9270: html theme : pyramid theme generates incorrect logo links
Expand Down
43 changes: 23 additions & 20 deletions sphinx/util/typing.py
Expand Up @@ -105,27 +105,30 @@ def restify(cls: Optional[Type]) -> str:
"""Convert python class to a reST reference."""
from sphinx.util import inspect # lazy loading

if cls is None or cls is NoneType:
return ':obj:`None`'
elif cls is Ellipsis:
return '...'
elif cls in INVALID_BUILTIN_CLASSES:
return ':class:`%s`' % INVALID_BUILTIN_CLASSES[cls]
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:
if sys.version_info >= (3, 7): # py37+
return _restify_py37(cls)
try:
if cls is None or cls is NoneType:
return ':obj:`None`'
elif cls is Ellipsis:
return '...'
elif cls in INVALID_BUILTIN_CLASSES:
return ':class:`%s`' % INVALID_BUILTIN_CLASSES[cls]
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:
return _restify_py36(cls)
if sys.version_info >= (3, 7): # py37+
return _restify_py37(cls)
else:
return _restify_py36(cls)
except AttributeError:
return repr(cls)


def _restify_py37(cls: Optional[Type]) -> str:
Expand Down
2 changes: 2 additions & 0 deletions tests/test_util_typing.py
Expand Up @@ -60,6 +60,7 @@ def test_restify_type_hints_containers():
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`]]")
Expand Down Expand Up @@ -168,6 +169,7 @@ def test_stringify_type_hints_containers():
assert stringify(Dict[str, float]) == "Dict[str, float]"
assert stringify(Tuple[str, str, str]) == "Tuple[str, str, str]"
assert stringify(Tuple[str, ...]) == "Tuple[str, ...]"
assert stringify(Tuple[()]) == "Tuple[()]"
assert stringify(List[Dict[str, Tuple]]) == "List[Dict[str, Tuple]]"
assert stringify(MyList[Tuple[int, int]]) == "tests.test_util_typing.MyList[Tuple[int, int]]"
assert stringify(Generator[None, None, None]) == "Generator[None, None, None]"
Expand Down

0 comments on commit 8c62099

Please sign in to comment.