Skip to content

Commit 18394ae

Browse files
authored
Add more types with an incorrect __module__ attribute (#11861)
1 parent ea9c61f commit 18394ae

File tree

2 files changed

+101
-11
lines changed

2 files changed

+101
-11
lines changed

sphinx/util/typing.py

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
from __future__ import annotations
44

55
import sys
6+
import types
67
import typing
78
from collections.abc import Sequence
9+
from contextvars import Context, ContextVar, Token
810
from struct import Struct
9-
from types import TracebackType
1011
from typing import TYPE_CHECKING, Any, Callable, ForwardRef, TypedDict, TypeVar, Union
1112

1213
from docutils import nodes
@@ -22,17 +23,40 @@
2223
else:
2324
UnionType = None
2425

25-
# classes that have incorrect __module__
26-
INVALID_BUILTIN_CLASSES = {
26+
# classes that have an incorrect .__module__ attribute
27+
_INVALID_BUILTIN_CLASSES = {
28+
Context: 'contextvars.Context', # Context.__module__ == '_contextvars'
29+
ContextVar: 'contextvars.ContextVar', # ContextVar.__module__ == '_contextvars'
30+
Token: 'contextvars.Token', # Token.__module__ == '_contextvars'
2731
Struct: 'struct.Struct', # Struct.__module__ == '_struct'
28-
TracebackType: 'types.TracebackType', # TracebackType.__module__ == 'builtins'
32+
# types in 'types' with <type>.__module__ == 'builtins':
33+
types.AsyncGeneratorType: 'types.AsyncGeneratorType',
34+
types.BuiltinFunctionType: 'types.BuiltinFunctionType',
35+
types.BuiltinMethodType: 'types.BuiltinMethodType',
36+
types.CellType: 'types.CellType',
37+
types.ClassMethodDescriptorType: 'types.ClassMethodDescriptorType',
38+
types.CodeType: 'types.CodeType',
39+
types.CoroutineType: 'types.CoroutineType',
40+
types.FrameType: 'types.FrameType',
41+
types.FunctionType: 'types.FunctionType',
42+
types.GeneratorType: 'types.GeneratorType',
43+
types.GetSetDescriptorType: 'types.GetSetDescriptorType',
44+
types.LambdaType: 'types.LambdaType',
45+
types.MappingProxyType: 'types.MappingProxyType',
46+
types.MemberDescriptorType: 'types.MemberDescriptorType',
47+
types.MethodDescriptorType: 'types.MethodDescriptorType',
48+
types.MethodType: 'types.MethodType',
49+
types.MethodWrapperType: 'types.MethodWrapperType',
50+
types.ModuleType: 'types.ModuleType',
51+
types.TracebackType: 'types.TracebackType',
52+
types.WrapperDescriptorType: 'types.WrapperDescriptorType',
2953
}
3054

3155

3256
def is_invalid_builtin_class(obj: Any) -> bool:
3357
"""Check *obj* is an invalid built-in class."""
3458
try:
35-
return obj in INVALID_BUILTIN_CLASSES
59+
return obj in _INVALID_BUILTIN_CLASSES
3660
except TypeError: # unhashable type
3761
return False
3862

@@ -143,7 +167,7 @@ def restify(cls: type | None, mode: str = 'fully-qualified-except-typing') -> st
143167
elif ismock(cls):
144168
return f':py:class:`{modprefix}{cls.__module__}.{cls.__name__}`'
145169
elif is_invalid_builtin_class(cls):
146-
return f':py:class:`{modprefix}{INVALID_BUILTIN_CLASSES[cls]}`'
170+
return f':py:class:`{modprefix}{_INVALID_BUILTIN_CLASSES[cls]}`'
147171
elif inspect.isNewType(cls):
148172
if sys.version_info[:2] >= (3, 10):
149173
# newtypes have correct module info since Python 3.10+
@@ -300,7 +324,7 @@ def stringify_annotation(
300324
elif ismock(annotation):
301325
return module_prefix + f'{annotation_module}.{annotation_name}'
302326
elif is_invalid_builtin_class(annotation):
303-
return module_prefix + INVALID_BUILTIN_CLASSES[annotation]
327+
return module_prefix + _INVALID_BUILTIN_CLASSES[annotation]
304328
elif str(annotation).startswith('typing.Annotated'): # for py310+
305329
pass
306330
elif annotation_module == 'builtins' and annotation_qualname:

tests/test_util_typing.py

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,32 @@
11
"""Tests util.typing functions."""
22

33
import sys
4+
from contextvars import Context, ContextVar, Token
45
from enum import Enum
56
from numbers import Integral
67
from struct import Struct
7-
from types import TracebackType
8+
from types import (
9+
AsyncGeneratorType,
10+
BuiltinFunctionType,
11+
BuiltinMethodType,
12+
CellType,
13+
ClassMethodDescriptorType,
14+
CodeType,
15+
CoroutineType,
16+
FrameType,
17+
FunctionType,
18+
GeneratorType,
19+
GetSetDescriptorType,
20+
LambdaType,
21+
MappingProxyType,
22+
MemberDescriptorType,
23+
MethodDescriptorType,
24+
MethodType,
25+
MethodWrapperType,
26+
ModuleType,
27+
TracebackType,
28+
WrapperDescriptorType,
29+
)
830
from typing import (
931
Any,
1032
Callable,
@@ -21,7 +43,7 @@
2143
import pytest
2244

2345
from sphinx.ext.autodoc import mock
24-
from sphinx.util.typing import INVALID_BUILTIN_CLASSES, restify, stringify_annotation
46+
from sphinx.util.typing import _INVALID_BUILTIN_CLASSES, restify, stringify_annotation
2547

2648

2749
class MyClass1:
@@ -76,11 +98,55 @@ def test_restify():
7698

7799
def test_is_invalid_builtin_class():
78100
# if these tests start failing, it means that the __module__
79-
# of one of these classes has changed, and INVALID_BUILTIN_CLASSES
101+
# of one of these classes has changed, and _INVALID_BUILTIN_CLASSES
80102
# in sphinx.util.typing needs to be updated.
81-
assert INVALID_BUILTIN_CLASSES.keys() == {Struct, TracebackType}
103+
assert _INVALID_BUILTIN_CLASSES.keys() == {
104+
Context,
105+
ContextVar,
106+
Token,
107+
Struct,
108+
AsyncGeneratorType,
109+
BuiltinFunctionType,
110+
BuiltinMethodType,
111+
CellType,
112+
ClassMethodDescriptorType,
113+
CodeType,
114+
CoroutineType,
115+
FrameType,
116+
FunctionType,
117+
GeneratorType,
118+
GetSetDescriptorType,
119+
LambdaType,
120+
MappingProxyType,
121+
MemberDescriptorType,
122+
MethodDescriptorType,
123+
MethodType,
124+
MethodWrapperType,
125+
ModuleType,
126+
TracebackType,
127+
WrapperDescriptorType,
128+
}
82129
assert Struct.__module__ == '_struct'
130+
assert AsyncGeneratorType.__module__ == 'builtins'
131+
assert BuiltinFunctionType.__module__ == 'builtins'
132+
assert BuiltinMethodType.__module__ == 'builtins'
133+
assert CellType.__module__ == 'builtins'
134+
assert ClassMethodDescriptorType.__module__ == 'builtins'
135+
assert CodeType.__module__ == 'builtins'
136+
assert CoroutineType.__module__ == 'builtins'
137+
assert FrameType.__module__ == 'builtins'
138+
assert FunctionType.__module__ == 'builtins'
139+
assert GeneratorType.__module__ == 'builtins'
140+
assert GetSetDescriptorType.__module__ == 'builtins'
141+
assert LambdaType.__module__ == 'builtins'
142+
assert MappingProxyType.__module__ == 'builtins'
143+
assert MemberDescriptorType.__module__ == 'builtins'
144+
assert MethodDescriptorType.__module__ == 'builtins'
145+
assert MethodType.__module__ == 'builtins'
146+
assert MethodWrapperType.__module__ == 'builtins'
147+
assert ModuleType.__module__ == 'builtins'
83148
assert TracebackType.__module__ == 'builtins'
149+
assert WrapperDescriptorType.__module__ == 'builtins'
84150

85151

86152
def test_restify_type_hints_containers():

0 commit comments

Comments
 (0)