Skip to content

Instantly share code, notes, and snippets.

@miraculixx
Last active December 29, 2017 15:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save miraculixx/01410a6a874a1cd2954b927ac2488435 to your computer and use it in GitHub Desktop.
Save miraculixx/01410a6a874a1cd2954b927ac2488435 to your computer and use it in GitHub Desktop.
type checking for python functions. this is way better than PEP 484 type hints and it works for Python 2.x and Python 3.x
from typecheck import typecheck
@typecheck((int, int), dict(c=(int, type(None))), int)
def foo(a, b, c=None):
print("hello", a, b)
return 5
typecheck.active = False
@typecheck((int, int), dict(c=(int, type(None))), str)
def foox(a, b, c=None):
print("hello", a, b)
return 5
# foo has typecheck enabled
foo(1, 2, c=5)
# foox does not have type check enabled
foox('1', '2', '3')
def typecheck(argstypes=[], kwargstypes={},
returntype=(str,dict,int,float,list,tuple,set,object,type(typecheck),type(None))):
"""
Assert types of arguments to functions and methods
Usage:
On any function use the @typecheck decorater
@typecheck((int, int))
def foo(a, b):
...
The decorator accepts three arguments:
argstypes: tuple of types
kwargstypes: dict of kwarg:tuple of types
returntype: tuple of return types
The default for each is to accept any type.
For methods, use the object type as the first argument to match self:
class Bar:
@typecheck((object, int, int))
def foo(self, a, b):
...
If you can't use the decorator for some reason, typecheck also works inside functions:
def internal(a, b, c):
typecheck((int, int, int)).ins(a, b, c)
result = 5
return typecheck(returntype=int).out(result)
If you need to use *args and **kwargs:
def internal2(*args, **kwargs):
(a, b, c), kwargs = typecheck((int, int, int)).ins(*args, **kwargs)
...
Notes:
typecheck works at run time and thus has some overhead. To deactivate typechecking in
production, set typecheck.active = False in your application's main entry point.
"""
def check_in(*args, **kwargs):
for i, arg in enumerate(args):
msg = "Expected arg {} to be of type {} got {}".format(i, argstypes[i], type(arg))
assert isinstance(arg, argstypes[i]), msg
for kwarg in kwargs.iteritems():
kw, val = kwarg
msg = "Expected kwarg {} to be of type {} got {}".format(kw, kwargstypes[kw], type(val))
assert isinstance(val, kwargstypes[kw]), msg
return args, kwargs
def check_out(result):
msg = "Expected result to be of type {} got {}".format(returntype, type(result))
assert isinstance(result, returntype), msg
return result
def wrap(func):
if not getattr(typecheck, 'active', True):
return func
def check(*args, **kwargs):
check_in(*args, **kwargs)
result = func(*args, **kwargs)
check_out(result)
return result
return check
wrap.ins = check_in
wrap.out = check_out
return wrap
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment