Beispiel #1
0
def test_batch_response():
    response = BatchResponse(
        {SuccessResponse("foo", id=1), SuccessResponse("bar", id=2)}
    )
    expected = [
        {"jsonrpc": "2.0", "result": "foo", "id": 1},
        {"jsonrpc": "2.0", "result": "bar", "id": 2},
    ]
    assert response.wanted == True
    for r in response.deserialized():
        assert r in expected
def test_examples_mixed_requests_and_notifications():
    """
    We break the spec here. The examples put an invalid jsonrpc request in the
    mix here.  but it's removed to test the rest, because we're not validating
    each request individually. Any invalid jsonrpc will respond with a single
    error message.

    The spec example includes this which invalidates the entire request:
        {"foo": "boo"},
    """
    methods = Methods(
        sum=lambda ctx, *args: SuccessResponse(sum(args), id=ctx.request.id),
        notify_hello=lambda ctx, *args: SuccessResponse(19, id=ctx.request.id),
        subtract=lambda ctx, *args: SuccessResponse(
            args[0] - sum(args[1:]), id=ctx.request.id
        ),
        get_data=lambda ctx: SuccessResponse(["hello", 5], id=ctx.request.id),
    )
    requests = serialize(
        [
            {"jsonrpc": "2.0", "method": "sum", "params": [1, 2, 4], "id": "1"},
            {"jsonrpc": "2.0", "method": "notify_hello", "params": [7]},
            {"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": "2"},
            {
                "jsonrpc": "2.0",
                "method": "foo.get",
                "params": {"name": "myself"},
                "id": "5",
            },
            {"jsonrpc": "2.0", "method": "get_data", "id": "9"},
        ]
    )
    response = dispatch_pure(
        requests,
        methods,
        extra=None,
        serialize=default_serialize,
        deserialize=default_deserialize,
    )
    expected = [
        {"jsonrpc": "2.0", "result": 7, "id": "1"},
        {"jsonrpc": "2.0", "result": 19, "id": "2"},
        {
            "jsonrpc": "2.0",
            "error": {"code": -32601, "message": "Method not found", "data": "foo.get"},
            "id": "5",
        },
        {"jsonrpc": "2.0", "result": ["hello", 5], "id": "9"},
    ]
    assert isinstance(response, BatchResponse)
    print(response.deserialized())
    for r in response.deserialized():
        assert r in expected
Beispiel #3
0
def test_to_serializable_SuccessResponse():
    assert to_serializable(Right(SuccessResponse(sentinel.result,
                                                 sentinel.id))) == {
                                                     "jsonrpc": "2.0",
                                                     "result": sentinel.result,
                                                     "id": sentinel.id,
                                                 }
Beispiel #4
0
def test_dispatch_to_response_with_global_methods():
    @method
    def ping():
        return Success("pong")

    response = dispatch_to_response('{"jsonrpc": "2.0", "method": "ping", "id": 1}')
    assert response == Right(SuccessResponse("pong", 1))
async def test_dispatch_to_response_pure_success():
    assert (await dispatch_to_response_pure(
        deserializer=default_deserializer,
        validator=default_validator,
        post_process=identity,
        context=NOCONTEXT,
        methods={"ping": ping},
        request='{"jsonrpc": "2.0", "method": "ping", "id": 1}',
    ) == Right(SuccessResponse("pong", 1)))
Beispiel #6
0
def test_dispatch_deserialized():
    assert (
        dispatch_deserialized(
            methods={"ping": ping},
            context=NOCONTEXT,
            post_process=identity,
            deserialized={"jsonrpc": "2.0", "method": "ping", "id": 1},
        )
        == Right(SuccessResponse("pong", 1))
    )
async def safe_call(request: Request, methods: Methods, *, caller: Caller,
                    debug: bool) -> Response:
    with handle_exceptions(request, debug) as handler:
        if caller:
            result = await caller.call(methods.items[request.method],
                                       *request.args, **request.kwargs)
        else:
            result = await call(methods.items[request.method], *request.args,
                                **request.kwargs)
        handler.response = SuccessResponse(result=result, id=request.id)
    return handler.response
async def test_dispatch_deserialized():
    assert (await dispatch_deserialized(
        {"ping": ping},
        NOCONTEXT,
        identity,
        {
            "jsonrpc": "2.0",
            "method": "ping",
            "id": 1
        },
    ) == Right(SuccessResponse("pong", 1)))
Beispiel #9
0
def test_examples_positionals():
    def subtract(minuend, subtrahend):
        return Success(minuend - subtrahend)

    response = dispatch_to_response_pure(
        methods={"subtract": subtract},
        context=NOCONTEXT,
        validator=default_validator,
        post_process=identity,
        deserializer=default_deserializer,
        request='{"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1}',
    )
    assert response == Right(SuccessResponse(19, 1))

    # Second example
    response = dispatch_to_response_pure(
        methods={"subtract": subtract},
        context=NOCONTEXT,
        validator=default_validator,
        post_process=identity,
        deserializer=default_deserializer,
        request='{"jsonrpc": "2.0", "method": "subtract", "params": [23, 42], "id": 2}',
    )
    assert response == Right(SuccessResponse(-19, 2))
Beispiel #10
0
def test_examples_nameds():
    def subtract(**kwargs):
        return Success(kwargs["minuend"] - kwargs["subtrahend"])

    response = dispatch_to_response_pure(
        methods={"subtract": subtract},
        context=NOCONTEXT,
        validator=default_validator,
        post_process=identity,
        deserializer=default_deserializer,
        request='{"jsonrpc": "2.0", "method": "subtract", "params": {"subtrahend": 23, "minuend": 42}, "id": 3}',
    )
    assert response == Right(SuccessResponse(19, 3))

    # Second example
    response = dispatch_to_response_pure(
        methods={"subtract": subtract},
        context=NOCONTEXT,
        validator=default_validator,
        post_process=identity,
        deserializer=default_deserializer,
        request='{"jsonrpc": "2.0", "method": "subtract", "params": {"minuend": 42, "subtrahend": 23}, "id": 4}',
    )
    assert response == Right(SuccessResponse(19, 4))
Beispiel #11
0
def dispatch(request_raw: str) -> JsonRpcResponse:
    """Dispatch a request (or requests) to methods.

    This is the main public method, it's the only one with optional params, and the only
    one that can be configured with a config file/env vars.

    Args:
        request_raw: The incoming request string.

    Returns:
        A Response.
    """
    methods = global_methods
    try:
        request_json: JSON = json.loads(request_raw)
        validator.validate(request_json)
    except JSONDecodeError as exc:
        return InvalidJSONResponse(data=str(exc), debug=True)
    except ValidationError:
        return InvalidJSONRPCResponse(data=None)

    request = create_requests(request_json, convert_camel_case=False)
    assert isinstance(request, Request)

    try:
        method_name = request.method
        method = methods.items[method_name]

        with sentry_sdk.start_span(op="rpc", transaction="rpc." + method_name) as span:
            span.set_data("args", request.args)
            span.set_data("kwargs", request.kwargs)
            result = call(method, *request.args, **request.kwargs)

        return SuccessResponse(result=result, id=request.id)

    except Exception as exc:
        traceback.print_exc()
        sys.stdout.flush()
        sys.stderr.flush()
        return ExceptionResponse(exc, id=request.id, debug=True)
Beispiel #12
0
def test_success_response_str():
    response = SuccessResponse("foo", id=1)
    assert str(response) == '{"jsonrpc": "2.0", "result": "foo", "id": 1}'
Beispiel #13
0
def test_success_response():
    response = SuccessResponse("foo", id=1)
    assert response.wanted == True
    assert response.result == "foo"
    assert str(response) == '{"jsonrpc": "2.0", "result": "foo", "id": 1}'
Beispiel #14
0
def test_extract_list_batch():
    assert extract_list(True, [SuccessResponse("foo", 1)]) == [
        SuccessResponse("foo", 1)
    ]
Beispiel #15
0
async def test_dispatch_to_response():
    assert await dispatch_to_response(
        '{"jsonrpc": "2.0", "method": "ping", "id": 1}', {"ping": ping}
    ) == Right(SuccessResponse("pong", 1))
 def subtract(context: Context, minuend, subtrahend):
     return SuccessResponse(minuend - subtrahend, id=context.request.id)
Beispiel #17
0
def test_SuccessResponse():
    response = SuccessResponse(sentinel.result, sentinel.id)
    assert response.result == sentinel.result
    assert response.id == sentinel.id
Beispiel #18
0
def test_extract_list():
    assert extract_list(False, [SuccessResponse("foo", 1)]) == SuccessResponse("foo", 1)
Beispiel #19
0
def test_to_response_SuccessResult():
    assert to_response(
        Request("ping", [], sentinel.id), Right(SuccessResult(sentinel.result))
    ) == Right(SuccessResponse(sentinel.result, sentinel.id))
def ping(context: Context):
    return SuccessResponse("pong", id=context.request.id)
 def subtract(context: Context, **kwargs):
     return SuccessResponse(
         kwargs["minuend"] - kwargs["subtrahend"], id=context.request.id
     )
Beispiel #22
0
def test_success_response_null_id():
    # OK - any type of id is acceptable
    response = SuccessResponse("foo", id=None)
    assert str(response) == '{"jsonrpc": "2.0", "result": "foo", "id": null}'
Beispiel #23
0
def test_success_response_null_result():
    # Perfectly fine.
    response = SuccessResponse(None, id=1)
    assert str(response) == '{"jsonrpc": "2.0", "result": null, "id": 1}'
Beispiel #24
0
def test_examples_mixed_requests_and_notifications():
    """
    We break the spec here. The examples put an invalid jsonrpc request in the
    mix here.  but it's removed to test the rest, because we're not validating
    each request individually. Any invalid jsonrpc will respond with a single
    error message.

    The spec example includes this which invalidates the entire request:
        {"foo": "boo"},
    """
    methods = {
        "sum": lambda *args: Right(SuccessResult(sum(args))),
        "notify_hello": lambda *args: Right(SuccessResult(19)),
        "subtract": lambda *args: Right(SuccessResult(args[0] - sum(args[1:]))),
        "get_data": lambda: Right(SuccessResult(["hello", 5])),
    }
    requests = json.dumps(
        [
            {"jsonrpc": "2.0", "method": "sum", "params": [1, 2, 4], "id": "1"},
            {"jsonrpc": "2.0", "method": "notify_hello", "params": [7]},
            {"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": "2"},
            {
                "jsonrpc": "2.0",
                "method": "foo.get",
                "params": {"name": "myself"},
                "id": "5",
            },
            {"jsonrpc": "2.0", "method": "get_data", "id": "9"},
        ]
    )
    response = dispatch_to_response_pure(
        deserializer=default_deserializer,
        validator=default_validator,
        post_process=identity,
        context=NOCONTEXT,
        methods=methods,
        request=requests,
    )
    expected = [
        Right(
            SuccessResponse(result=7, id="1")
        ),  # {"jsonrpc": "2.0", "result": 7, "id": "1"},
        Right(
            SuccessResponse(result=19, id="2")
        ),  # {"jsonrpc": "2.0", "result": 19, "id": "2"},
        Left(
            ErrorResponse(
                code=-32601, message="Method not found", data="foo.get", id="5"
            )
        ),
        # {
        #     "jsonrpc": "2.0",
        #     "error": {"code": -32601, "message": "Method not found", "data": "foo.get"},
        #     "id": "5",
        # },
        Right(
            SuccessResponse(result=["hello", 5], id="9")
        ),  # {"jsonrpc": "2.0", "result": ["hello", 5], "id": "9"},
    ]
    # assert isinstance(response, Iterable)
    for r in response:
        assert r in expected