Skip to content

Instantly share code, notes, and snippets.

@kgadek
Created January 29, 2014 01:55
Show Gist options
  • Save kgadek/8680382 to your computer and use it in GitHub Desktop.
Save kgadek/8680382 to your computer and use it in GitHub Desktop.
TurboDynoChecker - checking types in runtime via type annotations (PEP-3107)
from contextlib import contextmanager
from functools import wraps
from inspect import signature
from itertools import chain
class TypoDynoMismatch(Exception):
pass
def turbodynocheck(fn):
@contextmanager
def exception_map(e_from, e_to, e_ignored=None):
try:
yield
except e_ignored:
pass
except e_from:
raise e_to
@wraps(fn)
def wrapper(*args, **kwargs):
anns = fn.__annotations__
for key, val in chain(zip(signature(fn).parameters, args),
kwargs.items()):
with exception_map(e_from=ValueError, e_to=TypoDynoMismatch, e_ignored=KeyError):
if type(val) != anns[key] and anns[key](val) is not True:
msg = "Function {0} argument {1} :: {2}. Given {3} :: {4}".format(fn.__name__,
key,
anns[key],
val,
type(val))
raise TypoDynoMismatch(msg)
res = fn(*args, **kwargs)
with exception_map(e_from=ValueError, e_to=TypoDynoMismatch, e_ignored=KeyError):
if type(res) != anns['return'] and anns['return'](res) is not True:
msg = "Function {0} :: ... -> {1} but it returned ({2} :: {3})".format(fn.__name__,
anns['return'],
res,
type(res))
raise TypoDynoMismatch(msg)
return res
return wrapper
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment