# Buggy code
def get_func_args(func, stripself=False):
    """Return the argument name list of a callable"""
    if inspect.isfunction(func):
        func_args, _, _, _ = inspect.getargspec(func)
    elif inspect.isclass(func):
        return get_func_args(func.__init__, True)
    elif inspect.ismethod(func):
        return get_func_args(func.__func__, True)
    elif inspect.ismethoddescriptor(func):
        return []
    elif isinstance(func, partial):
        return [
            x
            for x in get_func_args(func.func)[len(func.args) :]
            if not (func.keywords and x in func.keywords)
        ]
    elif hasattr(func, "__call__"):
        if inspect.isroutine(func):
            return []
        else:
            return get_func_args(func.__call__, True)
    else:
        raise TypeError("%s is not callable" % type(func))
    if stripself:
        func_args.pop(0)
    return func_args


# Traceback (TypeError)
inspect.getmembers(itemgetter(2))
[('__call__',
<method-wrapper '__call__' of operator.itemgetter object at 0x7f79aeffb990>),
('__class__', <type 'operator.itemgetter'>),
('__delattr__',
<method-wrapper '__delattr__' of operator.itemgetter object at 0x7f79aeffb990>),
('__doc__',
'itemgetter(item, ...) --> itemgetter object\n\nReturn a callable object that fetches the given item(s) from its operand.\nAfter, f=itemgetter(2), the call f(r) returns r[2].\nAfter, g=itemgetter(2,5,3), the call g(r) returns (r[2], r[5], r[3])'),
('__format__',
<built-in method __format__ of operator.itemgetter object at 0x7f79aeffb990>),
('__getattribute__',
<method-wrapper '__getattribute__' of operator.itemgetter object at 0x7f79aeffb990>),
('__hash__',
<method-wrapper '__hash__' of operator.itemgetter object at 0x7f79aeffb990>),
('__init__',
<method-wrapper '__init__' of operator.itemgetter object at 0x7f79aeffb990>),
('__new__', <built-in method __new__ of type object at 0x8c1ec0>),
('__reduce__',
<built-in method __reduce__ of operator.itemgetter object at 0x7f79aeffb990>),
('__reduce_ex__',
<built-in method __reduce_ex__ of operator.itemgetter object at 0x7f79aeffb990>),
('__repr__',
<method-wrapper '__repr__' of operator.itemgetter object at 0x7f79aeffb990>),
('__setattr__',
<method-wrapper '__setattr__' of operator.itemgetter object at 0x7f79aeffb990>),
('__sizeof__',
<built-in method __sizeof__ of operator.itemgetter object at 0x7f79aeffb990>),
('__str__',
<method-wrapper '__str__' of operator.itemgetter object at 0x7f79aeffb990>),
('__subclasshook__',
<built-in method __subclasshook__ of type object at 0x8c1ec0>)]
inspect.getargspec(itemgetter(2).__call__)
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/usr/lib/python2.7/inspect.py", line 815, in getargspec
raise TypeError('{!r} is not a Python function'.format(func))
TypeError: <method-wrapper '__call__' of operator.itemgetter object at 0xb3ddd0> is not a Python function
inspect.getargspec(itemgetter(slice(None, 2)).__init__)
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/usr/lib/python2.7/inspect.py", line 815, in getargspec
raise TypeError('{!r} is not a Python function'.format(func))
TypeError: <method-wrapper '__init__' of operator.itemgetter object at 0xb3de10> is not a Python function

# Fixed code
def get_func_args(func, stripself=False):
    """Return the argument name list of a callable"""
    if inspect.isfunction(func):
        func_args, _, _, _ = inspect.getargspec(func)
    elif inspect.isclass(func):
        return get_func_args(func.__init__, True)
    elif inspect.ismethod(func):
        return get_func_args(func.__func__, True)
    elif inspect.ismethoddescriptor(func):
        return []
    elif isinstance(func, partial):
        return [
            x
            for x in get_func_args(func.func)[len(func.args) :]
            if not (func.keywords and x in func.keywords)
        ]
    elif hasattr(func, "__call__"):
        if inspect.isroutine(func):
            return []
        elif getattr(func, "__name__", None) == "__call__":
            return []
        else:
            return get_func_args(func.__call__, True)
    else:
        raise TypeError("%s is not callable" % type(func))
    if stripself:
        func_args.pop(0)
    return func_args