gruvi.jsonrpc
– JSON-RPC Client and Server¶
The gruvi.jsonrpc
module implements a JSON-RPC client and server.
There are two version of JSON-RPC: version 1.0 and version 2.0. While these
versions are similar, they are not mutually compatible. The classes exposed by
this module implement both versions. The default version to use is stored in
JsonRpcProtocol.default_version
, and most constructors take an argument
that can be used to override this.
The “batch” feature of version 2.0 is not supported. It more relevant for JSON-RPC over HTTP rather for that clients and servers that operate directly on top of a connection.
The two main classes in this module are JsonRpcClient
and
JsonRpcServer
. The difference is only who initiates the connection at
the transport level. The JSON-RPC protocol itself does not distinguish between
clients and servers.
Both the client and the server can receive and respond to incoming messages. These may be method calls (more common for servers), or notifications (common for both client and servers). These incoming messages are handled by a message handler, which is mandatory for a server and optional for a client. Note that for simple blocking method callls from client to a server no message handler is needed.
Message handlers run in a separate dispatcher fiber, one per connection. This means that a client will have at most one dispatcher fiber, while a server will have exactly one fiber per connection. Because they run in a separate fiber, message handlers can call into switchpoints themselves.
-
REQUEST
¶ Constant indicating a JSON-RPC request message.
-
RESPONSE
¶ Constant indicating a JSON-RPC response message.
-
errorcode
{...}¶ Dictionary mapping error codes to error names.
-
strerror
(code)¶ Return an error message for error code.
The error code is the
error.code
field of a JSON-RPC response message. The JSON-RPC version 2 spec contains a list of standard error codes.
-
exception
JsonRpcError
¶ Exception that is raised in case of JSON-RPC errors.
-
error
¶ The
error
field from the JSON-RPC response, if available.
-
-
class
JsonRpcVersion
(name)¶ Class that encapsulates the differences between JSON-RPC vesion 1.0 and 2.0.
-
name
¶ Return the JSON-RPC version as a string, e.g. ‘1.0’.
-
next_id
()¶ Return a unique message ID.
-
static
create
(version)¶ Return a new instance for version, which can be either ‘1.0’ or ‘2.0’.
-
check_message
(message)¶ Check message and return the message type. Raise a ValueError in case of an invalid message.
-
create_request
(method, args=None, notification=False)¶ Create a new request message for method with arguments args.
The optional notification argument, if nonzero, creates a notification and no response to this message is expected.
-
create_response
(request, result=None, error=None)¶ Create a new response message, as a response to request.
A successful response is created when the optional error argument is not provided. In this case result specifies the result, which may be any value including
None
. If error is provided, an error response is created, and error should be a dict as specified by the JSON-RPC specifications.The request argument may be explicitly set to
None
, in which case this is an error response that is not specific to any one request.
-
-
class
JsonRpcProtocol
(handler=None, version=None, timeout=None)¶ A JSON-RPC client and server
Protocol
implementation.-
default_timeout
= 30¶ Class level attribute that specifies the default timeout.
-
default_version
= '2.0'¶ Class level attribute that specifies the default JSON-RPC version.
-
version
¶ Return the
JsonRpcVersion
instance for this protocol.
-
switchpoint
send_message
(message)¶ Send a raw JSON-RPC message.
The message argument must be a dictionary containing a valid JSON-RPC message according to the version passed into the constructor.
-
switchpoint
call_method
(method, *args)¶ Call a JSON-RPC method and wait for its result.
The method is called with positional arguments args.
On success, the
result
field from the JSON-RPC response is returned. On error, aJsonRpcError
is raised, which you can use to access theerror
field of the JSON-RPC response.
-
switchpoint
send_notification
(method, *args)¶ Send a JSON-RPC notification.
The notification method is sent with positional arguments args.
-
switchpoint
send_response
(request, result=None, error=None)¶ Respond to a JSON-RPC method call.
This is a response to the message in request. If error is not provided, then this is a succesful response, and the value in result, which may be
None
, is passed back to the client. if error is provided and notNone
then an error is sent back. In this case error must be a dictionary as specified by the JSON-RPC spec.
-
-
class
JsonRpcClient
(handler=None, version=None, timeout=None)¶ A JSON-RPC
Client
.The handler argument specifies an optional JSON-RPC message handler. You need to supply a message handler if you want to listen to notifications or you want to respond to server-to-client method calls. If provided, the message handler it must be a callable with signature
handler(message, transport, protocol)
.The version and timeout argument can be used to override the default protocol version and timeout, respectively.
-
protocol
¶ Return the protocol, or
None
if not connected.
-
switchpoint
call_method
(method, *args)¶ A shorthand for
self.protocol.call_method()
.
-
switchpoint
send_message
(message)¶ A shorthand for
self.protocol.send_message()
.
-
switchpoint
send_notification
(method, *args)¶ A shorthand for
self.protocol.send_notification()
.
-
-
class
JsonRpcServer
(handler, version=None, timeout=None)¶ A JSON-RPC
Server
.The handler argument specifies the JSON-RPC message handler. It must be a callable with signature
handler(message, transport, protocol)
. The message handler is called in a separate dispatcher fiber (one per connection).The version and timeout argument can be used to override the default protocol version and timeout, respectively.
Example¶
# Ping-pong between JSON-RPC client and server.
from gruvi.jsonrpc import JsonRpcClient, JsonRpcServer
def handler(message, transport, protocol):
method = message.get('method')
if method == 'ping':
protocol.send_response(message, 'pong')
server = JsonRpcServer(handler)
server.listen(('localhost', 0))
addr = server.addresses[0]
client = JsonRpcClient()
client.connect(addr)
result = client.call_method('ping')
print('result = {}'.format(result))