Play around with function annotations to implement a crude type checker.
parent
f913d4fc63
commit
e222046269
@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env python3
|
||||
# Play around with function annotations to implement a crude type checker.
|
||||
|
||||
import inspect
|
||||
|
||||
|
||||
def typechecked(func):
|
||||
wrapped_func = func
|
||||
|
||||
def typecheck(*args, **kvargs):
|
||||
parameters = inspect.signature(wrapped_func).parameters
|
||||
wants = [(par, parameters[par].annotation) for par in parameters]
|
||||
for want, arg in zip(wants, args):
|
||||
name, class_ = want
|
||||
if not isinstance(arg, class_):
|
||||
raise TypeError("arg {} is not "
|
||||
"an instance of {}".format(name, class_))
|
||||
|
||||
return_ = wrapped_func(*args, **kvargs)
|
||||
class_ = wrapped_func.__annotations__["return"]
|
||||
if not isinstance(return_, class_):
|
||||
raise TypeError("return value is not "
|
||||
"an instance of {}".format(class_))
|
||||
return return_
|
||||
|
||||
typecheck.__doc__ = wrapped_func.__doc__
|
||||
return typecheck
|
||||
|
||||
|
||||
@typechecked
|
||||
def greet(name: str, age: int, fnord: str=None) -> str:
|
||||
"""Greet someone.
|
||||
|
||||
>>> greet("Mike", 12)
|
||||
'Hello Mike, you are 12 years old'
|
||||
>>> greet("Florian", "eins")
|
||||
Traceback (most recent call last):
|
||||
File "func_annotations.py", line 14, in typecheck
|
||||
"is not an instance of {}".format(name, class_))
|
||||
TypeError: arg age is not an instance of <class 'int'>
|
||||
"""
|
||||
return 'Hello {0}, you are {1} years old'.format(name, age)
|
||||
|
||||
|
||||
@typechecked
|
||||
def test(foo: int) -> str:
|
||||
""" Just a test.
|
||||
|
||||
>>> test(1)
|
||||
Traceback (most recent call last):
|
||||
File "func_annotations.py", line 21, in typecheck
|
||||
"is not an instance of {}".format(class_))
|
||||
TypeError: return value is not an instance of <class 'str'>
|
||||
"""
|
||||
return 1
|
||||
|
||||
import doctest
|
||||
doctest.testmod()
|
Loading…
Reference in New Issue