1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
|
#!/usr/bin/env python
from ..exc import *
class RPCRequest(object):
unique_id = None
"""A unique ID to remember the request by. Protocol specific, may or
may not be set. This value should only be set by
:py:func:`~tinyrpc.RPCProtocol.create_request`.
The ID allows client to receive responses out-of-order and still allocate
them to the correct request.
Only supported if the parent protocol has
:py:attr:`~tinyrpc.RPCProtocol.supports_out_of_order` set to ``True``.
"""
method = None
"""The name of the method to be called."""
args = []
"""The positional arguments of the method call."""
kwargs = {}
"""The keyword arguments of the method call."""
def error_respond(self, error):
"""Creates an error response.
Create a response indicating that the request was parsed correctly,
but an error has occured trying to fulfill it.
:param error: An exception or a string describing the error.
:return: A response or ``None`` to indicate that no error should be sent
out.
"""
raise NotImplementedError()
def respond(self, result):
"""Create a response.
Call this to return the result of a successful method invocation.
This creates and returns an instance of a protocol-specific subclass of
:py:class:`~tinyrpc.RPCResponse`.
:param result: Passed on to new response instance.
:return: A response or ``None`` to indicate this request does not expect a
response.
"""
raise NotImplementedError()
def serialize(self):
"""Returns a serialization of the request.
:return: A string to be passed on to a transport.
"""
raise NotImplementedError()
class RPCBatchRequest(list):
"""Multiple requests batched together.
A batch request is a subclass of :py:class:`list`. Protocols that support
multiple requests in a single message use this to group them together.
Handling a batch requests is done in any order, responses must be gathered
in a batch response and be in the same order as their respective requests.
Any item of a batch request is either a request or a subclass of
:py:class:`~tinyrpc.BadRequestError`, which indicates that there has been
an error in parsing the request.
"""
def create_batch_response(self):
"""Creates a response suitable for responding to this request.
:return: An :py:class:`~tinyrpc.RPCBatchResponse` or ``None``, if no
response is expected."""
raise NotImplementedError()
def serialize(self):
raise NotImplementedError()
class RPCResponse(object):
"""RPC call response class.
Base class for all deriving responses.
Has an attribute ``result`` containing the result of the RPC call, unless
an error occured, in which case an attribute ``error`` will contain the
error message."""
unique_id = None
def serialize(self):
"""Returns a serialization of the response.
:return: A reply to be passed on to a transport.
"""
raise NotImplementedError()
class RPCErrorResponse(RPCResponse):
pass
class RPCBatchResponse(list):
"""Multiple response from a batch request. See
:py:class:`~tinyrpc.RPCBatchRequest` on how to handle.
Items in a batch response need to be
:py:class:`~tinyrpc.RPCResponse` instances or None, meaning no reply should
generated for the request.
"""
def serialize(self):
"""Returns a serialization of the batch response."""
raise NotImplementedError()
class RPCProtocol(object):
"""Base class for all protocol implementations."""
supports_out_of_order = False
"""If true, this protocol can receive responses out of order correctly.
Note that this usually depends on the generation of unique_ids, the
generation of these may or may not be thread safe, depending on the
protocol. Ideally, only once instance of RPCProtocol should be used per
client."""
def create_request(self, method, args=None, kwargs=None, one_way=False):
"""Creates a new RPCRequest object.
It is up to the implementing protocol whether or not ``args``,
``kwargs``, one of these, both at once or none of them are supported.
:param method: The method name to invoke.
:param args: The positional arguments to call the method with.
:param kwargs: The keyword arguments to call the method with.
:param one_way: The request is an update, i.e. it does not expect a
reply.
:return: A new :py:class:`~tinyrpc.RPCRequest` instance.
"""
raise NotImplementedError()
def parse_request(self, data):
"""Parses a request given as a string and returns an
:py:class:`RPCRequest` instance.
:return: An instanced request.
"""
raise NotImplementedError()
def parse_reply(self, data):
"""Parses a reply and returns an :py:class:`RPCResponse` instance.
:return: An instanced response.
"""
raise NotImplementedError()
class RPCBatchProtocol(RPCProtocol):
def create_batch_request(self, requests=None):
"""Create a new :py:class:`tinyrpc.RPCBatchRequest` object.
:param requests: A list of requests.
"""
raise NotImplementedError()
|