mirror of
https://github.com/home-assistant/core.git
synced 2025-07-27 07:07:28 +00:00
JSON serialize NamedTuple subclasses with aiohttp (#74971)
This commit is contained in:
parent
ef025bccc0
commit
da027fa390
@ -14,7 +14,6 @@ from aiohttp import web
|
|||||||
from aiohttp.hdrs import CONTENT_TYPE, USER_AGENT
|
from aiohttp.hdrs import CONTENT_TYPE, USER_AGENT
|
||||||
from aiohttp.web_exceptions import HTTPBadGateway, HTTPGatewayTimeout
|
from aiohttp.web_exceptions import HTTPBadGateway, HTTPGatewayTimeout
|
||||||
import async_timeout
|
import async_timeout
|
||||||
import orjson
|
|
||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
from homeassistant.const import EVENT_HOMEASSISTANT_CLOSE, __version__
|
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 homeassistant.util import ssl as ssl_util
|
||||||
|
|
||||||
from .frame import warn_use
|
from .frame import warn_use
|
||||||
|
from .json import json_dumps
|
||||||
|
|
||||||
DATA_CONNECTOR = "aiohttp_connector"
|
DATA_CONNECTOR = "aiohttp_connector"
|
||||||
DATA_CONNECTOR_NOTVERIFY = "aiohttp_connector_notverify"
|
DATA_CONNECTOR_NOTVERIFY = "aiohttp_connector_notverify"
|
||||||
@ -98,7 +98,7 @@ def _async_create_clientsession(
|
|||||||
"""Create a new ClientSession with kwargs, i.e. for cookies."""
|
"""Create a new ClientSession with kwargs, i.e. for cookies."""
|
||||||
clientsession = aiohttp.ClientSession(
|
clientsession = aiohttp.ClientSession(
|
||||||
connector=_async_get_connector(hass, verify_ssl),
|
connector=_async_get_connector(hass, verify_ssl),
|
||||||
json_serialize=lambda x: orjson.dumps(x).decode("utf-8"),
|
json_serialize=json_dumps,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
)
|
)
|
||||||
# Prevent packages accidentally overriding our default headers
|
# Prevent packages accidentally overriding our default headers
|
||||||
|
@ -19,6 +19,7 @@ from homeassistant.const import (
|
|||||||
)
|
)
|
||||||
from homeassistant.core import EVENT_HOMEASSISTANT_CLOSE
|
from homeassistant.core import EVENT_HOMEASSISTANT_CLOSE
|
||||||
import homeassistant.helpers.aiohttp_client as client
|
import homeassistant.helpers.aiohttp_client as client
|
||||||
|
from homeassistant.util.color import RGBColor
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
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
|
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):
|
async def test_client_session_immutable_headers(hass):
|
||||||
"""Test we can't mutate headers."""
|
"""Test we can't mutate headers."""
|
||||||
session = client.async_get_clientsession(hass)
|
session = client.async_get_clientsession(hass)
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
import datetime
|
import datetime
|
||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
|
from typing import NamedTuple
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@ -13,6 +14,7 @@ from homeassistant.helpers.json import (
|
|||||||
json_dumps_sorted,
|
json_dumps_sorted,
|
||||||
)
|
)
|
||||||
from homeassistant.util import dt as dt_util
|
from homeassistant.util import dt as dt_util
|
||||||
|
from homeassistant.util.color import RGBColor
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("encoder", (JSONEncoder, ExtendedJSONEncoder))
|
@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))
|
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]"
|
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]"
|
||||||
|
@ -111,7 +111,7 @@ class AiohttpClientMocker:
|
|||||||
|
|
||||||
def create_session(self, loop):
|
def create_session(self, loop):
|
||||||
"""Create a ClientSession that is bound to this mocker."""
|
"""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
|
# Setting directly on `session` will raise deprecation warning
|
||||||
object.__setattr__(session, "_request", self.match_request)
|
object.__setattr__(session, "_request", self.match_request)
|
||||||
return session
|
return session
|
||||||
|
Loading…
x
Reference in New Issue
Block a user