Skip to content

Instantly share code, notes, and snippets.

@minus7
Created February 14, 2015 21:37
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 minus7/e0786917c7349e9a74bf to your computer and use it in GitHub Desktop.
Save minus7/e0786917c7349e9a74bf to your computer and use it in GitHub Desktop.
Python Type-Checking Decorator
# Check if a function's arguments are instances of a (set of) type(s):
# >>> @type_checked
# >>> def test(asdf: str):
# >>> print(type(asdf))
# >>> test(3)
# ValueError: Argument asdf should be of type str but is int
# Using @type_checked_cast instead of @type_checked tries
# casting the argument to the desired type:
# >>> @type_checked_cast
# >>> def test(asdf: str):
# >>> print(type(asdf))
# >>> test(3)
# <class 'str'>
from collections.abc import Iterable
from functools import wraps
from inspect import signature
def type_checked(func):
@wraps(func)
def wrapper(*args, **kwargs):
sig = signature(func)
bound = sig.bind(*args, **kwargs)
for k,v in bound.arguments.items():
ann = sig.parameters[k].annotation
if isinstance(ann, type):
ann = (ann,)
if isinstance(ann, Iterable):
for anni in ann:
if anni is sig.empty:
continue
if isinstance(anni, type) and not isinstance(v, anni):
raise ValueError("Argument {} should be of type {} but is {}"
.format(k, ann.__name__, type(v).__name__))
else:
# ignore non-type annotations
pass
else:
# ignore non-type, non-Container annotations
pass
return func(*bound.args, **bound.kwargs)
return wrapper
def type_checked_cast(func):
@wraps(func)
def wrapper(*args, **kwargs):
sig = signature(func)
bound = sig.bind(*args, **kwargs)
for k,v in bound.arguments.items():
ann = sig.parameters[k].annotation
if isinstance(ann, type):
ann = (ann,)
if isinstance(ann, Iterable):
for anni in ann:
if anni is sig.empty:
continue
if isinstance(anni, type) and not isinstance(v, anni):
bound.arguments[k] = anni(v)
else:
# ignore non-type annotations
pass
else:
# ignore non-type, non-Container annotations
pass
return func(*bound.args, **bound.kwargs)
return wrapper
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment