Skip to content

Instantly share code, notes, and snippets.

@tafaust
Created March 13, 2018 10:04
Show Gist options
  • Save tafaust/4a75a9f6a6c59ad3da8e716342772660 to your computer and use it in GitHub Desktop.
Save tafaust/4a75a9f6a6c59ad3da8e716342772660 to your computer and use it in GitHub Desktop.
Python 3.6 type «enforcement» (/ check) through annotations or custom list of types
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import logging.config
import functools
from typing import Callable, Union
__author__ = 'Thomas Hesse'
L = logging.getLogger(__name__)
L.debug(f'Loaded module: {__name__}.')
def accepts(*types):
"""Decorate any callable to force type checking on arguments.
:param types: *Optional.* When specified, these types are used over the python3 annotations.
"""
def check_accepts(f: Callable, *_types) -> Callable:
_types = _types or tuple(f.__annotations__.values())
assert len(_types) == f.__code__.co_argcount
@functools.wraps(f)
def new_f(*args, **kwargs) -> Callable:
for (a, t) in zip(args, _types):
if not isinstance(a, t.__args__ if type(t) is type(Union) else t):
err_msg = f'Call to function {f.__name__}: Argument {a} with type {type(a)} does not match type {t}'
L.error(err_msg)
raise AttributeError(err_msg)
return f(*args, **kwargs)
return new_f
return lambda f: check_accepts(f, *types)
@tafaust
Copy link
Author

tafaust commented May 20, 2018

Credits to the people from reddit.com/r/learnpython: Link to the thread that supported me in this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment