Skip to content

Commit

Permalink
Use base class for API response model
Browse files Browse the repository at this point in the history
  • Loading branch information
dext0r committed Oct 3, 2023
1 parent 34e2d53 commit 724eec8
Show file tree
Hide file tree
Showing 20 changed files with 127 additions and 106 deletions.
6 changes: 3 additions & 3 deletions custom_components/yandex_smart_home/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ async def execute(
)

if error_code_template := self._error_code_template:
if error_code := error_code_template.async_render(capability=action.dict(), parse_result=False):
if error_code := error_code_template.async_render(capability=action.as_dict(), parse_result=False):
if error_code not in const.ERROR_CODES:
raise SmartHomeError(const.ERR_INTERNAL_ERROR, f"Invalid error code for {self.id}: {error_code!r}")

Expand Down Expand Up @@ -390,7 +390,7 @@ def __init__(self, device: Device, event_entity_id: str, initial_report: bool =

for device_capability in [c for c in device.get_capabilities() if c.reportable]:
if (capability_state := device_capability.get_instance_state()) is not None:
self.capabilities.append(capability_state.dict())
self.capabilities.append(capability_state.as_dict())

for device_property in [c for c in device.get_properties() if c.reportable]:
if device_property.value_entity_id != event_entity_id:
Expand All @@ -404,7 +404,7 @@ def __init__(self, device: Device, event_entity_id: str, initial_report: bool =

property_state = device_property.get_instance_state()
if property_state is not None:
self.properties.append(property_state.dict())
self.properties.append(property_state.as_dict())

@property
def should_report(self) -> bool:
Expand Down
2 changes: 1 addition & 1 deletion custom_components/yandex_smart_home/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ async def async_devices_action(hass: HomeAssistant, data: RequestData, payload:

hass.bus.async_fire(
EVENT_DEVICE_ACTION,
{ATTR_ENTITY_ID: device_id, "capability": action.dict()},
{ATTR_ENTITY_ID: device_id, "capability": action.as_dict()},
context=data.context,
)

Expand Down
2 changes: 1 addition & 1 deletion custom_components/yandex_smart_home/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ async def _async_handle_request(self, hass: HomeAssistant, request: Request, dat
result = await handlers.async_handle_request(
hass, data, action=request.path.replace(self.url, "", 1), payload=await request.text()
)
response = json_response(text=result.json(exclude_none=True, ensure_ascii=False))
response = json_response(text=result.as_json())
_LOGGER.debug(f"Response: {response.text}")

return response
Expand Down
21 changes: 21 additions & 0 deletions custom_components/yandex_smart_home/schema/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""Base class for API response schemas."""
from typing import Any

from pydantic import BaseModel
from pydantic.generics import GenericModel


class APIModel(BaseModel):
"""Base API response model."""

def as_json(self) -> str:
"""Generate a JSON representation of the model."""
return super().json(exclude_none=True, ensure_ascii=False)

def as_dict(self) -> dict[str, Any]:
"""Generate a dictionary representation of the model."""
return super().dict(exclude_none=True)


class GenericAPIModel(GenericModel, APIModel):
"""Base generic API response model."""
21 changes: 11 additions & 10 deletions custom_components/yandex_smart_home/schema/capability.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
from enum import StrEnum
from typing import Annotated, Any, Literal, TypeVar, Union

from pydantic import BaseModel, Field
from pydantic import Field

from .base import APIModel
from .capability_color import (
ColorSettingCapabilityInstance,
ColorSettingCapabilityInstanceActionState,
Expand Down Expand Up @@ -56,7 +57,7 @@ class CapabilityType(StrEnum):
"""All capability instances."""


class CapabilityDescription(BaseModel):
class CapabilityDescription(APIModel):
"""Description of a capability for a device list request."""

type: CapabilityType
Expand All @@ -65,56 +66,56 @@ class CapabilityDescription(BaseModel):
parameters: CapabilityParameters | None


class CapabilityInstanceStateValue(BaseModel):
class CapabilityInstanceStateValue(APIModel):
"""Capability instance value."""

instance: CapabilityInstance
value: Any


class CapabilityInstanceState(BaseModel):
class CapabilityInstanceState(APIModel):
"""Capability state for state query and callback requests."""

type: CapabilityType
state: CapabilityInstanceStateValue


class OnOffCapabilityInstanceAction(BaseModel):
class OnOffCapabilityInstanceAction(APIModel):
"""New capability state for a state change request of on_off capability."""

type: Literal[CapabilityType.ON_OFF] = CapabilityType.ON_OFF
state: OnOffCapabilityInstanceActionState


class ColorSettingCapabilityInstanceAction(BaseModel):
class ColorSettingCapabilityInstanceAction(APIModel):
"""New capability state for a state change request of color_setting capability."""

type: Literal[CapabilityType.COLOR_SETTING] = CapabilityType.COLOR_SETTING
state: ColorSettingCapabilityInstanceActionState


class ModeCapabilityInstanceAction(BaseModel):
class ModeCapabilityInstanceAction(APIModel):
"""New capability state for a state change request of mode capability."""

type: Literal[CapabilityType.MODE] = CapabilityType.MODE
state: ModeCapabilityInstanceActionState


class RangeCapabilityInstanceAction(BaseModel):
class RangeCapabilityInstanceAction(APIModel):
"""New capability state for a state change request of range capability."""

type: Literal[CapabilityType.RANGE] = CapabilityType.RANGE
state: RangeCapabilityInstanceActionState


class ToggleCapabilityInstanceAction(BaseModel):
class ToggleCapabilityInstanceAction(APIModel):
"""New capability state for a state change request of toggle capability."""

type: Literal[CapabilityType.TOGGLE] = CapabilityType.TOGGLE
state: ToggleCapabilityInstanceActionState


class VideoStreamCapabilityInstanceAction(BaseModel):
class VideoStreamCapabilityInstanceAction(APIModel):
"""New capability state for a state change request of video_stream capability."""

type: Literal[CapabilityType.VIDEO_STREAM] = CapabilityType.VIDEO_STREAM
Expand Down
16 changes: 9 additions & 7 deletions custom_components/yandex_smart_home/schema/capability_color.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
from enum import StrEnum
from typing import Annotated, Any, Literal, Self, Union

from pydantic import BaseModel, Field, root_validator
from pydantic import Field, root_validator

from .base import APIModel


class ColorSettingCapabilityInstance(StrEnum):
Expand Down Expand Up @@ -49,14 +51,14 @@ class CapabilityParameterColorModel(StrEnum):
HSV = "hsv"


class CapabilityParameterTemperatureK(BaseModel):
class CapabilityParameterTemperatureK(APIModel):
"""Color temperature range."""

min: int
max: int


class CapabilityParameterColorScene(BaseModel):
class CapabilityParameterColorScene(APIModel):
"""Parameter of a scene instance."""

scenes: list[dict[Literal["id"], ColorScene]]
Expand All @@ -66,7 +68,7 @@ def from_list(cls, scenes: list[ColorScene]) -> Self:
return cls(scenes=[{"id": s} for s in scenes])


class ColorSettingCapabilityParameters(BaseModel):
class ColorSettingCapabilityParameters(APIModel):
"""Parameters of a color_setting capability."""

color_model: CapabilityParameterColorModel | None
Expand All @@ -81,21 +83,21 @@ def any_of(cls, values: dict[str, Any]) -> dict[str, Any]:
return values


class RGBInstanceActionState(BaseModel):
class RGBInstanceActionState(APIModel):
"""New value for a rgb instance."""

instance: Literal[ColorSettingCapabilityInstance.RGB] = ColorSettingCapabilityInstance.RGB
value: int


class TemperatureKInstanceActionState(BaseModel):
class TemperatureKInstanceActionState(APIModel):
"""New value for a temperature_k instance."""

instance: Literal[ColorSettingCapabilityInstance.TEMPERATURE_K] = ColorSettingCapabilityInstance.TEMPERATURE_K
value: int


class SceneInstanceActionState(BaseModel):
class SceneInstanceActionState(APIModel):
"""New value for a scene instance."""

instance: Literal[ColorSettingCapabilityInstance.SCENE] = ColorSettingCapabilityInstance.SCENE
Expand Down
6 changes: 3 additions & 3 deletions custom_components/yandex_smart_home/schema/capability_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from enum import StrEnum
from typing import Literal, Self

from pydantic import BaseModel
from .base import APIModel


class ModeCapabilityInstance(StrEnum):
Expand Down Expand Up @@ -108,7 +108,7 @@ class ModeCapabilityMode(StrEnum):
YOGURT = "yogurt"


class ModeCapabilityParameters(BaseModel):
class ModeCapabilityParameters(APIModel):
"""Parameters of a mode capability."""

instance: ModeCapabilityInstance
Expand All @@ -119,7 +119,7 @@ def from_list(cls, instance: ModeCapabilityInstance, modes: list[ModeCapabilityM
return cls(instance=instance, modes=[{"value": m} for m in modes])


class ModeCapabilityInstanceActionState(BaseModel):
class ModeCapabilityInstanceActionState(APIModel):
"""New value for a mode capability."""

instance: ModeCapabilityInstance
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"""
from enum import StrEnum

from pydantic import BaseModel
from .base import APIModel


class OnOffCapabilityInstance(StrEnum):
Expand All @@ -13,13 +13,13 @@ class OnOffCapabilityInstance(StrEnum):
ON = "on"


class OnOffCapabilityParameters(BaseModel):
class OnOffCapabilityParameters(APIModel):
"""Parameters of a on_off capability."""

split: bool


class OnOffCapabilityInstanceActionState(BaseModel):
class OnOffCapabilityInstanceActionState(APIModel):
"""New value for an on_off capability."""

instance: OnOffCapabilityInstance
Expand Down
10 changes: 6 additions & 4 deletions custom_components/yandex_smart_home/schema/capability_range.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
from enum import StrEnum
from typing import Any

from pydantic import BaseModel, root_validator
from pydantic import root_validator

from .base import APIModel


class RangeCapabilityUnit(StrEnum):
Expand All @@ -29,7 +31,7 @@ class RangeCapabilityInstance(StrEnum):
VOLUME = "volume"


class RangeCapabilityRange(BaseModel):
class RangeCapabilityRange(APIModel):
"""Value range of a range capability."""

min: float
Expand All @@ -40,7 +42,7 @@ def __str__(self) -> str:
return f"[{self.min}, {self.max}]"


class RangeCapabilityParameters(BaseModel):
class RangeCapabilityParameters(APIModel):
"""Parameters of a range capability."""

instance: RangeCapabilityInstance
Expand All @@ -64,7 +66,7 @@ def compute_unit(cls, values: dict[str, Any]) -> dict[str, Any]:
return values


class RangeCapabilityInstanceActionState(BaseModel):
class RangeCapabilityInstanceActionState(APIModel):
"""New value for a range capability."""

instance: RangeCapabilityInstance
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"""
from enum import StrEnum

from pydantic import BaseModel
from .base import APIModel


class ToggleCapabilityInstance(StrEnum):
Expand All @@ -22,13 +22,13 @@ class ToggleCapabilityInstance(StrEnum):
PAUSE = "pause"


class ToggleCapabilityParameters(BaseModel):
class ToggleCapabilityParameters(APIModel):
"""Parameters of a toggle capability."""

instance: ToggleCapabilityInstance


class ToggleCapabilityInstanceActionState(BaseModel):
class ToggleCapabilityInstanceActionState(APIModel):
"""New value for a toggle capability."""

instance: ToggleCapabilityInstance
Expand Down
10 changes: 5 additions & 5 deletions custom_components/yandex_smart_home/schema/capability_video.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from enum import StrEnum
from typing import Literal

from pydantic import BaseModel
from .base import APIModel

StreamProtocols = list[Literal["hls"]]

Expand All @@ -16,26 +16,26 @@ class VideoStreamCapabilityInstance(StrEnum):
GET_STREAM = "get_stream"


class VideoStreamCapabilityParameters(BaseModel):
class VideoStreamCapabilityParameters(APIModel):
"""Parameters of a video_stream capability."""

protocols: StreamProtocols


class GetStreamInstanceActionStateValue(BaseModel):
class GetStreamInstanceActionStateValue(APIModel):
"""New state value for a get_stream instance."""

protocols: StreamProtocols


class GetStreamInstanceActionState(BaseModel):
class GetStreamInstanceActionState(APIModel):
"""New value for a get_stream instance."""

instance: Literal[VideoStreamCapabilityInstance.GET_STREAM]
value: GetStreamInstanceActionStateValue


class GetStreamInstanceActionResultValue(BaseModel):
class GetStreamInstanceActionResultValue(APIModel):
"""New value after a get_stream instance state changed."""

stream_url: str
Expand Down
Loading

0 comments on commit 724eec8

Please sign in to comment.