This will return the class_name and function_name of the
    function traced back two functions.

    :param function_index: int of how many frames back the program 
                           should look (2 will give the parent of the caller)
    :param function_name: str of what function to look for (should 
                           not be used with function_index)
    :param line_number: int, some times the user may want to override 
                           this for testing purposes
    :return tuple: ('cls_name','func_name',line_number,globals())

def function_info(function_index=1, function_name=None, line_number=None):
    """
    This will return the class_name and function_name of the
    function traced back two functions.

    :param function_index: int of how many frames back the program 
                           should look (2 will give the parent of the caller)
    :param function_name: str of what function to look for (should 
                           not be used with function_index)
    :param line_number: int, some times the user may want to override 
                           this for testing purposes
    :return tuple: ('cls_name','func_name',line_number,globals())
    """
    frm = func_frame(function_index + 1, function_name)

    file_ = os.path.abspath(frm.f_code.co_filename)
    class_name = frm.f_locals.get('self', None)
    if class_name is not None: # and not skip_class:
        class_name = str(type(class_name)).split('.',1)[-1].split("'")[0]
        # try:
        #     class_name = str(class_name).split(None, 1)[1]
        #     class_name = class_name.split('.')[-1].replace(')', '')
        # except:
        #     class_name = repr(class_name).split()[0].split('.')[-1]
        # if 'object at' in str(class_name):
        #     class_name = str(class_name).split(' object at')[0].split('.')[-1]

    args, _, _, kwargs = inspect.getargvalues(frm)
    line_number = line_number or frm.f_lineno
    return {'class_name': class_name or '',
            'function_name': frm.f_code.co_name,
            'file': file_,
            'path': os.path.split(file_)[0],
            'basename': os.path.basename(file_).split('.')[0],
            'line_number': line_number or frm.f_lineno,
            'globals': frm.f_globals,
            'locals': frm.f_locals,
            'arguments': args,
            'kwargs': kwargs,
            'frame': frm}