Skip to content

Instantly share code, notes, and snippets.

@pedro823
Last active October 8, 2018 18:30
Show Gist options
  • Save pedro823/0674cd9c6223c5ae2c2b3138b8da10a8 to your computer and use it in GitHub Desktop.
Save pedro823/0674cd9c6223c5ae2c2b3138b8da10a8 to your computer and use it in GitHub Desktop.
Type Checker decorator in python
from functools import wraps
# Definitions
def __precheck_types(func_annotations, *args, **kwargs):
annotations = dict((argument, value_type)
for argument, value_type in func_annotations.items()
if argument != 'return')
for arg, value in kwargs.items():
if arg not in annotations:
continue
if not isinstance(value, annotations[arg]):
raise TypeError(f'value \'{value}\' is not of '
+ f'type {annotations[arg]}')
del annotations[arg]
for expected_type, value in zip(annotations.values(), args):
if not isinstance(value, expected_type):
raise TypeError(f'value \'{value}\' is not of '
+ f'type {expected_type}')
def type_checked(bound: bool = False):
def decorator(func):
has_return_type = 'return' in func.__annotations__
return_type = func.__annotations__.get('return', None.__class__)
if bound:
@wraps(func)
def func_wrapper(self, *args, **kwargs):
__precheck_types(func.__annotations__, *args, **kwargs)
result = func(self, *args, **kwargs)
if has_return_type:
if not isinstance(result, return_type):
raise TypeError('return type is not of '
+ f'type {return_type}')
return result
else:
@wraps(func)
def func_wrapper(*args, **kwargs):
__precheck_types(func.__annotations__, *args, **kwargs)
result = func(*args, **kwargs)
if has_return_type:
if not isinstance(result, return_type):
raise TypeError('return type is not of '
+ f'type {return_type}')
return result
return func_wrapper
return decorator
# Usage
if __name__ == '__main__':
@type_checked()
def f(a: str, b: int):
return a * b
class A:
@type_checked(bound=True)
def g(self, a: str):
return 4 * a
@type_checked(bound=False)
def h(a: str, *args) -> tuple:
s = a
for arg in args:
s += arg
return s, 2
print(h('a', 'b', 'c', 'd'))
print(f('a', 2))
print(f(b=2, a='f'))
print(f('c', b=2))
try:
print(f(2, 3))
except Exception as e:
print(str(e))
x = A()
print(x.g('23'))
try:
print(x.g(23))
except Exception as e:
print(str(e))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment