JSON serialize NamedTuple subclasses with aiohttp (#74971)

pull/75147/head
J. Nick Koston 2022-07-11 23:46:55 +02:00 committed by Paulus Schoutsen
parent 4d81d056da
commit c45313e9de
4 changed files with 36 additions and 3 deletions

View File

@ -14,7 +14,6 @@ from aiohttp import web
from aiohttp.hdrs import CONTENT_TYPE, USER_AGENT
from aiohttp.web_exceptions import HTTPBadGateway, HTTPGatewayTimeout
import async_timeout
import orjson
from homeassistant import config_entries
from homeassistant.const import EVENT_HOMEASSISTANT_CLOSE, __version__
@ -23,6 +22,7 @@ from homeassistant.loader import bind_hass
from homeassistant.util import ssl as ssl_util
from .frame import warn_use
from .json import json_dumps
DATA_CONNECTOR = "aiohttp_connector"
DATA_CONNECTOR_NOTVERIFY = "aiohttp_connector_notverify"
@ -98,7 +98,7 @@ def _async_create_clientsession(
"""Create a new ClientSession with kwargs, i.e. for cookies."""
clientsession = aiohttp.ClientSession(
connector=_async_get_connector(hass, verify_ssl),
json_serialize=lambda x: orjson.dumps(x).decode("utf-8"),
json_serialize=json_dumps,
**kwargs,
)
# Prevent packages accidentally overriding our default headers

View File

@ -19,6 +19,7 @@ from homeassistant.const import (
)
from homeassistant.core import EVENT_HOMEASSISTANT_CLOSE
import homeassistant.helpers.aiohttp_client as client
from homeassistant.util.color import RGBColor
from tests.common import MockConfigEntry
@ -215,6 +216,16 @@ async def test_async_aiohttp_proxy_stream_client_err(aioclient_mock, camera_clie
assert resp.status == 502
async def test_sending_named_tuple(hass, aioclient_mock):
"""Test sending a named tuple in json."""
resp = aioclient_mock.post("http://127.0.0.1/rgb", json={"rgb": RGBColor(4, 3, 2)})
session = client.async_create_clientsession(hass)
resp = await session.post("http://127.0.0.1/rgb", json={"rgb": RGBColor(4, 3, 2)})
assert resp.status == 200
await resp.json() == {"rgb": RGBColor(4, 3, 2)}
aioclient_mock.mock_calls[0][2]["rgb"] == RGBColor(4, 3, 2)
async def test_client_session_immutable_headers(hass):
"""Test we can't mutate headers."""
session = client.async_get_clientsession(hass)

View File

@ -2,6 +2,7 @@
import datetime
import json
import time
from typing import NamedTuple
import pytest
@ -13,6 +14,7 @@ from homeassistant.helpers.json import (
json_dumps_sorted,
)
from homeassistant.util import dt as dt_util
from homeassistant.util.color import RGBColor
@pytest.mark.parametrize("encoder", (JSONEncoder, ExtendedJSONEncoder))
@ -96,3 +98,23 @@ def test_json_dumps_tuple_subclass():
tt = time.struct_time((1999, 3, 17, 32, 44, 55, 2, 76, 0))
assert json_dumps(tt) == "[1999,3,17,32,44,55,2,76,0]"
def test_json_dumps_named_tuple_subclass():
"""Test the json dumps a tuple subclass."""
class NamedTupleSubclass(NamedTuple):
"""A NamedTuple subclass."""
name: str
nts = NamedTupleSubclass("a")
assert json_dumps(nts) == '["a"]'
def test_json_dumps_rgb_color_subclass():
"""Test the json dumps of RGBColor."""
rgb = RGBColor(4, 2, 1)
assert json_dumps(rgb) == "[4,2,1]"

View File

@ -111,7 +111,7 @@ class AiohttpClientMocker:
def create_session(self, loop):
"""Create a ClientSession that is bound to this mocker."""
session = ClientSession(loop=loop)
session = ClientSession(loop=loop, json_serialize=json_dumps)
# Setting directly on `session` will raise deprecation warning
object.__setattr__(session, "_request", self.match_request)
return session