mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Fix #10133: autodoc: Crashed when mocked module is used for type annotation
This commit is contained in:
parent
2be0630951
commit
444e27865d
2
CHANGES
2
CHANGES
@ -19,6 +19,8 @@ Features added
|
|||||||
Bugs fixed
|
Bugs fixed
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
* #10133: autodoc: Crashed when mocked module is used for type annotation
|
||||||
|
|
||||||
Testing
|
Testing
|
||||||
--------
|
--------
|
||||||
|
|
||||||
|
@ -154,6 +154,11 @@ def mock(modnames: List[str]) -> Generator[None, None, None]:
|
|||||||
finder.invalidate_caches()
|
finder.invalidate_caches()
|
||||||
|
|
||||||
|
|
||||||
|
def ismockmodule(subject: Any) -> bool:
|
||||||
|
"""Check if the object is a mocked module."""
|
||||||
|
return isinstance(subject, _MockModule)
|
||||||
|
|
||||||
|
|
||||||
def ismock(subject: Any) -> bool:
|
def ismock(subject: Any) -> bool:
|
||||||
"""Check if the object is mocked."""
|
"""Check if the object is mocked."""
|
||||||
# check the object has '__sphinx_mock__' attribute
|
# check the object has '__sphinx_mock__' attribute
|
||||||
|
@ -116,6 +116,7 @@ def restify(cls: Optional[Type], mode: str = 'fully-qualified-except-typing') ->
|
|||||||
'smart'
|
'smart'
|
||||||
Show the name of the annotation.
|
Show the name of the annotation.
|
||||||
"""
|
"""
|
||||||
|
from sphinx.ext.autodoc.mock import ismock, ismockmodule # lazy loading
|
||||||
from sphinx.util import inspect # lazy loading
|
from sphinx.util import inspect # lazy loading
|
||||||
|
|
||||||
if mode == 'smart':
|
if mode == 'smart':
|
||||||
@ -130,6 +131,10 @@ def restify(cls: Optional[Type], mode: str = 'fully-qualified-except-typing') ->
|
|||||||
return '...'
|
return '...'
|
||||||
elif isinstance(cls, str):
|
elif isinstance(cls, str):
|
||||||
return cls
|
return cls
|
||||||
|
elif ismockmodule(cls):
|
||||||
|
return ':py:class:`%s%s`' % (modprefix, cls.__name__)
|
||||||
|
elif ismock(cls):
|
||||||
|
return ':py:class:`%s%s.%s`' % (modprefix, cls.__module__, cls.__name__)
|
||||||
elif cls in INVALID_BUILTIN_CLASSES:
|
elif cls in INVALID_BUILTIN_CLASSES:
|
||||||
return ':py:class:`%s%s`' % (modprefix, INVALID_BUILTIN_CLASSES[cls])
|
return ':py:class:`%s%s`' % (modprefix, INVALID_BUILTIN_CLASSES[cls])
|
||||||
elif inspect.isNewType(cls):
|
elif inspect.isNewType(cls):
|
||||||
@ -335,6 +340,7 @@ def stringify(annotation: Any, mode: str = 'fully-qualified-except-typing') -> s
|
|||||||
'fully-qualified'
|
'fully-qualified'
|
||||||
Show the module name and qualified name of the annotation.
|
Show the module name and qualified name of the annotation.
|
||||||
"""
|
"""
|
||||||
|
from sphinx.ext.autodoc.mock import ismock, ismockmodule # lazy loading
|
||||||
from sphinx.util import inspect # lazy loading
|
from sphinx.util import inspect # lazy loading
|
||||||
|
|
||||||
if mode == 'smart':
|
if mode == 'smart':
|
||||||
@ -364,6 +370,10 @@ def stringify(annotation: Any, mode: str = 'fully-qualified-except-typing') -> s
|
|||||||
return repr(annotation)
|
return repr(annotation)
|
||||||
elif annotation is NoneType:
|
elif annotation is NoneType:
|
||||||
return 'None'
|
return 'None'
|
||||||
|
elif ismockmodule(annotation):
|
||||||
|
return modprefix + annotation.__name__
|
||||||
|
elif ismock(annotation):
|
||||||
|
return modprefix + '%s.%s' % (annotation.__module__, annotation.__name__)
|
||||||
elif annotation in INVALID_BUILTIN_CLASSES:
|
elif annotation in INVALID_BUILTIN_CLASSES:
|
||||||
return modprefix + INVALID_BUILTIN_CLASSES[annotation]
|
return modprefix + INVALID_BUILTIN_CLASSES[annotation]
|
||||||
elif str(annotation).startswith('typing.Annotated'): # for py310+
|
elif str(annotation).startswith('typing.Annotated'): # for py310+
|
||||||
|
@ -213,6 +213,7 @@ def test_restify_broken_type_hints():
|
|||||||
def test_restify_mock():
|
def test_restify_mock():
|
||||||
with mock(['unknown']):
|
with mock(['unknown']):
|
||||||
import unknown
|
import unknown
|
||||||
|
assert restify(unknown) == ':py:class:`unknown`'
|
||||||
assert restify(unknown.secret.Class) == ':py:class:`unknown.secret.Class`'
|
assert restify(unknown.secret.Class) == ':py:class:`unknown.secret.Class`'
|
||||||
assert restify(unknown.secret.Class, "smart") == ':py:class:`~unknown.secret.Class`'
|
assert restify(unknown.secret.Class, "smart") == ':py:class:`~unknown.secret.Class`'
|
||||||
|
|
||||||
@ -480,5 +481,6 @@ def test_stringify_broken_type_hints():
|
|||||||
def test_stringify_mock():
|
def test_stringify_mock():
|
||||||
with mock(['unknown']):
|
with mock(['unknown']):
|
||||||
import unknown
|
import unknown
|
||||||
|
assert stringify(unknown) == 'unknown'
|
||||||
assert stringify(unknown.secret.Class) == 'unknown.secret.Class'
|
assert stringify(unknown.secret.Class) == 'unknown.secret.Class'
|
||||||
assert stringify(unknown.secret.Class, "smart") == 'unknown.secret.Class'
|
assert stringify(unknown.secret.Class, "smart") == 'unknown.secret.Class'
|
||||||
|
Loading…
Reference in New Issue
Block a user