diff options
Diffstat (limited to 'sphinx/util/inspect.py')
-rw-r--r-- | sphinx/util/inspect.py | 174 |
1 files changed, 20 insertions, 154 deletions
diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py index 1ce5bb900..2d665c1a6 100644 --- a/sphinx/util/inspect.py +++ b/sphinx/util/inspect.py @@ -21,8 +21,9 @@ from inspect import ( # NOQA from io import StringIO from typing import Any, Callable, Mapping, List, Tuple +from sphinx.deprecation import RemovedInSphinx40Warning from sphinx.util import logging -from sphinx.util.typing import NoneType +from sphinx.util.typing import stringify as stringify_annotation if sys.version_info > (3, 7): from types import ( @@ -381,11 +382,11 @@ class Signature: return None def format_args(self, show_annotation: bool = True) -> str: - def format_param_annotation(param: inspect.Parameter) -> str: + def get_annotation(param: inspect.Parameter) -> Any: if isinstance(param.annotation, str) and param.name in self.annotations: - return self.format_annotation(self.annotations[param.name]) + return self.annotations[param.name] else: - return self.format_annotation(param.annotation) + return param.annotation args = [] last_kind = None @@ -409,7 +410,7 @@ class Signature: arg.write(param.name) if show_annotation and param.annotation is not param.empty: arg.write(': ') - arg.write(format_param_annotation(param)) + arg.write(stringify_annotation(get_annotation(param))) if param.default is not param.empty: if param.annotation is param.empty or show_annotation is False: arg.write('=') @@ -422,13 +423,13 @@ class Signature: arg.write(param.name) if show_annotation and param.annotation is not param.empty: arg.write(': ') - arg.write(format_param_annotation(param)) + arg.write(stringify_annotation(get_annotation(param))) elif param.kind == param.VAR_KEYWORD: arg.write('**') arg.write(param.name) if show_annotation and param.annotation is not param.empty: arg.write(': ') - arg.write(format_param_annotation(param)) + arg.write(stringify_annotation(get_annotation(param))) args.append(arg.getvalue()) last_kind = param.kind @@ -437,164 +438,29 @@ class Signature: return '(%s)' % ', '.join(args) else: if 'return' in self.annotations: - annotation = self.format_annotation(self.annotations['return']) + annotation = stringify_annotation(self.annotations['return']) else: - annotation = self.format_annotation(self.return_annotation) + annotation = stringify_annotation(self.return_annotation) return '(%s) -> %s' % (', '.join(args), annotation) def format_annotation(self, annotation: Any) -> str: - """Return formatted representation of a type annotation. - - Show qualified names for types and additional details for types from - the ``typing`` module. - - Displaying complex types from ``typing`` relies on its private API. - """ - if isinstance(annotation, str): - return annotation - elif isinstance(annotation, typing.TypeVar): # type: ignore - return annotation.__name__ - elif not annotation: - return repr(annotation) - elif annotation is NoneType: # type: ignore - return 'None' - elif getattr(annotation, '__module__', None) == 'builtins': - return annotation.__qualname__ - elif annotation is Ellipsis: - return '...' - - if sys.version_info >= (3, 7): # py37+ - return self.format_annotation_new(annotation) - else: - return self.format_annotation_old(annotation) + """Return formatted representation of a type annotation.""" + warnings.warn('format_annotation() is deprecated', + RemovedInSphinx40Warning) + return stringify_annotation(annotation) def format_annotation_new(self, annotation: Any) -> str: """format_annotation() for py37+""" - module = getattr(annotation, '__module__', None) - if module == 'typing': - if getattr(annotation, '_name', None): - qualname = annotation._name - elif getattr(annotation, '__qualname__', None): - qualname = annotation.__qualname__ - elif getattr(annotation, '__forward_arg__', None): - qualname = annotation.__forward_arg__ - else: - qualname = self.format_annotation(annotation.__origin__) # ex. Union - elif hasattr(annotation, '__qualname__'): - qualname = '%s.%s' % (module, annotation.__qualname__) - else: - qualname = repr(annotation) - - if getattr(annotation, '__args__', None): - if qualname == 'Union': - if len(annotation.__args__) == 2 and annotation.__args__[1] is NoneType: # type: ignore # NOQA - return 'Optional[%s]' % self.format_annotation(annotation.__args__[0]) - else: - args = ', '.join(self.format_annotation(a) for a in annotation.__args__) - return '%s[%s]' % (qualname, args) - elif qualname == 'Callable': - args = ', '.join(self.format_annotation(a) for a in annotation.__args__[:-1]) - returns = self.format_annotation(annotation.__args__[-1]) - return '%s[[%s], %s]' % (qualname, args, returns) - elif annotation._special: - return qualname - else: - args = ', '.join(self.format_annotation(a) for a in annotation.__args__) - return '%s[%s]' % (qualname, args) - - return qualname + warnings.warn('format_annotation_new() is deprecated', + RemovedInSphinx40Warning) + return stringify_annotation(annotation) def format_annotation_old(self, annotation: Any) -> str: """format_annotation() for py36 or below""" - module = getattr(annotation, '__module__', None) - if module == 'typing': - if getattr(annotation, '_name', None): - qualname = annotation._name - elif getattr(annotation, '__qualname__', None): - qualname = annotation.__qualname__ - elif getattr(annotation, '__forward_arg__', None): - qualname = annotation.__forward_arg__ - elif getattr(annotation, '__origin__', None): - qualname = self.format_annotation(annotation.__origin__) # ex. Union - else: - qualname = repr(annotation).replace('typing.', '') - elif hasattr(annotation, '__qualname__'): - qualname = '%s.%s' % (module, annotation.__qualname__) - else: - qualname = repr(annotation) - - if (isinstance(annotation, typing.TupleMeta) and # type: ignore - not hasattr(annotation, '__tuple_params__')): # for Python 3.6 - params = annotation.__args__ - if params: - param_str = ', '.join(self.format_annotation(p) for p in params) - return '%s[%s]' % (qualname, param_str) - else: - return qualname - elif isinstance(annotation, typing.GenericMeta): - params = None - if hasattr(annotation, '__args__'): - # for Python 3.5.2+ - if annotation.__args__ is None or len(annotation.__args__) <= 2: # type: ignore # NOQA - params = annotation.__args__ # type: ignore - else: # typing.Callable - args = ', '.join(self.format_annotation(arg) for arg - in annotation.__args__[:-1]) # type: ignore - result = self.format_annotation(annotation.__args__[-1]) # type: ignore - return '%s[[%s], %s]' % (qualname, args, result) - elif hasattr(annotation, '__parameters__'): - # for Python 3.5.0 and 3.5.1 - params = annotation.__parameters__ # type: ignore - if params is not None: - param_str = ', '.join(self.format_annotation(p) for p in params) - return '%s[%s]' % (qualname, param_str) - elif (hasattr(typing, 'UnionMeta') and - isinstance(annotation, typing.UnionMeta) and # type: ignore - hasattr(annotation, '__union_params__')): # for Python 3.5 - params = annotation.__union_params__ - if params is not None: - if len(params) == 2 and params[1] is NoneType: # type: ignore - return 'Optional[%s]' % self.format_annotation(params[0]) - else: - param_str = ', '.join(self.format_annotation(p) for p in params) - return '%s[%s]' % (qualname, param_str) - elif (hasattr(annotation, '__origin__') and - annotation.__origin__ is typing.Union): # for Python 3.5.2+ - params = annotation.__args__ - if params is not None: - if len(params) == 2 and params[1] is NoneType: # type: ignore - return 'Optional[%s]' % self.format_annotation(params[0]) - else: - param_str = ', '.join(self.format_annotation(p) for p in params) - return 'Union[%s]' % param_str - elif (isinstance(annotation, typing.CallableMeta) and # type: ignore - getattr(annotation, '__args__', None) is not None and - hasattr(annotation, '__result__')): # for Python 3.5 - # Skipped in the case of plain typing.Callable - args = annotation.__args__ - if args is None: - return qualname - elif args is Ellipsis: - args_str = '...' - else: - formatted_args = (self.format_annotation(a) for a in args) - args_str = '[%s]' % ', '.join(formatted_args) - return '%s[%s, %s]' % (qualname, - args_str, - self.format_annotation(annotation.__result__)) - elif (isinstance(annotation, typing.TupleMeta) and # type: ignore - hasattr(annotation, '__tuple_params__') and - hasattr(annotation, '__tuple_use_ellipsis__')): # for Python 3.5 - params = annotation.__tuple_params__ - if params is not None: - param_strings = [self.format_annotation(p) for p in params] - if annotation.__tuple_use_ellipsis__: - param_strings.append('...') - return '%s[%s]' % (qualname, - ', '.join(param_strings)) - - return qualname + warnings.warn('format_annotation_old() is deprecated', + RemovedInSphinx40Warning) + return stringify_annotation(annotation) def getdoc(obj: Any, attrgetter: Callable = safe_getattr, |