Skip to content

Commit

Permalink
Close #9560: autodoc: Allow to refer NewType with modname in py310+
Browse files Browse the repository at this point in the history
Before 3.10, an instance of NewType has incorrect module name. But it
was fixed on 3.10.  This starts to use the module info if the
interpreter is 3.10+.
  • Loading branch information
tk0miya committed Sep 5, 2021
1 parent 336605b commit c5b35ef
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CHANGES
Expand Up @@ -15,6 +15,8 @@ Features added

* #9445: autodoc: Support class properties
* #9479: autodoc: Emit a warning if target is a mocked object
* #9560: autodoc: Allow to refer NewType instances with module name in Python
3.10 or above
* #9447: html theme: Expose the version of Sphinx in the form of tuple as a
template variable ``sphinx_version_tuple``
* #9445: py domain: ``:py:property:`` directive supports ``:classmethod:``
Expand Down
14 changes: 11 additions & 3 deletions sphinx/util/typing.py
Expand Up @@ -116,7 +116,12 @@ def restify(cls: Optional[Type]) -> str:
elif cls in INVALID_BUILTIN_CLASSES:
return ':class:`%s`' % INVALID_BUILTIN_CLASSES[cls]
elif inspect.isNewType(cls):
return ':class:`%s`' % cls.__name__
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__)
else:
return ':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)
Expand Down Expand Up @@ -307,8 +312,11 @@ def stringify(annotation: Any) -> str:
else:
return '.'.join([annotation.__module__, annotation.__name__])
elif inspect.isNewType(annotation):
# Could not get the module where it defined
return annotation.__name__
if sys.version_info > (3, 10):
# newtypes have correct module info since Python 3.10+
return '%s.%s' % (annotation.__module__, annotation.__name__)
else:
return annotation.__name__
elif not annotation:
return repr(annotation)
elif annotation is NoneType:
Expand Down
11 changes: 9 additions & 2 deletions tests/test_util_typing.py
Expand Up @@ -113,7 +113,11 @@ def test_restify_type_hints_typevars():
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(MyInt) == ":class:`MyInt`"

if sys.version_info >= (3, 10):
assert restify(MyInt) == ":class:`tests.test_util_typing.MyInt`"
else:
assert restify(MyInt) == ":class:`MyInt`"


def test_restify_type_hints_custom_class():
Expand Down Expand Up @@ -250,7 +254,10 @@ def test_stringify_type_hints_typevars():
assert stringify(T_contra) == "tests.test_util_typing.T_contra"
assert stringify(List[T]) == "List[tests.test_util_typing.T]"

assert stringify(MyInt) == "MyInt"
if sys.version_info >= (3, 10):
assert stringify(MyInt) == "tests.test_util_typing.MyInt"
else:
assert stringify(MyInt) == "MyInt"


def test_stringify_type_hints_custom_class():
Expand Down

0 comments on commit c5b35ef

Please sign in to comment.