Source code for hoft.core.decorators

#!/usr/bin/env python
# -*- coding: latin-1 -*-
#
# Brief description
# @module hoft.core.decorators
# @version 0.1
# @copyright (c) 2017-present Francis Horsman.

from inspect import getargspec, getcallargs

import six

from hoft.core.parsers_in import parse_all_in_args
from hoft.core.parsers_sig import parse_all_sig_args
from hoft.core.utils import raise_exc


[docs]def analyse_in(*parse_args, **parse_kwargs): """ Decorator for methods (to analyse) the args and kwargs of the decorated callable. This method does not modify the args or kwargs in any way. Deprecated. Will be removed in a future version, use `analyse_sig` instead. :param parse_args: A list of callables which accept two values only: These callables will be passed the target function's argument at the same position as - the callable is in the decorator's arguments list and the index of the argument. If callable==`IGNORE`, then the decorated function's arg is not parsed. :param parse_kwargs: A dictionary of name, callables. The name represents the target function's kwarg that will be passed to the callable. The callable receives the name, value and a boolean representing if the name is present in the kwargs: ie: `def my_func(name, value, name_in_decorated_funcs_passed_kwargs)`. :param bool parse_kwargs['_fail_fast_']: True: Fail on the first exception raised by any supplied callable. :param bool parse_kwargs['_on_error_']: Callable or type to be called when an exception is found in a supplied callable, if the type is an exception or subclass-of, it will be raised (the exception constructor should take the same signature as my_func below): ie: `def my_func(exc, list_of_excs)`. If the type is not an exception or subclass-of it will be called, it is up to this callable to raise an exception if required. :returns: Decorated function. :note: Any exception raised by a supplied callable will have an additional field: `_errors_`. This is always a list of one or all of the errors encountered during the supplied callables (depending on the value of the `_fail_fast_` kwargs). Example: >>> @hoft.analyse_in( _a_func(z=1), None, bar=_b_func(x=1, y=2), baz=_validate_baz(), x=None, _fail_fast_=True, _on_error_=my_func, ) def _validate_something_decorated(foo, ignored, bar=hoft.IGNORE, baz=None, x=None): ... """ def decorator(func): @six.wraps(func) def wrapper(*args, **kwargs): fail_fast = parse_kwargs.pop('_fail_fast_', False) on_error = parse_kwargs.pop('_on_error_', None) argspec = getargspec(func) errors = parse_all_in_args( parse_args, parse_kwargs, args, kwargs, argspec, on_error, fail_fast, ) if errors and not fail_fast: # We have errors to raise which have not already been raised. exc = errors[0] raise_exc( exc=exc.error, on_error=on_error, errors=errors, fail_fast=fail_fast, force=True, ) # Call the wrapped function: return func(*args, **kwargs) return wrapper return decorator
[docs]def analyse_sig(*parse_args, **parse_kwargs): """ Decorator for methods (to analyse) the args and kwargs of the decorated callable. This method does not modify the args or kwargs in any way. Preferred method over `analyse_in`. :param parse_args: A list of callables which accept two values only: These callables will be passed the target function's argument at the same position as - the callable is in the decorator's arguments list and the index of the argument. If callable==`IGNORE`, then the decorated function's arg is not parsed. :param parse_kwargs: A dictionary of name, callables. The name represents the target function's kwarg that will be passed to the callable. The callable receives the name, value and a boolean representing if the name is present in the kwargs: ie: `def my_func(name, value, name_in_decorated_funcs_passed_kwargs)`. :param bool parse_kwargs['_fail_fast_']: True: Fail on the first exception raised by any supplied callable. :param bool parse_kwargs['_on_error_']: Callable or type to be called when an exception is found in a supplied callable, if the type is an exception or subclass-of, it will be raised (the exception constructor should take the same signature as my_func below): ie: `def my_func(exc, list_of_excs)`. If the type is not an exception or subclass-of it will be called, it is up to this callable to raise an exception if required. :param bool parse_kwargs['_strict_']: True=Error if all params are not analysed. :param callable parse_kwargs['_default_']: Default handler for all not previously analysed arguments. :returns: Decorated function. :note: Any exception raised by a supplied callable will have an additional field: `_errors_`. This is always a list of one or all of the errors encountered during the supplied callables (depending on the value of the `_fail_fast_` kwargs). Example: >>> @hoft.analyse_sig( _a_func(z=1), None, bar=_b_func(x=1, y=2), baz=_validate_baz(), x=None, _fail_fast_=True, _on_error_=my_func, _strict_=False, _default_=_default_func, ) def _validate_something_decorated(foo, ignored, bar=hoft.IGNORE, baz=None, x=None): ... """ def decorator(func): @six.wraps(func) def wrapper(*args, **kwargs): argspec = getargspec(func) callargs = getcallargs(func, *args, **kwargs) strict = parse_kwargs.pop('_strict_', None) default = parse_kwargs.pop('_default_', None) fail_fast = parse_kwargs.pop('_fail_fast_', False) on_error = parse_kwargs.pop('_on_error_', None) errors = parse_all_sig_args( parse_args, parse_kwargs, args, kwargs, argspec, callargs, strict, default, on_error, fail_fast, ) if errors and not fail_fast: # We have errors to raise which have not already been raised. exc = errors[0] raise_exc( exc=exc.error, on_error=on_error, errors=errors, fail_fast=fail_fast, force=True, ) # Call the wrapped function: return func(*args, **kwargs) return wrapper return decorator