Migration¶
From 3.x to 4.x¶
Version 4 is a rewrite. In 3.x, jsonrpcclient sent the request over HTTP (or another transport) for you. In 4.x it only builds the request and parses the response, and you send it with any library you like.
Old calls can fail silently
In 3.x, request("http://fruits.com", "get") sent get to that URL. In
4.x the first argument is the method name and the second is params. So
the same call returns a dict, sends nothing, and raises no error:
>>> from jsonrpcclient import request
>>> request("http://fruits.com", "get")
{'jsonrpc': '2.0', 'method': 'http://fruits.com', 'params': 'get', 'id': 1}
If your code still calls request with a URL first, nothing reaches the
server. Search your code for those calls when you upgrade. notify and
send no longer exist, so code that uses them fails at import. With keyword arguments, such as request(url, "get", color="yellow"),
you get TypeError: request() got an unexpected keyword argument 'color'
instead.
A request, before and after¶
3.x:
# jsonrpcclient 3.x. This doesn't run on 4.x.
from jsonrpcclient import request
response = request("http://localhost:8000/", "get", color="yellow")
print(response.data.result)
4.x, using requests to send it:
import requests
from jsonrpcclient import Error, Ok, parse, request
response = requests.post(
"http://localhost:8000/", json=request("add", [2, 3]), timeout=10
)
response.raise_for_status()
parsed = parse(response.json())
if isinstance(parsed, Ok):
print(parsed.result)
elif isinstance(parsed, Error):
print("Error:", parsed.message)
5
Keyword arguments become a dict: request("get", {"color": "yellow"}).
Positional arguments become a list: request("add", [2, 3]).
What changed¶
| 3.x | 4.x |
|---|---|
request(url, method, *args, **kwargs) sends a request |
request(method, params) returns a dict, and you send it |
notify(url, method, ...) |
notification(method, params), then send it |
send(url, request) |
send the request with your HTTP library |
HTTPClient(url).request(...), .notify(...), .send(...) |
requests, httpx or urllib |
jsonrpcclient.clients.* (aiohttp, tornado, websockets, zeromq, socket) |
the library itself, as in Transports |
client.some_method(...) attribute calls |
request("some_method", ...) |
Request("ping") and Notification("ping") classes |
the request and notification functions |
response.data.result |
parse(...).result, after checking you got an Ok |
response.data.ok |
isinstance(parsed, Ok) |
ReceivedErrorResponseError raised on an error response |
parse returns an Error. Raise your own exception if you want one, as in Error handling |
ReceivedNon2xxResponseError |
your HTTP library, such as response.raise_for_status() |
| jsonschema validation of responses | parse checks the response shape and raises InvalidResponse (4.1.0 and later) |
| logging of requests and responses | log the request dict and the reply yourself |
the jsonrpc command-line tool |
removed, see the FAQ |
pip install "jsonrpcclient[requests]" extras |
pip install jsonrpcclient requests (there are no extras) |
The 3.x documentation is no longer online. The changelog lists every 3.x change.
From 4.0 to 4.1¶
Most code needs no change. These are the differences you might notice.
A response with both result and error is now an Error. If error
is present and not null, parse returns an Error. 4.0 returned
Ok(result=None) and dropped the server's error. If you relied on that, check
for Error instead.
A broken error next to a result now raises. If a response has a
result and a non-null error that isn't an object with code and
message, such as "error": "boom" or "error": false, parse raises
InvalidResponse. 4.0 returned Ok and ignored the error. If a server you
use does this, catch InvalidResponse around parse.
Malformed responses raise InvalidResponse. It subclasses KeyError and
TypeError, which 4.0 raised, so existing except KeyError or
except TypeError clauses still work. You can now catch InvalidResponse
directly:
from jsonrpcclient import InvalidResponse, parse
try:
parse({"jsonrpc": "2.0", "result": "pong"})
except InvalidResponse as exc:
print(exc)
Invalid JSON-RPC response: missing 'id'
New error messages. parse_json('"pong"') used to say "Use parse_json on
strings". It now says it expected an object. Update any test that matches the
old text.
parse on bytes now raises TypeError: Use parse_json on strings, the
same as for a str.
Tuple params in notifications are now sent as a list. The JSON is the
same, but the dict that notification returns holds a list.
Type hints (4.0.4). parse has overloads and parse_json is no longer
typed as Any. Code that uses parse_json(...).result without an
isinstance check now fails mypy. See Typing.
Python 3.8 or later (4.0.4). Python 3.6 and 3.7 keep installing 4.0.3.