(wrapped_sig, partial, extra_args=())
return wrapped_sig.replace(parameters=new_params.values())
Private helper to calculate how 'wrapped_sig' signature will
    look like after applying a 'functools.partial' object (or alike)
    on it.
Private helper to calculate how 'wrapped_sig' signature will
    look like after applying a 'functools.partial' object (or alike)
    on it.
Private helper to calculate how wrapped_sig signature will look like after applying a functools . partial object ( or alike ) on it .
def _signature_get_partial(wrapped_sig, partial, extra_args=()):
    """Private helper to calculate how 'wrapped_sig' signature will
    look like after applying a 'functools.partial' object (or alike)
    on it.
    """

    old_params = wrapped_sig.parameters
    new_params = OrderedDict(old_params.items())

    partial_args = partial.args or ()
    partial_keywords = partial.keywords or {}

    if extra_args:
        partial_args = extra_args + partial_args

    try:
        ba = wrapped_sig.bind_partial(*partial_args, **partial_keywords)
    except TypeError as ex:
        msg = 'partial object {!r} has incorrect arguments'.format(partial)
        raise ValueError(msg) from ex


    transform_to_kwonly = False
    for param_name, param in old_params.items():
        try:
            arg_value = ba.arguments[param_name]
        except KeyError:
            pass
        else:
            if param.kind is _POSITIONAL_ONLY:
                # If positional-only parameter is bound by partial,
                # it effectively disappears from the signature
                new_params.pop(param_name)
                continue

            if param.kind is _POSITIONAL_OR_KEYWORD:
                if param_name in partial_keywords:
                    # This means that this parameter, and all parameters
                    # after it should be keyword-only (and var-positional
                    # should be removed). Here's why. Consider the following
                    # function:
                    #     foo(a, b, *args, c):
                    #         pass
                    #
                    # "partial(foo, a='spam')" will have the following
                    # signature: "(*, a='spam', b, c)". Because attempting
                    # to call that partial with "(10, 20)" arguments will
                    # raise a TypeError, saying that "a" argument received
                    # multiple values.
                    transform_to_kwonly = True
                    # Set the new default value
                    new_params[param_name] = param.replace(default=arg_value)
                else:
                    # was passed as a positional argument
                    new_params.pop(param.name)
                    continue

            if param.kind is _KEYWORD_ONLY:
                # Set the new default value
                new_params[param_name] = param.replace(default=arg_value)

        if transform_to_kwonly:
            assert param.kind is not _POSITIONAL_ONLY

            if param.kind is _POSITIONAL_OR_KEYWORD:
                new_param = new_params[param_name].replace(kind=_KEYWORD_ONLY)
                new_params[param_name] = new_param
                new_params.move_to_end(param_name)
            elif param.kind in (_KEYWORD_ONLY, _VAR_KEYWORD):
                new_params.move_to_end(param_name)
            elif param.kind is _VAR_POSITIONAL:
                new_params.pop(param.name)

    return wrapped_sig.replace(parameters=new_params.values())
def _signature_get_partial ( wrapped_sig , partial , extra_args = ( ) ) : old_params = wrapped_sig . parameters new_params = OrderedDict ( old_params . items ( ) ) partial_args = partial . args or ( ) partial_keywords = partial . keywords or { } if extra_args : partial_args = extra_args + partial_args try : ba = wrapped_sig . bind_partial ( * partial_args , * * partial_keywords ) except TypeError as ex : msg = 'partial object {!r} has incorrect arguments' . format ( partial ) raise ValueError ( msg ) from ex transform_to_kwonly = False for param_name , param in old_params . items ( ) : try : arg_value = ba . arguments [ param_name ] except KeyError : pass else : if param . kind is _POSITIONAL_ONLY : # If positional-only parameter is bound by partial, # it effectively disappears from the signature new_params . pop ( param_name ) continue if param . kind is _POSITIONAL_OR_KEYWORD : if param_name in partial_keywords : # This means that this parameter, and all parameters # after it should be keyword-only (and var-positional # should be removed). Here's why. Consider the following # function: #     foo(a, b, *args, c): #         pass # # "partial(foo, a='spam')" will have the following # signature: "(*, a='spam', b, c)". Because attempting # to call that partial with "(10, 20)" arguments will # raise a TypeError, saying that "a" argument received # multiple values. transform_to_kwonly = True # Set the new default value new_params [ param_name ] = param . replace ( default = arg_value ) else : # was passed as a positional argument new_params . pop ( param . name ) continue if param . kind is _KEYWORD_ONLY : # Set the new default value new_params [ param_name ] = param . replace ( default = arg_value ) if transform_to_kwonly : assert param . kind is not _POSITIONAL_ONLY if param . kind is _POSITIONAL_OR_KEYWORD : new_param = new_params [ param_name ] . replace ( kind = _KEYWORD_ONLY ) new_params [ param_name ] = new_param new_params . move_to_end ( param_name ) elif param . kind in ( _KEYWORD_ONLY , _VAR_KEYWORD ) : new_params . move_to_end ( param_name ) elif param . kind is _VAR_POSITIONAL : new_params . pop ( param . name ) return wrapped_sig . replace ( parameters = new_params . values ( ) )