Source code for char.main

"""
This is one and only file with working code in the whole package
"""

# Standard library imports
import sys
import logging
from functools import wraps
# Third party imports

# Local imports


LOGGER = logging.getLogger("check_types_of_arguments")
LOGGER.addHandler(logging.NullHandler())


DICT_TUPLE_DEFAULT_TYPES_BY_PREFIX = {}
#####
# First define prefixes which are python version specific
if sys.version_info[0] == 2:
    # basestring is parent class for str and unicode
    DICT_TUPLE_DEFAULT_TYPES_BY_PREFIX["str_"] = (basestring)
else:
    DICT_TUPLE_DEFAULT_TYPES_BY_PREFIX["str_"] = (str)
#####
DICT_TUPLE_DEFAULT_TYPES_BY_PREFIX["any_"] = (object)
DICT_TUPLE_DEFAULT_TYPES_BY_PREFIX["bytes_"] = (bytes)
DICT_TUPLE_DEFAULT_TYPES_BY_PREFIX["bool_"] = (bool)
DICT_TUPLE_DEFAULT_TYPES_BY_PREFIX["b_"] = (bool)
DICT_TUPLE_DEFAULT_TYPES_BY_PREFIX["is_"] = (bool)
DICT_TUPLE_DEFAULT_TYPES_BY_PREFIX["has_"] = (bool)
DICT_TUPLE_DEFAULT_TYPES_BY_PREFIX["int_"] = (int)
DICT_TUPLE_DEFAULT_TYPES_BY_PREFIX["i_"] = (int)
DICT_TUPLE_DEFAULT_TYPES_BY_PREFIX["float_"] = (float)
DICT_TUPLE_DEFAULT_TYPES_BY_PREFIX["f_"] = (float)
DICT_TUPLE_DEFAULT_TYPES_BY_PREFIX["list_"] = (list)
DICT_TUPLE_DEFAULT_TYPES_BY_PREFIX["l_"] = (list)
DICT_TUPLE_DEFAULT_TYPES_BY_PREFIX["dict_"] = (dict)
DICT_TUPLE_DEFAULT_TYPES_BY_PREFIX["d_"] = (dict)
DICT_TUPLE_DEFAULT_TYPES_BY_PREFIX["set_"] = (set)
DICT_TUPLE_DEFAULT_TYPES_BY_PREFIX["s_"] = (set)
DICT_TUPLE_DEFAULT_TYPES_BY_PREFIX["tuple_"] = (tuple)
DICT_TUPLE_DEFAULT_TYPES_BY_PREFIX["t_"] = (tuple)



[docs]class ArgumentTypeError(TypeError): """Error that type of argument is incorrect Args: TypeError (Exception): Wrong type of argument was given to function """ pass
[docs]def check_type_of_1_argument( str_function_name, str_argument_name, argument_value, tuple_types_var_can_be ): """Check type of one argument for function Args: str_function_name (str): Name of function from which method is called str_argument_name (str): Name of argument to check argument_value (Any): Value that was given to this argument tuple_types_var_can_be (tuple of types): Types this arg can be Raises: ArgumentTypeError: Wrong type of argument, child from TypeError """ if isinstance(argument_value, tuple_types_var_can_be): return str_error_message = ( "Incorrect type of variable was given to function: " + str_function_name + "\n" + "---> For variable: " + str(str_argument_name) + "\n" + "---> Were given value: " + str(argument_value) + "\n" + "---> With type: " + str(type(argument_value)) + "\n" + "---> Instead of: " + str(tuple_types_var_can_be) ) raise ArgumentTypeError(str_error_message)
[docs]def char( function=None, dict_tuple_types_by_prefix=None, dict_tuple_types_by_prefix_to_update_default=None, bool_is_to_skip_none_value=True, ): """Decorator for checking types of arguments in function Check is done according to prefices that was given (or default ones) E.G. if name of variable starts with int_ and there is prefix "int_" in dict which describe how to check types then if for the argument will be given value with any another type then ArgumentTypeError Exception will be raised Args: function (function, optional): To call dec without arguments. Defaults to None. dict_tuple_types_by_prefix (dict, optional): Rules how to check types. Defaults to None. dict_tuple_types_by_prefix_to_update_default (dict, optional): Additional to default Rules how to check types. Defaults to None. bool_is_to_skip_none_value (bool, optional): Flag what to do with None values. Defaults to True. Returns: function: Decorator without arguments """ # Process additional arguments if dict_tuple_types_by_prefix is None: dict_tuple_types_by_prefix_local = DICT_TUPLE_DEFAULT_TYPES_BY_PREFIX else: dict_tuple_types_by_prefix_local = dict_tuple_types_by_prefix if dict_tuple_types_by_prefix_to_update_default is not None: dict_tuple_types_by_prefix_local.update( dict_tuple_types_by_prefix_to_update_default) def cfa_with_args(func_to_check): """Main decorator without arguments Args: func_to_check (function): decorated function Returns: function: Decorated function """ int_args_count = func_to_check.__code__.co_argcount list_function_arguments = \ func_to_check.__code__.co_varnames[:int_args_count] str_function_name = func_to_check.__name__ @wraps(func_to_check) def wrapper(*args, **kwargs): """wrapper for decorated function Returns: Any: Result of the decorated function """ dict_local_variables = locals() tuple_args = dict_local_variables['args'] dict_kwargs = dict_local_variables['kwargs'] list_tuples_to_iterate = ( list(zip(list_function_arguments, tuple_args)) + list(dict_kwargs.items()) ) ##### # Check arguments one by one for str_argument_name, argument_value in list_tuples_to_iterate: LOGGER.debug("Checking type of argument: %s", str_argument_name) # By default if value is None then leave this argument alone if argument_value is None and bool_is_to_skip_none_value: continue for str_prefix in dict_tuple_types_by_prefix_local: if str_argument_name.startswith(str_prefix): check_type_of_1_argument( str_function_name, str_argument_name, argument_value, dict_tuple_types_by_prefix_local[str_prefix] ) ##### return func_to_check(*args, **kwargs) return wrapper if function: return cfa_with_args(function) return cfa_with_args