Skip to content

Instantly share code, notes, and snippets.

@johntyree
Created January 24, 2014 20:15
Show Gist options
  • Save johntyree/8605391 to your computer and use it in GitHub Desktop.
Save johntyree/8605391 to your computer and use it in GitHub Desktop.
A not so great hack to check types at runtime.
#!/usr/bin/env python
# coding: utf8
# GistID: 8605391
""" Add type checking decorators to functions.
@in_types(int, str)
@out_types(str)
def mul(a, b):
return a * b
mul(3, 'x')
"""
from __future__ import division
from functools import wraps
def check(value, expected, msg):
if expected is None:
expected = type(expected)
if not isinstance(value, expected):
msg = msg.format(type(value), value, expected)
raise TypeError(msg)
def check_len(a, b, msg):
if len(a) != len(b):
raise TypeError(msg.format(len(a), len(b)))
def in_types(*args, **kwargs):
def decorator(f): # noqa
prefix = f.func_name + "() argument {}: "
msg = "{} {} is not of type {}"
lenprefix = f.func_name + "() signature: "
lenmsg = "requires {} arguments, called with {} arguments."
@wraps(f)
def new_f(*a, **k):
errmsg = lenprefix + lenmsg
check_len(args, a, errmsg)
for i, (arg, typ) in enumerate(zip(a, args)):
errmsg = prefix.format(i+1) + msg
check(arg, typ, errmsg)
for key, val in k.items():
if key in kwargs:
check(val, kwargs[key], msg)
ret = f(*a, **k)
return ret
return new_f
return decorator
def out_types(return_type):
def decorator(f): # noqa
prefix = f.func_name + "() return value:"
msg = "{} {} is not of type {}"
errmsg = prefix + msg
@wraps(f)
def new_f(*a, **k):
ret = f(*a, **k)
check(ret, return_type, errmsg)
print f.func_name + "(): OK!"
return ret
return new_f
return decorator
try:
@in_types(int, str)
@out_types(None)
def too_many(a, b, c):
return
too_many(1, '', 3)
except TypeError as e:
print e
try:
@in_types(int, str)
@out_types(None)
def too_few():
return
too_few()
except TypeError as e:
print e
try:
@in_types(int, str)
@out_types(None)
def bad_in_types_type(a, b):
return
bad_in_types_type(0, 2)
except TypeError as e:
print e
try:
@in_types(int, str)
@out_types(None)
def bad_return_type(a, b):
return 0
bad_return_type(0, '')
except TypeError as e:
print e
@in_types(int, str)
@out_types(tuple)
def well_typed(a, b):
return (a, b)
well_typed(0, '')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment