A small wrapper around getargspec that also supports callable classes
    :param is_class_method: Pass True if you are sure that the function being passed
                            is a class method. The reason for this is that on Python 3
                            ``inspect.ismethod`` only returns ``True`` for bound methods,
                            while on Python 2, it returns ``True`` for bound and unbound
                            methods. So, on Python 3, in case of a class method, you'd
                            need the class to which the function belongs to be instantiated
                            and this is not always wanted.

def get_function_argspec(func, is_class_method=None):
    '''
    A small wrapper around getargspec that also supports callable classes
    :param is_class_method: Pass True if you are sure that the function being passed
                            is a class method. The reason for this is that on Python 3
                            ``inspect.ismethod`` only returns ``True`` for bound methods,
                            while on Python 2, it returns ``True`` for bound and unbound
                            methods. So, on Python 3, in case of a class method, you'd
                            need the class to which the function belongs to be instantiated
                            and this is not always wanted.
    '''
    if not callable(func):
        raise TypeError('{0} is not a callable'.format(func))

    if six.PY2:
        if is_class_method is True:
            aspec = inspect.getargspec(func)
            del aspec.args[0]  # self
        elif inspect.isfunction(func):
            aspec = inspect.getargspec(func)
        elif inspect.ismethod(func):
            aspec = inspect.getargspec(func)
            del aspec.args[0]  # self
        elif isinstance(func, object):
            aspec = inspect.getargspec(func.__call__)
            del aspec.args[0]  # self
        else:
            raise TypeError(
                'Cannot inspect argument list for \'{0}\''.format(func)
            )
    else:
        if is_class_method is True:
            aspec = _getargspec(func)
            del aspec.args[0]  # self
        elif inspect.isfunction(func):
            aspec = _getargspec(func)  # pylint: disable=redefined-variable-type
        elif inspect.ismethod(func):
            aspec = _getargspec(func)
            del aspec.args[0]  # self
        elif isinstance(func, object):
            aspec = _getargspec(func.__call__)
            del aspec.args[0]  # self
        else:
            raise TypeError(
                'Cannot inspect argument list for \'{0}\''.format(func)
            )
    return aspec