Skip to content

Instantly share code, notes, and snippets.

@pirate
Created March 27, 2019 02:45
Show Gist options
  • Save pirate/27b5437a92feb7c25b775d4f1ef753d7 to your computer and use it in GitHub Desktop.
Save pirate/27b5437a92feb7c25b775d4f1ef753d7 to your computer and use it in GitHub Desktop.
# This is a decorator that checks the function parameters as runtime against their type hints.
#
# @enforce_types
# def example(a: str, b: int):
# return 'Success!'
#
# if __name__ == '__main__':
# example('abc', 123)
# example(123, 'abc') # this throws a TypeError
def enforce_types(func):
"""
Enforce function arg and kwarg types at runtime using its python3 type hints
"""
# TODO: check return type as well
@wraps(func)
def typechecked_function(*args, **kwargs):
sig = signature(func)
def check_argument_type(arg_key, arg_val):
try:
annotation = sig.parameters[arg_key].annotation
except KeyError:
annotation = _empty
if annotation is not _empty and annotation.__class__ is type:
if not isinstance(arg_val, annotation):
raise TypeError(
'{}(..., {}: {}) got unexpected {} argument {}={}'.format(
func.__name__,
arg_key,
annotation.__name__,
type(arg_val).__name__,
arg_key,
arg_val,
)
)
# check args
for arg_val, arg_key in zip(args, sig.parameters):
check_argument_type(arg_key, arg_val)
# check kwargs
for arg_key, arg_val in kwargs.items():
check_argument_type(arg_key, arg_val)
return func(*args, **kwargs)
return typechecked_function
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment