mirror of
https://github.com/pocketpy/pocketpy
synced 2026-08-06 22:27:11 +08:00
Update inspect.signature with annotations
This commit is contained in:
parent
e803108eab
commit
56ba5f7f83
@ -11,15 +11,20 @@ class Parameter:
|
||||
|
||||
empty = _empty
|
||||
|
||||
def __init__(self, name, kind, *default):
|
||||
def __init__(self, name, kind, *default, annotation=None):
|
||||
self.name = name
|
||||
self.kind = kind
|
||||
# pocketpy only allows literal defaults, so use *default as sentinel
|
||||
self.default = default[0] if default else _empty
|
||||
self.annotation = _empty if annotation is None else annotation
|
||||
|
||||
def __str__(self):
|
||||
res = self.name
|
||||
if self.default is not _empty:
|
||||
if self.annotation is not _empty:
|
||||
res += ': ' + self.annotation
|
||||
if self.default is not _empty:
|
||||
res += ' = ' + repr(self.default)
|
||||
elif self.default is not _empty:
|
||||
res += '=' + repr(self.default)
|
||||
if self.kind == Parameter.VAR_POSITIONAL:
|
||||
res = '*' + res
|
||||
@ -34,25 +39,34 @@ class Parameter:
|
||||
class Signature:
|
||||
empty = _empty
|
||||
|
||||
def __init__(self, parameters):
|
||||
def __init__(self, parameters, return_annotation=None):
|
||||
self.parameters = {p.name: p for p in parameters}
|
||||
self.return_annotation = _empty if return_annotation is None else return_annotation
|
||||
|
||||
def __str__(self):
|
||||
return '(' + ', '.join([str(p) for p in self.parameters.values()]) + ')'
|
||||
res = '(' + ', '.join([str(p) for p in self.parameters.values()]) + ')'
|
||||
if self.return_annotation is not _empty:
|
||||
res += ' -> ' + self.return_annotation
|
||||
return res
|
||||
|
||||
def __repr__(self):
|
||||
return '<Signature ' + str(self) + '>'
|
||||
|
||||
|
||||
def _make_params(func):
|
||||
return [Parameter(*entry) for entry in _signature_data(func)]
|
||||
def _from_function(func, drop_first):
|
||||
annotations = func.__annotations__
|
||||
params = [Parameter(*entry, annotation=annotations.get(entry[0]))
|
||||
for entry in _signature_data(func)]
|
||||
if drop_first:
|
||||
params = params[1:]
|
||||
return Signature(params, annotations.get('return'))
|
||||
|
||||
|
||||
def signature(obj):
|
||||
if not callable(obj):
|
||||
raise TypeError(repr(obj) + ' is not a callable object')
|
||||
if isinstance(obj, type):
|
||||
return Signature(_make_params(obj.__init__)[1:])
|
||||
return _from_function(obj.__init__, True)
|
||||
if hasattr(obj, '__func__'):
|
||||
return Signature(_make_params(obj.__func__)[1:])
|
||||
return Signature(_make_params(obj))
|
||||
return _from_function(obj.__func__, True)
|
||||
return _from_function(obj, False)
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -182,6 +182,8 @@ except TypeError:
|
||||
pass
|
||||
|
||||
# ---------------- __annotations__ ----------------
|
||||
from inspect import Signature
|
||||
|
||||
def h1(a: int, *args: int, b: str = 'x', c: float = 1.5, **kwargs: str) -> bool:
|
||||
pass
|
||||
|
||||
@ -194,10 +196,16 @@ assert h1.__annotations__ == {
|
||||
'return': 'bool',
|
||||
}
|
||||
|
||||
sig = signature(h1)
|
||||
assert sig.parameters['a'].annotation == 'int'
|
||||
assert sig.return_annotation == 'bool'
|
||||
assert str(sig) == "(a: int, *args: int, b: str = 'x', c: float = 1.5, **kwargs: str) -> bool"
|
||||
|
||||
def h2(a, b: int, c=1):
|
||||
pass
|
||||
|
||||
assert h2.__annotations__ == {'b': 'int'}
|
||||
assert str(signature(h2)) == '(a, b: int, c=1)'
|
||||
|
||||
# complex annotation expressions are preserved as written
|
||||
def h3(p: list[int], q: dict[str, int]) -> 'A | None':
|
||||
@ -205,4 +213,15 @@ def h3(p: list[int], q: dict[str, int]) -> 'A | None':
|
||||
|
||||
assert h3.__annotations__ == {'p': 'list[int]', 'q': 'dict[str, int]', 'return': "'A | None'"}
|
||||
|
||||
class D:
|
||||
def m(self, x: int) -> str:
|
||||
return str(x)
|
||||
|
||||
sig = signature(D().m)
|
||||
assert sig.parameters['x'].annotation == 'int'
|
||||
assert sig.return_annotation == 'str'
|
||||
|
||||
assert (lambda x: x).__annotations__ == {}
|
||||
sig = signature(lambda x: x)
|
||||
assert sig.parameters['x'].annotation is Parameter.empty
|
||||
assert sig.return_annotation is Signature.empty
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user