-
Notifications
You must be signed in to change notification settings - Fork 16
/
typed_signature.py
66 lines (50 loc) · 1.65 KB
/
typed_signature.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
"""
A wrapper around inspect.signature that knows what kind of type it came from.
This is useful for when we care about the distinction between different kinds
of callables, e.g., between methods, classmethods, and staticmethods.
"""
import types
from .compat import signature, unwrap
from .default import default
class TypedSignature(object):
"""
Wrapper around an inspect.Signature that knows what kind of callable it came from.
Parameters
----------
obj : callable
An object from which to extract a signature and a type.
"""
def __init__(self, obj):
self._type = type(obj)
if self._type is default:
self._type = type(obj.implementation)
self._signature = signature(extract_func(obj))
@property
def signature(self):
return self._signature
@property
def first_argument_name(self):
try:
return next(iter(self.signature.parameters))
except StopIteration:
return None
@property
def type(self):
return self._type
def __str__(self):
return str(self._signature)
BUILTIN_FUNCTION_TYPES = (types.FunctionType, types.BuiltinFunctionType)
def _inner_extract_func(obj):
if isinstance(obj, BUILTIN_FUNCTION_TYPES):
# Fast path, since this is the most likely case.
return obj
elif isinstance(obj, (classmethod, staticmethod)):
return obj.__func__
elif isinstance(obj, property):
return obj.fget
elif isinstance(obj, default):
return _inner_extract_func(obj.implementation)
else:
return obj
def extract_func(obj):
return unwrap(_inner_extract_func(obj))