Skip to content

Commit b6948b8

Browse files
authored
Style tweaks to sphinx.util.typing (#12282)
1 parent 55ca37f commit b6948b8

File tree

1 file changed

+34
-29
lines changed

1 file changed

+34
-29
lines changed

sphinx/util/typing.py

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
from docutils.parsers.rst.states import Inliner
1515

1616
if TYPE_CHECKING:
17-
from typing import Literal
17+
from collections.abc import Mapping
18+
from typing import Final, Literal
1819

1920
from typing_extensions import TypeAlias
2021

@@ -36,7 +37,7 @@
3637
UnionType = None
3738

3839
# classes that have an incorrect .__module__ attribute
39-
_INVALID_BUILTIN_CLASSES = {
40+
_INVALID_BUILTIN_CLASSES: Final[Mapping[object, str]] = {
4041
Context: 'contextvars.Context', # Context.__module__ == '_contextvars'
4142
ContextVar: 'contextvars.ContextVar', # ContextVar.__module__ == '_contextvars'
4243
Token: 'contextvars.Token', # Token.__module__ == '_contextvars'
@@ -83,8 +84,10 @@ def is_invalid_builtin_class(obj: Any) -> bool:
8384
PathMatcher = Callable[[str], bool]
8485

8586
# common role functions
86-
RoleFunction = Callable[[str, str, str, int, Inliner, dict[str, Any], Sequence[str]],
87-
tuple[list[nodes.Node], list[nodes.system_message]]]
87+
RoleFunction = Callable[
88+
[str, str, str, int, Inliner, dict[str, Any], Sequence[str]],
89+
tuple[list[nodes.Node], list[nodes.system_message]],
90+
]
8891

8992
# A option spec for directive
9093
OptionSpec = dict[str, Callable[[str], Any]]
@@ -127,7 +130,9 @@ class ExtensionMetadata(TypedDict, total=False):
127130

128131

129132
def get_type_hints(
130-
obj: Any, globalns: dict[str, Any] | None = None, localns: dict[str, Any] | None = None,
133+
obj: Any,
134+
globalns: dict[str, Any] | None = None,
135+
localns: dict[str, Any] | None = None,
131136
) -> dict[str, Any]:
132137
"""Return a dictionary containing type hints for a function, method, module or class
133138
object.
@@ -201,13 +206,15 @@ def restify(cls: type | None, mode: _RestifyMode = 'fully-qualified-except-typin
201206
elif ismock(cls):
202207
return f':py:class:`{modprefix}{cls.__module__}.{cls.__name__}`'
203208
elif is_invalid_builtin_class(cls):
209+
# The above predicate never raises TypeError but should not be
210+
# evaluated before determining whether *cls* is a mocked object
211+
# or not; instead of two try-except blocks, we keep it here.
204212
return f':py:class:`{modprefix}{_INVALID_BUILTIN_CLASSES[cls]}`'
205213
elif inspect.isNewType(cls):
206214
if sys.version_info[:2] >= (3, 10):
207215
# newtypes have correct module info since Python 3.10+
208216
return f':py:class:`{modprefix}{cls.__module__}.{cls.__name__}`'
209-
else:
210-
return f':py:class:`{cls.__name__}`'
217+
return f':py:class:`{cls.__name__}`'
211218
elif UnionType and isinstance(cls, UnionType):
212219
# Union types (PEP 585) retain their definition order when they
213220
# are printed natively and ``None``-like types are kept as is.
@@ -219,8 +226,7 @@ def restify(cls: type | None, mode: _RestifyMode = 'fully-qualified-except-typin
219226

220227
concatenated_args = ', '.join(restify(arg, mode) for arg in cls.__args__)
221228
return fr':py:class:`{cls.__name__}`\ [{concatenated_args}]'
222-
else:
223-
return f':py:class:`{cls.__name__}`'
229+
return f':py:class:`{cls.__name__}`'
224230
elif (inspect.isgenericalias(cls)
225231
and cls.__module__ == 'typing'
226232
and cls.__origin__ is Union): # type: ignore[attr-defined]
@@ -241,10 +247,9 @@ def restify(cls: type | None, mode: _RestifyMode = 'fully-qualified-except-typin
241247
elif all(is_system_TypeVar(a) for a in cls.__args__):
242248
# Suppress arguments if all system defined TypeVars (ex. Dict[KT, VT])
243249
pass
244-
elif (cls.__module__ == 'typing'
245-
and cls._name == 'Callable'): # type: ignore[attr-defined]
250+
elif cls.__module__ == 'typing' and cls._name == 'Callable': # type: ignore[attr-defined]
246251
args = ', '.join(restify(a, mode) for a in cls.__args__[:-1])
247-
text += fr"\ [[{args}], {restify(cls.__args__[-1], mode)}]"
252+
text += fr'\ [[{args}], {restify(cls.__args__[-1], mode)}]'
248253
elif cls.__module__ == 'typing' and getattr(origin, '_name', None) == 'Literal':
249254
args = ', '.join(_format_literal_arg_restify(a, mode=mode)
250255
for a in cls.__args__)
@@ -327,45 +332,45 @@ def stringify_annotation(
327332
else:
328333
module_prefix = ''
329334

330-
annotation_qualname = getattr(annotation, '__qualname__', '')
331-
annotation_module = getattr(annotation, '__module__', '')
332-
annotation_name = getattr(annotation, '__name__', '')
335+
# The values below must be strings if the objects are well-formed.
336+
annotation_qualname: str = getattr(annotation, '__qualname__', '')
337+
annotation_module: str = getattr(annotation, '__module__', '')
338+
annotation_name: str = getattr(annotation, '__name__', '')
333339
annotation_module_is_typing = annotation_module == 'typing'
334340

335341
if isinstance(annotation, TypeVar):
336342
if annotation_module_is_typing and mode in {'fully-qualified-except-typing', 'smart'}:
337343
return annotation_name
338-
else:
339-
return module_prefix + f'{annotation_module}.{annotation_name}'
344+
return module_prefix + f'{annotation_module}.{annotation_name}'
340345
elif isNewType(annotation):
341346
if sys.version_info[:2] >= (3, 10):
342347
# newtypes have correct module info since Python 3.10+
343348
return module_prefix + f'{annotation_module}.{annotation_name}'
344-
else:
345-
return annotation_name
349+
return annotation_name
346350
elif ismockmodule(annotation):
347351
return module_prefix + annotation_name
348352
elif ismock(annotation):
349353
return module_prefix + f'{annotation_module}.{annotation_name}'
350354
elif is_invalid_builtin_class(annotation):
351355
return module_prefix + _INVALID_BUILTIN_CLASSES[annotation]
352-
elif str(annotation).startswith('typing.Annotated'): # for py310+
356+
elif str(annotation).startswith('typing.Annotated'): # for py39+
353357
pass
354358
elif annotation_module == 'builtins' and annotation_qualname:
355-
if (args := getattr(annotation, '__args__', None)) is not None: # PEP 585 generic
356-
if not args: # Empty tuple, list, ...
357-
return repr(annotation)
358-
359-
concatenated_args = ', '.join(stringify_annotation(arg, mode) for arg in args)
360-
return f'{annotation_qualname}[{concatenated_args}]'
361-
else:
359+
args = getattr(annotation, '__args__', None)
360+
if args is None:
362361
return annotation_qualname
363362

363+
# PEP 585 generic
364+
if not args: # Empty tuple, list, ...
365+
return repr(annotation)
366+
concatenated_args = ', '.join(stringify_annotation(arg, mode) for arg in args)
367+
return f'{annotation_qualname}[{concatenated_args}]'
368+
364369
module_prefix = f'{annotation_module}.'
365-
annotation_forward_arg = getattr(annotation, '__forward_arg__', None)
370+
annotation_forward_arg: str | None = getattr(annotation, '__forward_arg__', None)
366371
if annotation_qualname or (annotation_module_is_typing and not annotation_forward_arg):
367372
if mode == 'smart':
368-
module_prefix = '~' + module_prefix
373+
module_prefix = f'~{module_prefix}'
369374
if annotation_module_is_typing and mode == 'fully-qualified-except-typing':
370375
module_prefix = ''
371376
else:

0 commit comments

Comments
 (0)