Created
January 4, 2020 21:40
-
-
Save tweekmonster/6e2e528faa7f2583eb88c9ebb3aac786 to your computer and use it in GitHub Desktop.
Decorator for enforcing strict type annotations on functions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import typing | |
import inspect | |
import functools | |
def strict_types(func: typing.Callable): | |
"""Decorator for enforcing strict type annotations""" | |
argspec = inspect.getfullargspec(func) | |
ret_type = argspec.annotations.pop('return', None) | |
@functools.wraps(func) | |
def wrapper(*args, **kwargs): | |
for arg, cls in argspec.annotations.items(): | |
if arg in kwargs: | |
val = kwargs.get(arg) | |
else: | |
try: | |
i = argspec.args.index(arg) | |
val = args[i] | |
except ValueError: | |
continue | |
if val is not None and not isinstance(val, cls): | |
raise ValueError('Expected %r to be of type %r, ' | |
'but got %r instead' % (arg, cls.__name__, | |
val.__class__.__name__)) | |
ret_val = func(*args, **kwargs) | |
if ret_type and ret_val is not None and not isinstance(ret_val, ret_type): | |
raise ValueError('Expected return value to be of type %r, ' | |
'but got %r instead' % (cls.__name__, | |
ret_val.__class__.__name__)) | |
return wrapper |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment