(obj, *,
                             follow_wrapper_chains=True,
                             skip_bound_arg=True,
                             globals=None,
                             locals=None,
                             eval_str=False,
                             sigcls)
Private helper function to get signature for arbitrary
    callable objects.
Private helper function to get signature for arbitrary
    callable objects.
Private helper function to get signature for arbitrary callable objects .
def _signature_from_callable(obj, *,
                             follow_wrapper_chains=True,
                             skip_bound_arg=True,
                             globals=None,
                             locals=None,
                             eval_str=False,
                             sigcls):

    """Private helper function to get signature for arbitrary
    callable objects.
    """

    _get_signature_of = functools.partial(_signature_from_callable,
                                follow_wrapper_chains=follow_wrapper_chains,
                                skip_bound_arg=skip_bound_arg,
                                globals=globals,
                                locals=locals,
                                sigcls=sigcls,
                                eval_str=eval_str)

    if not callable(obj):
        raise TypeError('{!r} is not a callable object'.format(obj))

    if isinstance(obj, types.MethodType):
        # In this case we skip the first parameter of the underlying
        # function (usually `self` or `cls`).
        sig = _get_signature_of(obj.__func__)

        if skip_bound_arg:
            return _signature_bound_method(sig)
        else:
            return sig

    # Was this function wrapped by a decorator?
    if follow_wrapper_chains:
        obj = unwrap(obj, stop=(lambda f: hasattr(f, "__signature__")))
        if isinstance(obj, types.MethodType):
            # If the unwrapped object is a *method*, we might want to
            # skip its first parameter (self).
            # See test_signature_wrapped_bound_method for details.
            return _get_signature_of(obj)

    try:
        sig = obj.__signature__
    except AttributeError:
        pass
    else:
        if sig is not None:
            if not isinstance(sig, Signature):
                raise TypeError(
                    'unexpected object {!r} in __signature__ '
                    'attribute'.format(sig))
            return sig

    try:
        partialmethod = obj._partialmethod
    except AttributeError:
        pass
    else:
        if isinstance(partialmethod, functools.partialmethod):
            # Unbound partialmethod (see functools.partialmethod)
            # This means, that we need to calculate the signature
            # as if it's a regular partial object, but taking into
            # account that the first positional argument
            # (usually `self`, or `cls`) will not be passed
            # automatically (as for boundmethods)

            wrapped_sig = _get_signature_of(partialmethod.func)

            sig = _signature_get_partial(wrapped_sig, partialmethod, (None,))
            first_wrapped_param = tuple(wrapped_sig.parameters.values())[0]
            if first_wrapped_param.kind is Parameter.VAR_POSITIONAL:
                # First argument of the wrapped callable is `*args`, as in
                # `partialmethod(lambda *args)`.
                return sig
            else:
                sig_params = tuple(sig.parameters.values())
                assert (not sig_params or
                        first_wrapped_param is not sig_params[0])
                new_params = (first_wrapped_param,) + sig_params
                return sig.replace(parameters=new_params)

    if isfunction(obj) or _signature_is_functionlike(obj):
        # If it's a pure Python function, or an object that is duck type
        # of a Python function (Cython functions, for instance), then:
        return _signature_from_function(sigcls, obj,
                                        skip_bound_arg=skip_bound_arg,
                                        globals=globals, locals=locals, eval_str=eval_str)

    if _signature_is_builtin(obj):
        return _signature_from_builtin(sigcls, obj,
                                       skip_bound_arg=skip_bound_arg)

    if isinstance(obj, functools.partial):
        wrapped_sig = _get_signature_of(obj.func)
        return _signature_get_partial(wrapped_sig, obj)

    sig = None
    if isinstance(obj, type):
        # obj is a class or a metaclass

        # First, let's see if it has an overloaded __call__ defined
        # in its metaclass
        call = _signature_get_user_defined_method(type(obj), '__call__')
        if call is not None:
            sig = _get_signature_of(call)
        else:
            factory_method = None
            new = _signature_get_user_defined_method(obj, '__new__')
            init = _signature_get_user_defined_method(obj, '__init__')
            # Now we check if the 'obj' class has an own '__new__' method
            if '__new__' in obj.__dict__:
                factory_method = new
            # or an own '__init__' method
            elif '__init__' in obj.__dict__:
                factory_method = init
            # If not, we take inherited '__new__' or '__init__', if present
            elif new is not None:
                factory_method = new
            elif init is not None:
                factory_method = init

            if factory_method is not None:
                sig = _get_signature_of(factory_method)

        if sig is None:
            # At this point we know, that `obj` is a class, with no user-
            # defined '__init__', '__new__', or class-level '__call__'

            for base in obj.__mro__[:-1]:
                # Since '__text_signature__' is implemented as a
                # descriptor that extracts text signature from the
                # class docstring, if 'obj' is derived from a builtin
                # class, its own '__text_signature__' may be 'None'.
                # Therefore, we go through the MRO (except the last
                # class in there, which is 'object') to find the first
                # class with non-empty text signature.
                try:
                    text_sig = base.__text_signature__
                except AttributeError:
                    pass
                else:
                    if text_sig:
                        # If 'obj' class has a __text_signature__ attribute:
                        # return a signature based on it
                        return _signature_fromstr(sigcls, obj, text_sig)

            # No '__text_signature__' was found for the 'obj' class.
            # Last option is to check if its '__init__' is
            # object.__init__ or type.__init__.
            if type not in obj.__mro__:
                # We have a class (not metaclass), but no user-defined
                # __init__ or __new__ for it
                if (obj.__init__ is object.__init__ and
                    obj.__new__ is object.__new__):
                    # Return a signature of 'object' builtin.
                    return sigcls.from_callable(object)
                else:
                    raise ValueError(
                        'no signature found for builtin type {!r}'.format(obj))

    elif not isinstance(obj, _NonUserDefinedCallables):
        # An object with __call__
        # We also check that the 'obj' is not an instance of
        # _WrapperDescriptor or _MethodWrapper to avoid
        # infinite recursion (and even potential segfault)
        call = _signature_get_user_defined_method(type(obj), '__call__')
        if call is not None:
            try:
                sig = _get_signature_of(call)
            except ValueError as ex:
                msg = 'no signature found for {!r}'.format(obj)
                raise ValueError(msg) from ex

    if sig is not None:
        # For classes and objects we skip the first parameter of their
        # __call__, __new__, or __init__ methods
        if skip_bound_arg:
            return _signature_bound_method(sig)
        else:
            return sig

    if isinstance(obj, types.BuiltinFunctionType):
        # Raise a nicer error message for builtins
        msg = 'no signature found for builtin function {!r}'.format(obj)
        raise ValueError(msg)

    raise ValueError('callable {!r} is not supported by signature'.format(obj))
def _signature_from_callable ( obj , * , follow_wrapper_chains = True , skip_bound_arg = True , globals = None , locals = None , eval_str = False , sigcls ) : _get_signature_of = functools . partial ( _signature_from_callable , follow_wrapper_chains = follow_wrapper_chains , skip_bound_arg = skip_bound_arg , globals = globals , locals = locals , sigcls = sigcls , eval_str = eval_str ) if not callable ( obj ) : raise TypeError ( '{!r} is not a callable object' . format ( obj ) ) if isinstance ( obj , types . MethodType ) : # In this case we skip the first parameter of the underlying # function (usually `self` or `cls`). sig = _get_signature_of ( obj . __func__ ) if skip_bound_arg : return _signature_bound_method ( sig ) else : return sig # Was this function wrapped by a decorator? if follow_wrapper_chains : obj = unwrap ( obj , stop = ( lambda f : hasattr ( f , "__signature__" ) ) ) if isinstance ( obj , types . MethodType ) : # If the unwrapped object is a *method*, we might want to # skip its first parameter (self). # See test_signature_wrapped_bound_method for details. return _get_signature_of ( obj ) try : sig = obj . __signature__ except AttributeError : pass else : if sig is not None : if not isinstance ( sig , Signature ) : raise TypeError ( 'unexpected object {!r} in __signature__ ' 'attribute' . format ( sig ) ) return sig try : partialmethod = obj . _partialmethod except AttributeError : pass else : if isinstance ( partialmethod , functools . partialmethod ) : # Unbound partialmethod (see functools.partialmethod) # This means, that we need to calculate the signature # as if it's a regular partial object, but taking into # account that the first positional argument # (usually `self`, or `cls`) will not be passed # automatically (as for boundmethods) wrapped_sig = _get_signature_of ( partialmethod . func ) sig = _signature_get_partial ( wrapped_sig , partialmethod , ( None , ) ) first_wrapped_param = tuple ( wrapped_sig . parameters . values ( ) ) [ 0 ] if first_wrapped_param . kind is Parameter . VAR_POSITIONAL : # First argument of the wrapped callable is `*args`, as in # `partialmethod(lambda *args)`. return sig else : sig_params = tuple ( sig . parameters . values ( ) ) assert ( not sig_params or first_wrapped_param is not sig_params [ 0 ] ) new_params = ( first_wrapped_param , ) + sig_params return sig . replace ( parameters = new_params ) if isfunction ( obj ) or _signature_is_functionlike ( obj ) : # If it's a pure Python function, or an object that is duck type # of a Python function (Cython functions, for instance), then: return _signature_from_function ( sigcls , obj , skip_bound_arg = skip_bound_arg , globals = globals , locals = locals , eval_str = eval_str ) if _signature_is_builtin ( obj ) : return _signature_from_builtin ( sigcls , obj , skip_bound_arg = skip_bound_arg ) if isinstance ( obj , functools . partial ) : wrapped_sig = _get_signature_of ( obj . func ) return _signature_get_partial ( wrapped_sig , obj ) sig = None if isinstance ( obj , type ) : # obj is a class or a metaclass # First, let's see if it has an overloaded __call__ defined # in its metaclass call = _signature_get_user_defined_method ( type ( obj ) , '__call__' ) if call is not None : sig = _get_signature_of ( call ) else : factory_method = None new = _signature_get_user_defined_method ( obj , '__new__' ) init = _signature_get_user_defined_method ( obj , '__init__' ) # Now we check if the 'obj' class has an own '__new__' method if '__new__' in obj . __dict__ : factory_method = new # or an own '__init__' method elif '__init__' in obj . __dict__ : factory_method = init # If not, we take inherited '__new__' or '__init__', if present elif new is not None : factory_method = new elif init is not None : factory_method = init if factory_method is not None : sig = _get_signature_of ( factory_method ) if sig is None : # At this point we know, that `obj` is a class, with no user- # defined '__init__', '__new__', or class-level '__call__' for base in obj . __mro__ [ : - 1 ] : # Since '__text_signature__' is implemented as a # descriptor that extracts text signature from the # class docstring, if 'obj' is derived from a builtin # class, its own '__text_signature__' may be 'None'. # Therefore, we go through the MRO (except the last # class in there, which is 'object') to find the first # class with non-empty text signature. try : text_sig = base . __text_signature__ except AttributeError : pass else : if text_sig : # If 'obj' class has a __text_signature__ attribute: # return a signature based on it return _signature_fromstr ( sigcls , obj , text_sig ) # No '__text_signature__' was found for the 'obj' class. # Last option is to check if its '__init__' is # object.__init__ or type.__init__. if type not in obj . __mro__ : # We have a class (not metaclass), but no user-defined # __init__ or __new__ for it if ( obj . __init__ is object . __init__ and obj . __new__ is object . __new__ ) : # Return a signature of 'object' builtin. return sigcls . from_callable ( object ) else : raise ValueError ( 'no signature found for builtin type {!r}' . format ( obj ) ) elif not isinstance ( obj , _NonUserDefinedCallables ) : # An object with __call__ # We also check that the 'obj' is not an instance of # _WrapperDescriptor or _MethodWrapper to avoid # infinite recursion (and even potential segfault) call = _signature_get_user_defined_method ( type ( obj ) , '__call__' ) if call is not None : try : sig = _get_signature_of ( call ) except ValueError as ex : msg = 'no signature found for {!r}' . format ( obj ) raise ValueError ( msg ) from ex if sig is not None : # For classes and objects we skip the first parameter of their # __call__, __new__, or __init__ methods if skip_bound_arg : return _signature_bound_method ( sig ) else : return sig if isinstance ( obj , types . BuiltinFunctionType ) : # Raise a nicer error message for builtins msg = 'no signature found for builtin function {!r}' . format ( obj ) raise ValueError ( msg ) raise ValueError ( 'callable {!r} is not supported by signature' . format ( obj ) )