def logx(supress_args=[], supress_all_args=False, supress_result=False, receiver=None):
    """
    logs parameters and result
    takes arguments
        supress_args - list of parameter names to supress
        supress_all_args - boolean to supress all arguments
        supress_result - boolean to supress result
        receiver - custom logging function which takes a string as input; defaults to logging on stdout
    """

    def decorator(fn):
        def func(*args, **kwargs):
            if not supress_all_args:
                arg_string = ""
                for i in range(0, len(args)):
                    var_name = fn.__code__.co_varnames[i]
                    if var_name != "self" and var_name not in supress_args:
                        arg_string += var_name + ":" + str(args[i]) + ","
                arg_string = arg_string[0:len(arg_string) - 1]
                string = (RED + BOLD + '>> ' + END + 'Calling {0}({1})'.format(fn.__code__.co_name, arg_string))
                if len(kwargs):
                    string = (
                        RED + BOLD + '>> ' + END + 'Calling {0} with args {1} and kwargs {2}'.format(
                            fn.__code__.co_name,
                            arg_string, kwargs))
                if receiver:
                    receiver(string)
                else:
                    print(string)

            result = fn(*args, **kwargs)
            if not supress_result:
                string = BLUE + BOLD + '<< ' + END + 'Return {0} with result :{1}'.format(fn.__code__.co_name, result)
                if receiver:
                    receiver(string)
                else:
                    print(string)
            return result

        return func

    return decorator
def logx ( supress_args = [ ] , supress_all_args = False , supress_result = False , receiver = None ) : def decorator ( fn ) : def func ( * args , ** kwargs ) : if not supress_all_args : arg_string = "" for i in range ( 0 , len ( args ) ) : var_name = fn . __code__ . co_varnames [ i ] if var_name != "self" and var_name not in supress_args : arg_string += var_name + ":" + str ( args [ i ] ) + "," arg_string = arg_string [ 0 : len ( arg_string ) - 1 ] string = ( RED + BOLD + '>> ' + END + 'Calling {0}({1})' . format ( fn . __code__ . co_name , arg_string ) ) if len ( kwargs ) : string = ( RED + BOLD + '>> ' + END + 'Calling {0} with args {1} and kwargs {2}' . format ( fn . __code__ . co_name , arg_string , kwargs ) ) if receiver : receiver ( string ) else : print ( string ) result = fn ( * args , ** kwargs ) if not supress_result : string = BLUE + BOLD + '<< ' + END + 'Return {0} with result :{1}' . format ( fn . __code__ . co_name , result ) if receiver : receiver ( string ) else : print ( string ) return result return func return decorator
logs parameters and result
    takes arguments
        supress_args - list of parameter names to supress
        supress_all_args - boolean to supress all arguments
        supress_result - boolean to supress result
        receiver - custom logging function which takes a string as input; defaults to logging on stdout