예제 #1
0
def test_function_info():
    def f1():
        pass

    async def f2(x):
        pass

    def f3(x, y=2):
        pass

    async def f4(x, y=2, *, z=3):
        pass

    def f5(x, y=2, *, z=3, **kwargs):
        pass

    async def f6(x, y=2, *args):
        pass

    def f7(x, *args, **kwargs):
        pass

    f8 = pow

    assert signature_info(f1) == SignatureInfo(0, 0, [], [])
    assert signature_info(f2) == SignatureInfo(1, 1, ['x'], [])
    assert signature_info(f3) == SignatureInfo(1, 2, ['x'], ['y'])
    assert signature_info(f4) == SignatureInfo(1, 2, ['x'], ['y', 'z'])
    assert signature_info(f5) == SignatureInfo(1, 2, ['x'], any)
    assert signature_info(f6) == SignatureInfo(1, None, ['x'], ['y'])
    assert signature_info(f7) == SignatureInfo(1, None, ['x'], any)
    assert signature_info(f8) == SignatureInfo(2, 3, [], None)
예제 #2
0
def handler_invocation(handler, request):
    method, args = request.method, request.args
    if handler is None:
        raise RPCError(JSONRPC.METHOD_NOT_FOUND,
                       f'unknown method "{method}"')

    # We must test for too few and too many arguments.  How
    # depends on whether the arguments were passed as a list or as
    # a dictionary.
    info = signature_info(handler)
    if isinstance(args, (tuple, list)):
        if len(args) < info.min_args:
            s = '' if len(args) == 1 else 's'
            raise RPCError.invalid_args(
                f'{len(args)} argument{s} passed to method '
                f'"{method}" but it requires {info.min_args}')
        if info.max_args is not None and len(args) > info.max_args:
            s = '' if len(args) == 1 else 's'
            raise RPCError.invalid_args(
                f'{len(args)} argument{s} passed to method '
                f'{method} taking at most {info.max_args}')
        return partial(handler, *args)

    # Arguments passed by name
    if info.other_names is None:
        raise RPCError.invalid_args(f'method "{method}" cannot '
                                    f'be called with named arguments')

    missing = set(info.required_names).difference(args)
    if missing:
        s = '' if len(missing) == 1 else 's'
        missing = ', '.join(sorted(f'"{name}"' for name in missing))
        raise RPCError.invalid_args(f'method "{method}" requires '
                                    f'parameter{s} {missing}')

    if info.other_names is not any:
        excess = set(args).difference(info.required_names)
        excess = excess.difference(info.other_names)
        if excess:
            s = '' if len(excess) == 1 else 's'
            excess = ', '.join(sorted(f'"{name}"' for name in excess))
            raise RPCError.invalid_args(f'method "{method}" does not '
                                        f'take parameter{s} {excess}')
    return partial(handler, **args)