Make most types serializable

This commit is contained in:
Jules 2025-05-13 20:35:22 +02:00
parent 9b1752c096
commit 7efc8170c5
Signed by: jdejaegh
GPG key ID: 99D6D184CA66933A
8 changed files with 68 additions and 12 deletions

View file

@ -1,6 +1,6 @@
"""Data classes for IRM KMI integration""" """Data classes for IRM KMI integration"""
from datetime import datetime from datetime import datetime
from enum import Enum from enum import StrEnum
from typing import List, Required, TypedDict from typing import List, Required, TypedDict
@ -36,7 +36,7 @@ class Forecast(TypedDict, total=False):
is_daytime: bool | None # Mandatory to use with forecast_twice_daily is_daytime: bool | None # Mandatory to use with forecast_twice_daily
class ConditionEvol(Enum): class ConditionEvol(StrEnum):
"""Possible state for evolution between weather conditions""" """Possible state for evolution between weather conditions"""
ONE_WAY = 'one_way' ONE_WAY = 'one_way'
@ -44,7 +44,7 @@ class ConditionEvol(Enum):
STABLE = 'stable' STABLE = 'stable'
class RadarStyle(Enum): class RadarStyle(StrEnum):
"""Possible style for the rain radar""" """Possible style for the rain radar"""
OPTION_STYLE_STD = 'standard_style' OPTION_STYLE_STD = 'standard_style'
@ -53,7 +53,7 @@ class RadarStyle(Enum):
OPTION_STYLE_SATELLITE = 'satellite_style' OPTION_STYLE_SATELLITE = 'satellite_style'
class PollenName(Enum): class PollenName(StrEnum):
ALDER = 'alder' ALDER = 'alder'
ASH = 'ash' ASH = 'ash'
BIRCH = 'birch' BIRCH = 'birch'
@ -63,7 +63,7 @@ class PollenName(Enum):
OAK = 'oak' OAK = 'oak'
class PollenLevel(Enum): class PollenLevel(StrEnum):
"""Possible pollen levels""" """Possible pollen levels"""
NONE = 'none' NONE = 'none'
@ -74,7 +74,7 @@ class PollenLevel(Enum):
RED = 'red' RED = 'red'
PURPLE = 'purple' PURPLE = 'purple'
class WarningType(Enum): class WarningType(StrEnum):
"""Possible warning types""" """Possible warning types"""
COLD = 'cold' COLD = 'cold'

View file

@ -21,3 +21,15 @@ def get_api_with_data(fixture: str) -> IrmKmiApiClientHa:
api = IrmKmiApiClientHa(session=MagicMock(), user_agent='', cdt_map=IRM_KMI_TO_HA_CONDITION_MAP) api = IrmKmiApiClientHa(session=MagicMock(), user_agent='', cdt_map=IRM_KMI_TO_HA_CONDITION_MAP)
api._api_data = get_api_data(fixture) api._api_data = get_api_data(fixture)
return api return api
def is_serializable(x):
try:
json.dumps(x)
return True
except (TypeError, OverflowError):
return False
def assert_all_serializable(elements: list):
for element in elements:
for v in element.values():
assert is_serializable(v)

View file

@ -5,7 +5,7 @@ import pytest
from freezegun import freeze_time from freezegun import freeze_time
from irm_kmi_api import CurrentWeatherData from irm_kmi_api import CurrentWeatherData
from tests.conftest import get_api_data, get_api_with_data from tests.conftest import get_api_data, get_api_with_data, is_serializable
from irm_kmi_api.const import ATTR_CONDITION_CLOUDY, ATTR_CONDITION_PARTLYCLOUDY from irm_kmi_api.const import ATTR_CONDITION_CLOUDY, ATTR_CONDITION_PARTLYCLOUDY
@ -140,3 +140,10 @@ def test_current_weather_attributes(
assert r == expected_ assert r == expected_
run(sensor, expected) run(sensor, expected)
@freeze_time(datetime.fromisoformat('2023-12-26T17:30:00+00:00'))
def test_current_weather_is_serializable() -> None:
api = get_api_with_data("forecast.json")
tz = ZoneInfo("Europe/Brussels")
result = api.get_current_weather(tz)
assert is_serializable(result)

View file

@ -4,7 +4,7 @@ from zoneinfo import ZoneInfo
from freezegun import freeze_time from freezegun import freeze_time
from irm_kmi_api import ConditionEvol, ExtendedForecast from irm_kmi_api import ConditionEvol, ExtendedForecast
from tests.conftest import get_api_with_data from tests.conftest import get_api_with_data, assert_all_serializable
from irm_kmi_api.const import ATTR_CONDITION_PARTLYCLOUDY from irm_kmi_api.const import ATTR_CONDITION_PARTLYCLOUDY
@ -106,3 +106,11 @@ async def test_sunrise_sunset_be() -> None:
assert result[2]['sunrise'] == '2023-12-28T08:45:00+01:00' assert result[2]['sunrise'] == '2023-12-28T08:45:00+01:00'
assert result[2]['sunset'] == '2023-12-28T16:43:00+01:00' assert result[2]['sunset'] == '2023-12-28T16:43:00+01:00'
def test_daily_serializable() -> None:
api = get_api_with_data("forecast.json")
tz = ZoneInfo("Europe/Brussels")
result = api.get_daily_forecast(tz, 'fr')
assert_all_serializable(result)

View file

@ -4,7 +4,7 @@ from zoneinfo import ZoneInfo
from freezegun import freeze_time from freezegun import freeze_time
from irm_kmi_api import Forecast from irm_kmi_api import Forecast
from tests.conftest import get_api_with_data from tests.conftest import get_api_with_data, assert_all_serializable
from irm_kmi_api.const import ATTR_CONDITION_CLOUDY, ATTR_CONDITION_RAINY from irm_kmi_api.const import ATTR_CONDITION_CLOUDY, ATTR_CONDITION_RAINY
@ -88,4 +88,10 @@ def test_hourly_forecast_midnight_bug() -> None:
assert result[24]['datetime'] == '2024-06-01T00:00:00+02:00' assert result[24]['datetime'] == '2024-06-01T00:00:00+02:00'
def test_hourly_serializable() -> None:
api = get_api_with_data("forecast.json")
tz = ZoneInfo("Europe/Brussels")
result = api.get_hourly_forecast(tz)
assert_all_serializable(result)

View file

@ -1,7 +1,7 @@
from unittest.mock import AsyncMock from unittest.mock import AsyncMock
from irm_kmi_api import PollenLevel, PollenName, PollenParser from irm_kmi_api import PollenLevel, PollenName, PollenParser
from tests.conftest import get_api_with_data, load_fixture from tests.conftest import get_api_with_data, load_fixture, is_serializable
def test_svg_pollen_parsing(): def test_svg_pollen_parsing():
@ -76,3 +76,9 @@ async def test_pollen_data_from_api() -> None:
PollenName.HAZEL: PollenLevel.NONE} PollenName.HAZEL: PollenLevel.NONE}
assert result == expected assert result == expected
def test_pollen_is_serializable():
with open("tests/fixtures/pollens-2025.svg", "r") as file:
svg_data = file.read()
data = PollenParser(svg_data).get_pollen_data()
assert is_serializable(data)

View file

@ -1,7 +1,7 @@
import pytest import pytest
from irm_kmi_api import RadarForecast from irm_kmi_api import RadarForecast
from tests.conftest import get_api_with_data from tests.conftest import get_api_with_data, assert_all_serializable
def test_radar_forecast() -> None: def test_radar_forecast() -> None:
@ -78,3 +78,10 @@ async def test_current_rainfall_unit(
for r in radar_forecast: for r in radar_forecast:
assert r.get('unit') == expected assert r.get('unit') == expected
def test_radar_serializable() -> None:
api = get_api_with_data("forecast.json")
result = api.get_radar_forecast()
assert_all_serializable(result)

View file

@ -3,7 +3,7 @@ from datetime import datetime
from freezegun import freeze_time from freezegun import freeze_time
from irm_kmi_api import WarningType from irm_kmi_api import WarningType
from tests.conftest import get_api_with_data from tests.conftest import get_api_with_data, is_serializable
@freeze_time(datetime.fromisoformat('2024-01-12T07:10:00+00:00')) @freeze_time(datetime.fromisoformat('2024-01-12T07:10:00+00:00'))
@ -23,3 +23,13 @@ async def test_warning_data() -> None:
assert first.get('friendly_name') == 'Fog' assert first.get('friendly_name') == 'Fog'
assert first.get('id') == 7 assert first.get('id') == 7
assert first.get('level') == 1 assert first.get('level') == 1
async def test_warning_data_is_serializable() -> None:
api = get_api_with_data("be_forecast_warning.json")
result = api.get_warnings(lang='en')
for r in result:
del r["starts_at"]
del r["ends_at"]
assert is_serializable(r)