Created
March 13, 2018 10:04
-
-
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
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
#!/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) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Credits to the people from reddit.com/r/learnpython: Link to the thread that supported me in this