Skip to main content
Archived

This project has been archived by its maintainers, and is no longer receiving any updates.

https://img.shields.io/pypi/status/typedjsonrpc.svg https://img.shields.io/pypi/l/typedjsonrpc.svg https://img.shields.io/pypi/pyversions/typedjsonrpc.svg https://img.shields.io/pypi/wheel/typedjsonrpc.svg https://badge.fury.io/py/typedjsonrpc.svg https://circleci.com/gh/palantir/typedjsonrpc.svg?style=shield

typedjsonrpc is a decorator-based JSON-RPC library for Python that exposes parameter and return types. It is influenced by Flask JSON-RPC but has some key differences:

typedjsonrpc…

  • allows return type checking

  • focuses on easy debugging

These docs are also available on Read the Docs.

Using typedjsonrpc

Installation

Use pip to install typedjsonrpc:

$ pip install typedjsonrpc

Project setup

To include typedjsonrpc in your project, use:

from typedjsonrpc.registry import Registry
from typedjsonrpc.server import Server

registry = Registry()
server = Server(registry)

The registry will keep track of methods that are available for JSON-RPC. Whenever you annotate a method, it will be added to the registry. You can always use the method rpc.describe() to get a description of all available methods. Server is a WSGI compatible app that handles requests. Server also has a development mode that can be run using server.run(host, port).

Example usage

Annotate your methods to make them accessible and provide type information:

@registry.method(returns=int, a=int, b=int)
def add(a, b):
    return a + b

@registry.method(returns=str, a=str, b=str)
def concat(a, b):
    return a + b

The return type has to be declared using the returns keyword. For methods that don’t return anything, you can use either type(None) or just None:

@registry.method(returns=type(None), a=str)
def foo(a):
    print(a)

@registry.method(returns=None, a=int)
def bar(a):
    print(5 * a)

You can use any of the basic JSON types:

JSON type

Python type

string

basestring (Python 2), str (Python 3)

number

int, float

null

None

boolean

bool

array

list

object

dict

Your functions may also accept *args and **kwargs, but you cannot declare their types. So the correct way to use these would be:

@registry.method(a=str)
def foo(a, *args, **kwargs):
    return a + str(args) + str(kwargs)

To check that everything is running properly, try (assuming add is declared in your main module):

$ curl -XPOST http://<host>:<port>/api -d @- <<EOF
{
    "jsonrpc": "2.0",
    "method": "__main__.add",
    "params": {
        "a": 5,
        "b": 7
    },
    "id": "foo"
}
EOF

{
    "jsonrpc": "2.0",
    "id": "foo",
    "result": 12
}

Passing any non-integer arguments into add will raise a InvalidParamsError.

Batching

You can send a list of JSON-RPC request objects as one request and will receive a list of JSON-RPC response objects in return. These response objects can be mapped back to the request objects using the id. Here’s an example of calling the add method with two sets of parameters:

$ curl -XPOST http://<host>:<port>/api -d @- <<EOF
[
    {
        "jsonrpc": "2.0",
        "method": "__main__.add",
        "params": {
            "a": 5,
            "b": 7
        },
        "id": "foo"
    }, {
        "jsonrpc": "2.0",
        "method": "__main__.add",
        "params": {
            "a": 42,
            "b": 1337
        },
        "id": "bar"
    }
]
EOF

[
    {
        "jsonrpc": "2.0",
        "id": "foo",
        "result": 12
    }, {
        "jsonrpc": "2.0",
        "id": "bar",
        "result": 1379
    }
]

Debugging

If you create the registry with the parameter debug=True, you’ll be able to use werkzeug’s debugger. In that case, if there is an error during execution - e.g. you tried to use a string as one of the parameters for add - the response will contain an error object with a debug_url:

$ curl -XPOST http://<host>:<port>/api -d @- <<EOF
{
    "jsonrpc": "2.0",
    "method": "__main__.add",
    "params": {
        "a": 42,
        "b": "hello"
    },
    "id": "bar"
}
EOF

{
    "jsonrpc": "2.0",
    "id": "bar",
    "error": {
        "message": "Invalid params",
        "code": -32602,
        "data": {
            "message": "Value 'hello' for parameter 'b' is not of expected type <type 'int'>.",
            "debug_url": "/debug/1234567890"
        }
    }
}

This tells you to find the traceback interpreter at <host>:<port>/debug/1234567890.

Logging

The registry has a default logger in the module typedjsonrpc.registry and it logs all errors that are not defined by typedjsonrpc. You can configure the logger as follows:

import logging
logger = logging.getLogger("typedjsonrpc.registry")
# Do configuration to this logger

HTTP status codes

Since typedjsonrpc 0.4.0, HTTP status codes were added to the responses from the typedjsonrpc.server.Server class. This is to improve the usage of typedjsonrpc over HTTP. The following chart are the satus codes which are returned:

Condition

Batched

Status code

Success

Y

200

N

200

All notifications

Y

204

N

204

ParseError or InvalidRequestError

Y

200

N

400

MethodNotFoundError

Y

200

N

404

All other errors

Y

200

N

500

Additional features

Customizing type serialization

If you would like to serialize custom types, you can set the json_encoder and json_decoder attributes on Server to your own custom json.JSONEncoder and json.JSONDecoder instance. By default, we use the default encoder and decoder.

Adding hooks before the first request

You can add functions to run before the first request is called. This can be useful for some special setup you need for your WSGI app. For example, you can register a function to print debugging information before your first request:

import datetime

from typedjsonrpc.registry import Registry
from typedjsonrpc.server import Server

registry = Registry()
server = Server(registry)

def print_time():
    now = datetime.datetime.now()
    print("Handling first request at: {}".format(now))

server.register_before_first_request(print_time)

Accessing the HTTP request from JSON-RPC methods

In some situations, you may want to access the HTTP request from your JSON-RPC method. For example, you could need to perform logic based on headers in the request. In the typedjsonrpc.server module, there is a special typedjsonrpc.server.current_request attribute which allows you to access the HTTP request which was used to call the current method.

Example:

from typedjsonrpc.server import current_request

@registry.method(returns=list)
def get_headers():
    return list(current_request.headers)

Disabling strictness of floats

typedjsonrpc by default will only accept floats into a float typed parameter. For example, if your function were this:

import math

@registry.method(returns=int, x=float)
def floor(x):
    return int(math.floor(x))

and your input were this:

{
    "jsonrpc": "2.0",
    "method": "floor",
    "params": {
        "x": 1
    },
    "id": "foo"
}

You would get an invalid param error like this:

{
    "error": {
        "code": -32602,
        "data": {
            "debug_url": "/debug/4456954960",
            "message": "Value '1' for parameter 'x' is not of expected type <type 'float'>."
        },
        "message": "Invalid params"
    },
    "id": "foo",
    "jsonrpc": "2.0"
}

This can actually frequently come up when you use a JSON encoder. A JSON encoder may choose to write the float 1.0 as an integer 1. In order to get around this, you can manually edit the JSON or set strict_floats to False in your typedjsonrpc.registry.Registry.

Release files for typedjsonrpc 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for typedjsonrpc 0.4.0
File Size Uploaded
typedjsonrpc-0.4.0.tar.gz 32.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for typedjsonrpc 0.4.0
File Interpreter ABI Platform
typedjsonrpc-0.4.0-py2.py3-none-any.whl Python 2, Python 3 none any Details

Total release size:54.6 kB

Release files / typedjsonrpc-0.4.0.tar.gz

Download URL typedjsonrpc-0.4.0.tar.gz
Size 32.2 kB
Tags Source
SHA-256 checksum
How to use checksums
e2bc43e25bc6935681668f89f0223ab0f254a6dc4c532dd73ec9fce49dda85bf
BLAKE2b-256 checksum
How to use checksums
54d6c027e0326bd0728c9667940e8ce17b35c03cb0e27d1234e906e4ba45195c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Release files / typedjsonrpc-0.4.0-py2.py3-none-any.whl

Download URL typedjsonrpc-0.4.0-py2.py3-none-any.whl
Size 22.5 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
0bccb01c1f2d90c19caceebe5cc45e0d31d5ff1eeb308c03d5fa77ddf0765df3
BLAKE2b-256 checksum
How to use checksums
fe521f32bf002e570261e83064605428cd2e67ec6e046f6f5b49a8dbfb0779e6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Release history Release notifications | RSS feed

This release

0.4.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page