Migrate to py3 style type annotation: sphinx.util.inspect

This commit is contained in:
Takeshi KOMIYA 2019-04-18 16:47:06 +09:00
parent 316c61b172
commit 1fc0985df7

View File

@ -20,15 +20,12 @@ from inspect import ( # NOQA
isclass, ismethod, ismethoddescriptor, isroutine isclass, ismethod, ismethoddescriptor, isroutine
) )
from io import StringIO from io import StringIO
from typing import Any, Callable, Mapping, List, Tuple
from sphinx.deprecation import RemovedInSphinx30Warning from sphinx.deprecation import RemovedInSphinx30Warning
from sphinx.util import logging from sphinx.util import logging
from sphinx.util.typing import NoneType from sphinx.util.typing import NoneType
if False:
# For type annotation
from typing import Any, Callable, Mapping, List, Tuple, Type # NOQA
if sys.version_info > (3, 7): if sys.version_info > (3, 7):
from types import ( from types import (
ClassMethodDescriptorType, ClassMethodDescriptorType,
@ -114,26 +111,22 @@ def getargspec(func):
kwonlyargs, kwdefaults, annotations) kwonlyargs, kwdefaults, annotations)
def isenumclass(x): def isenumclass(x: Any) -> bool:
# type: (Type) -> bool
"""Check if the object is subclass of enum.""" """Check if the object is subclass of enum."""
return inspect.isclass(x) and issubclass(x, enum.Enum) return inspect.isclass(x) and issubclass(x, enum.Enum)
def isenumattribute(x): def isenumattribute(x: Any) -> bool:
# type: (Any) -> bool
"""Check if the object is attribute of enum.""" """Check if the object is attribute of enum."""
return isinstance(x, enum.Enum) return isinstance(x, enum.Enum)
def ispartial(obj): def ispartial(obj: Any) -> bool:
# type: (Any) -> bool
"""Check if the object is partial.""" """Check if the object is partial."""
return isinstance(obj, (partial, partialmethod)) return isinstance(obj, (partial, partialmethod))
def isclassmethod(obj): def isclassmethod(obj: Any) -> bool:
# type: (Any) -> bool
"""Check if the object is classmethod.""" """Check if the object is classmethod."""
if isinstance(obj, classmethod): if isinstance(obj, classmethod):
return True return True
@ -143,8 +136,7 @@ def isclassmethod(obj):
return False return False
def isstaticmethod(obj, cls=None, name=None): def isstaticmethod(obj: Any, cls: Any = None, name: str = None) -> bool:
# type: (Any, Any, str) -> bool
"""Check if the object is staticmethod.""" """Check if the object is staticmethod."""
if isinstance(obj, staticmethod): if isinstance(obj, staticmethod):
return True return True
@ -163,8 +155,7 @@ def isstaticmethod(obj, cls=None, name=None):
return False return False
def isdescriptor(x): def isdescriptor(x: Any) -> bool:
# type: (Any) -> bool
"""Check if the object is some kind of descriptor.""" """Check if the object is some kind of descriptor."""
for item in '__get__', '__set__', '__delete__': for item in '__get__', '__set__', '__delete__':
if hasattr(safe_getattr(x, item, None), '__call__'): if hasattr(safe_getattr(x, item, None), '__call__'):
@ -172,14 +163,12 @@ def isdescriptor(x):
return False return False
def isabstractmethod(obj): def isabstractmethod(obj: Any) -> bool:
# type: (Any) -> bool
"""Check if the object is an abstractmethod.""" """Check if the object is an abstractmethod."""
return safe_getattr(obj, '__isabstractmethod__', False) is True return safe_getattr(obj, '__isabstractmethod__', False) is True
def isattributedescriptor(obj): def isattributedescriptor(obj: Any) -> bool:
# type: (Any) -> bool
"""Check if the object is an attribute like descriptor.""" """Check if the object is an attribute like descriptor."""
if inspect.isdatadescriptor(object): if inspect.isdatadescriptor(object):
# data descriptor is kind of attribute # data descriptor is kind of attribute
@ -206,20 +195,17 @@ def isattributedescriptor(obj):
return False return False
def isfunction(obj): def isfunction(obj: Any) -> bool:
# type: (Any) -> bool
"""Check if the object is function.""" """Check if the object is function."""
return inspect.isfunction(obj) or ispartial(obj) and inspect.isfunction(obj.func) return inspect.isfunction(obj) or ispartial(obj) and inspect.isfunction(obj.func)
def isbuiltin(obj): def isbuiltin(obj: Any) -> bool:
# type: (Any) -> bool
"""Check if the object is builtin.""" """Check if the object is builtin."""
return inspect.isbuiltin(obj) or ispartial(obj) and inspect.isbuiltin(obj.func) return inspect.isbuiltin(obj) or ispartial(obj) and inspect.isbuiltin(obj.func)
def iscoroutinefunction(obj): def iscoroutinefunction(obj: Any) -> bool:
# type: (Any) -> bool
"""Check if the object is coroutine-function.""" """Check if the object is coroutine-function."""
if inspect.iscoroutinefunction(obj): if inspect.iscoroutinefunction(obj):
return True return True
@ -230,14 +216,12 @@ def iscoroutinefunction(obj):
return False return False
def isproperty(obj): def isproperty(obj: Any) -> bool:
# type: (Any) -> bool
"""Check if the object is property.""" """Check if the object is property."""
return isinstance(obj, property) return isinstance(obj, property)
def safe_getattr(obj, name, *defargs): def safe_getattr(obj: Any, name: str, *defargs) -> Any:
# type: (Any, str, Any) -> Any
"""A getattr() that turns all exceptions into AttributeErrors.""" """A getattr() that turns all exceptions into AttributeErrors."""
try: try:
return getattr(obj, name, *defargs) return getattr(obj, name, *defargs)
@ -259,8 +243,8 @@ def safe_getattr(obj, name, *defargs):
raise AttributeError(name) raise AttributeError(name)
def safe_getmembers(object, predicate=None, attr_getter=safe_getattr): def safe_getmembers(object: Any, predicate: Callable[[str], bool] = None,
# type: (Any, Callable[[str], bool], Callable) -> List[Tuple[str, Any]] attr_getter: Callable = safe_getattr) -> List[Tuple[str, Any]]:
"""A version of inspect.getmembers() that uses safe_getattr().""" """A version of inspect.getmembers() that uses safe_getattr()."""
results = [] # type: List[Tuple[str, Any]] results = [] # type: List[Tuple[str, Any]]
for key in dir(object): for key in dir(object):
@ -274,8 +258,7 @@ def safe_getmembers(object, predicate=None, attr_getter=safe_getattr):
return results return results
def object_description(object): def object_description(object: Any) -> str:
# type: (Any) -> str
"""A repr() implementation that returns text safe to use in reST context.""" """A repr() implementation that returns text safe to use in reST context."""
if isinstance(object, dict): if isinstance(object, dict):
try: try:
@ -312,8 +295,7 @@ def object_description(object):
return s.replace('\n', ' ') return s.replace('\n', ' ')
def is_builtin_class_method(obj, attr_name): def is_builtin_class_method(obj: Any, attr_name: str) -> bool:
# type: (Any, str) -> bool
"""If attr_name is implemented at builtin class, return True. """If attr_name is implemented at builtin class, return True.
>>> is_builtin_class_method(int, '__init__') >>> is_builtin_class_method(int, '__init__')
@ -339,8 +321,8 @@ class Parameter:
VAR_KEYWORD = 4 VAR_KEYWORD = 4
empty = object() empty = object()
def __init__(self, name, kind=POSITIONAL_OR_KEYWORD, default=empty): def __init__(self, name: str, kind: int = POSITIONAL_OR_KEYWORD,
# type: (str, int, Any) -> None default: Any = empty) -> None:
self.name = name self.name = name
self.kind = kind self.kind = kind
self.default = default self.default = default
@ -355,8 +337,8 @@ class Signature:
its return annotation. its return annotation.
""" """
def __init__(self, subject, bound_method=False, has_retval=True): def __init__(self, subject: Callable, bound_method: bool = False,
# type: (Callable, bool, bool) -> None has_retval: bool = True) -> None:
# check subject is not a built-in class (ex. int, str) # check subject is not a built-in class (ex. int, str)
if (isinstance(subject, type) and if (isinstance(subject, type) and
is_builtin_class_method(subject, "__new__") and is_builtin_class_method(subject, "__new__") and
@ -401,16 +383,14 @@ class Signature:
self.skip_first_argument = False self.skip_first_argument = False
@property @property
def parameters(self): def parameters(self) -> Mapping:
# type: () -> Mapping
if self.partialmethod_with_noargs: if self.partialmethod_with_noargs:
return {} return {}
else: else:
return self.signature.parameters return self.signature.parameters
@property @property
def return_annotation(self): def return_annotation(self) -> Any:
# type: () -> Any
if self.signature: if self.signature:
if self.has_retval: if self.has_retval:
return self.signature.return_annotation return self.signature.return_annotation
@ -419,8 +399,7 @@ class Signature:
else: else:
return None return None
def format_args(self, show_annotation=True): def format_args(self, show_annotation: bool = True) -> str:
# type: (bool) -> str
args = [] args = []
last_kind = None last_kind = None
for i, param in enumerate(self.parameters.values()): for i, param in enumerate(self.parameters.values()):
@ -475,8 +454,7 @@ class Signature:
return '(%s) -> %s' % (', '.join(args), annotation) return '(%s) -> %s' % (', '.join(args), annotation)
def format_annotation(self, annotation): def format_annotation(self, annotation: Any) -> str:
# type: (Any) -> str
"""Return formatted representation of a type annotation. """Return formatted representation of a type annotation.
Show qualified names for types and additional details for types from Show qualified names for types and additional details for types from
@ -502,8 +480,7 @@ class Signature:
else: else:
return self.format_annotation_old(annotation) return self.format_annotation_old(annotation)
def format_annotation_new(self, annotation): def format_annotation_new(self, annotation: Any) -> str:
# type: (Any) -> str
"""format_annotation() for py37+""" """format_annotation() for py37+"""
module = getattr(annotation, '__module__', None) module = getattr(annotation, '__module__', None)
if module == 'typing': if module == 'typing':
@ -539,8 +516,7 @@ class Signature:
return qualname return qualname
def format_annotation_old(self, annotation): def format_annotation_old(self, annotation: Any) -> str:
# type: (Any) -> str
"""format_annotation() for py36 or below""" """format_annotation() for py36 or below"""
module = getattr(annotation, '__module__', None) module = getattr(annotation, '__module__', None)
if module == 'typing': if module == 'typing':
@ -641,8 +617,8 @@ class Signature:
return qualname return qualname
def getdoc(obj, attrgetter=safe_getattr, allow_inherited=False): def getdoc(obj: Any, attrgetter: Callable = safe_getattr,
# type: (Any, Callable, bool) -> str allow_inherited: bool = False) -> str:
"""Get the docstring for the object. """Get the docstring for the object.
This tries to obtain the docstring for some kind of objects additionally: This tries to obtain the docstring for some kind of objects additionally: