Expose BaseRequest.parse_json_payload (#3072)

This commit is contained in:
Bibo-Joshi 2022-06-01 21:26:18 +02:00 committed by GitHub
parent 6ded9cc25c
commit 67869693a7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 7 deletions

View file

@ -68,6 +68,11 @@ class BaseRequest(
finally:
await request_object.shutdown()
Tip:
JSON encoding and decoding is done with the standard library's :mod:`json` by default.
To use a custom library for this, you can override :meth:`parse_json_payload` and implement
custom logic to encode the keys of :attr:`telegram.request.RequestData.parameters`.
.. versionadded:: 20.0
"""
@ -163,7 +168,7 @@ class BaseRequest(
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
)
json_data = self._parse_json_response(result)
json_data = self.parse_json_payload(result)
# For successful requests, the results are in the 'result' entry
# see https://core.telegram.org/bots/api#making-requests
return json_data["result"]
@ -285,7 +290,7 @@ class BaseRequest(
# 200-299 range are HTTP success statuses
return payload
response_data = self._parse_json_response(payload)
response_data = self.parse_json_payload(payload)
description = response_data.get("description")
if description:
@ -325,16 +330,24 @@ class BaseRequest(
raise NetworkError(f"{message} ({code})")
@staticmethod
def _parse_json_response(json_payload: bytes) -> JSONDict:
"""Try and parse the JSON returned from Telegram.
def parse_json_payload(payload: bytes) -> JSONDict:
"""Parse the JSON returned from Telegram.
Tip:
By default, this method uses the standard library's :func:`json.loads` and
``errors="replace"`` in :meth:`bytes.decode`.
You can override it to customize either of these behaviors.
Args:
payload (:obj:`bytes`): The UTF-8 encoded JSON payload as returned by Telegram.
Returns:
dict: A JSON parsed as Python dict with results.
Raises:
TelegramError: If the data could not be json_loaded
TelegramError: If loading the JSON data failed
"""
decoded_s = json_payload.decode("utf-8", "replace")
decoded_s = payload.decode("utf-8", "replace")
try:
return json.loads(decoded_s)
except ValueError as exc:

View file

@ -64,6 +64,11 @@ class RequestData:
def json_parameters(self) -> Dict[str, str]:
"""Gives the parameters as mapping of parameter name to the respective JSON encoded
value.
Tip:
By default, this property uses the standard library's :func:`json.dumps`.
To use a custom library for JSON encoding, you can directly encode the keys of
:attr:`parameters` - note that string valued keys should not be JSON encoded.
"""
return {
param.name: param.json_value
@ -96,7 +101,13 @@ class RequestData:
@property
def json_payload(self) -> bytes:
"""The parameters as UTF-8 encoded JSON payload."""
"""The :attr:`parameters` as UTF-8 encoded JSON payload.
Tip:
By default, this property uses the standard library's :func:`json.dumps`.
To use a custom library for JSON encoding, you can directly encode the keys of
:attr:`parameters` - note that string valued keys should not be JSON encoded.
"""
return json.dumps(self.json_parameters).encode("utf-8")
@property

View file

@ -129,6 +129,9 @@ class TestRequest:
monkeypatch.setattr(httpx_request, "do_request", mocker_factory(response=server_response))
assert await httpx_request.post(None, None, None) == "test_string<EFBFBD>"
# Explicitly call `parse_json_payload` here is well so that this public method is covered
# not only implicitly.
assert httpx_request.parse_json_payload(server_response) == {"result": "test_string<EFBFBD>"}
async def test_illegal_json_response(self, monkeypatch, httpx_request: HTTPXRequest):
# for proper JSON it should be `"result":` instead of `result:`