Add slots to all models when using py3.10 or later (#459)

This commit is contained in:
J. Nick Koston 2023-07-18 17:23:07 -05:00 committed by GitHub
parent 46622cfcef
commit 541ce059c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 61 additions and 60 deletions

View File

@ -427,7 +427,7 @@ class APIClient:
# Return CameraState with the merged data
image_data = bytes().join(data_parts)
del image_stream[msg_key]
on_state(CameraState(key=msg.key, data=image_data))
on_state(CameraState(key=msg.key, data=image_data)) # type: ignore[call-arg]
assert self._connection is not None
self._connection.send_message_callback_response(
@ -847,7 +847,7 @@ class APIClient:
services.extend(BluetoothGATTServices.from_pb(msg).services)
return ESPHomeBluetoothGATTServices(address=address, services=services)
return ESPHomeBluetoothGATTServices(address=address, services=services) # type: ignore[call-arg]
async def bluetooth_gatt_read(
self,

View File

@ -1,7 +1,7 @@
import enum
import sys
from dataclasses import asdict, dataclass, field, fields
from functools import cache, lru_cache
from functools import cache, lru_cache, partial
from typing import (
TYPE_CHECKING,
Any,
@ -20,11 +20,12 @@ from uuid import UUID
from .util import fix_float_single_double_conversion
if sys.version_info[:2] < (3, 10):
_dataclass_decorator = dataclass()
_dataclass_decorator = dataclass
_frozen_dataclass_decorator = partial(dataclass, frozen=True)
else:
_dataclass_decorator = dataclass( # pylint: disable=unexpected-keyword-arg
slots=True
)
_dataclass_decorator = partial(dataclass, slots=True)
_frozen_dataclass_decorator = partial(dataclass, frozen=True, slots=True)
if TYPE_CHECKING:
from .api_pb2 import ( # type: ignore
@ -69,7 +70,7 @@ class APIIntEnum(enum.IntEnum):
cached_fields = cache(fields)
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class APIModelBase:
def __post_init__(self) -> None:
for field_ in cached_fields(type(self)): # type: ignore[arg-type]
@ -78,10 +79,10 @@ class APIModelBase:
continue
val = getattr(self, field_.name)
# use this setattr to prevent FrozenInstanceError
super().__setattr__(field_.name, convert(val))
object.__setattr__(self, field_.name, convert(val))
def to_dict(self) -> Dict[str, Any]:
return asdict(self)
return asdict(self) # type: ignore[no-any-return, call-overload]
@classmethod
def from_dict(
@ -124,7 +125,7 @@ class BluetoothProxySubscriptionFlag(enum.IntFlag):
RAW_ADVERTISEMENTS = 1 << 0
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class DeviceInfo(APIModelBase):
uses_password: bool = False
name: str = ""
@ -165,7 +166,7 @@ class EntityCategory(APIIntEnum):
DIAGNOSTIC = 2
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class EntityInfo(APIModelBase):
object_id: str = ""
key: int = 0
@ -178,26 +179,26 @@ class EntityInfo(APIModelBase):
)
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class EntityState(APIModelBase):
key: int = 0
# ==================== BINARY SENSOR ====================
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class BinarySensorInfo(EntityInfo):
device_class: str = ""
is_status_binary_sensor: bool = False
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class BinarySensorState(EntityState):
state: bool = False
missing_state: bool = False
# ==================== COVER ====================
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class CoverInfo(EntityInfo):
assumed_state: bool = False
supports_stop: bool = False
@ -223,7 +224,7 @@ class CoverOperation(APIIntEnum):
IS_CLOSING = 2
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class CoverState(EntityState):
legacy_state: Optional[LegacyCoverState] = converter_field(
default=LegacyCoverState.OPEN, converter=LegacyCoverState.convert
@ -245,7 +246,7 @@ class CoverState(EntityState):
# ==================== FAN ====================
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class FanInfo(EntityInfo):
supports_oscillation: bool = False
supports_speed: bool = False
@ -264,7 +265,7 @@ class FanDirection(APIIntEnum):
REVERSE = 1
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class FanState(EntityState):
state: bool = False
oscillating: bool = False
@ -287,7 +288,7 @@ class LightColorCapability(enum.IntFlag):
RGB = 1 << 5
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class LightInfo(EntityInfo):
supported_color_modes: List[int] = converter_field(
default_factory=list, converter=list
@ -357,7 +358,7 @@ class LightInfo(EntityInfo):
return self.supported_color_modes
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class LightState(EntityState):
state: bool = False
brightness: float = converter_field(
@ -405,7 +406,7 @@ class LastResetType(APIIntEnum):
AUTO = 2
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class SensorInfo(EntityInfo):
device_class: str = ""
unit_of_measurement: str = ""
@ -419,43 +420,43 @@ class SensorInfo(EntityInfo):
)
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class SensorState(EntityState):
state: float = 0.0
missing_state: bool = False
# ==================== SWITCH ====================
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class SwitchInfo(EntityInfo):
assumed_state: bool = False
device_class: str = ""
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class SwitchState(EntityState):
state: bool = False
# ==================== TEXT SENSOR ====================
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class TextSensorInfo(EntityInfo):
pass
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class TextSensorState(EntityState):
state: str = ""
missing_state: bool = False
# ==================== CAMERA ====================
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class CameraInfo(EntityInfo):
pass
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class CameraState(EntityState):
data: bytes = field(default_factory=bytes)
@ -511,7 +512,7 @@ class ClimatePreset(APIIntEnum):
ACTIVITY = 7
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class ClimateInfo(EntityInfo):
supports_current_temperature: bool = False
supports_two_point_target_temperature: bool = False
@ -558,7 +559,7 @@ class ClimateInfo(EntityInfo):
return self.supported_presets
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class ClimateState(EntityState):
mode: Optional[ClimateMode] = converter_field(
default=ClimateMode.OFF, converter=ClimateMode.convert
@ -604,7 +605,7 @@ class NumberMode(APIIntEnum):
SLIDER = 2
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class NumberInfo(EntityInfo):
min_value: float = converter_field(
default=0.0, converter=fix_float_single_double_conversion
@ -622,7 +623,7 @@ class NumberInfo(EntityInfo):
device_class: str = ""
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class NumberState(EntityState):
state: float = converter_field(
default=0.0, converter=fix_float_single_double_conversion
@ -631,32 +632,32 @@ class NumberState(EntityState):
# ==================== SELECT ====================
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class SelectInfo(EntityInfo):
options: List[str] = converter_field(default_factory=list, converter=list)
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class SelectState(EntityState):
state: str = ""
missing_state: bool = False
# ==================== SIREN ====================
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class SirenInfo(EntityInfo):
tones: List[str] = converter_field(default_factory=list, converter=list)
supports_volume: bool = False
supports_duration: bool = False
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class SirenState(EntityState):
state: bool = False
# ==================== BUTTON ====================
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class ButtonInfo(EntityInfo):
device_class: str = ""
@ -677,7 +678,7 @@ class LockCommand(APIIntEnum):
OPEN = 2
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class LockInfo(EntityInfo):
supports_open: bool = False
assumed_state: bool = False
@ -686,7 +687,7 @@ class LockInfo(EntityInfo):
code_format: str = ""
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class LockEntityState(EntityState):
state: Optional[LockState] = converter_field(
default=LockState.NONE, converter=LockState.convert
@ -709,12 +710,12 @@ class MediaPlayerCommand(APIIntEnum):
UNMUTE = 4
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class MediaPlayerInfo(EntityInfo):
supports_pause: bool = False
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class MediaPlayerEntityState(EntityState):
state: Optional[MediaPlayerState] = converter_field(
default=MediaPlayerState.NONE, converter=MediaPlayerState.convert
@ -749,14 +750,14 @@ class AlarmControlPanelCommand(APIIntEnum):
TRIGGER = 6
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class AlarmControlPanelInfo(EntityInfo):
supported_features: int = 0
requires_code: bool = False
requires_code_to_arm: bool = False
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class AlarmControlPanelEntityState(EntityState):
state: Optional[AlarmControlPanelState] = converter_field(
default=AlarmControlPanelState.DISARMED,
@ -796,7 +797,7 @@ def _convert_homeassistant_service_map(
return {v.key: v.value for v in value} # type: ignore
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class HomeassistantServiceCall(APIModelBase):
service: str = ""
is_event: bool = False
@ -822,7 +823,7 @@ class UserServiceArgType(APIIntEnum):
STRING_ARRAY = 7
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class UserServiceArg(APIModelBase):
name: str = ""
type: Optional[UserServiceArgType] = converter_field(
@ -842,7 +843,7 @@ class UserServiceArg(APIModelBase):
return ret
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class UserService(APIModelBase):
name: str = ""
key: int = 0
@ -955,7 +956,7 @@ def make_ble_raw_advertisement_processor(
return _on_ble_raw_advertisement_response
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class BluetoothDeviceConnection(APIModelBase):
address: int = 0
connected: bool = False
@ -963,28 +964,28 @@ class BluetoothDeviceConnection(APIModelBase):
error: int = 0
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class BluetoothDevicePairing(APIModelBase):
address: int = 0
paired: bool = False
error: int = 0
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class BluetoothDeviceUnpairing(APIModelBase):
address: int = 0
success: bool = False
error: int = 0
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class BluetoothDeviceClearCache(APIModelBase):
address: int = 0
success: bool = False
error: int = 0
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class BluetoothGATTRead(APIModelBase):
address: int = 0
handle: int = 0
@ -992,7 +993,7 @@ class BluetoothGATTRead(APIModelBase):
data: bytes = field(default_factory=bytes)
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class BluetoothGATTDescriptor(APIModelBase):
uuid: str = converter_field(default="", converter=_join_split_uuid)
handle: int = 0
@ -1008,7 +1009,7 @@ class BluetoothGATTDescriptor(APIModelBase):
return ret
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class BluetoothGATTCharacteristic(APIModelBase):
uuid: str = converter_field(default="", converter=_join_split_uuid)
handle: int = 0
@ -1029,7 +1030,7 @@ class BluetoothGATTCharacteristic(APIModelBase):
return ret
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class BluetoothGATTService(APIModelBase):
uuid: str = converter_field(default="", converter=_join_split_uuid)
handle: int = 0
@ -1048,7 +1049,7 @@ class BluetoothGATTService(APIModelBase):
return ret
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class BluetoothGATTServices(APIModelBase):
address: int = 0
services: List[BluetoothGATTService] = converter_field(
@ -1056,19 +1057,19 @@ class BluetoothGATTServices(APIModelBase):
)
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class ESPHomeBluetoothGATTServices:
address: int = 0
services: List[BluetoothGATTService] = field(default_factory=list)
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class BluetoothConnectionsFree(APIModelBase):
free: int = 0
limit: int = 0
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class BluetoothGATTError(APIModelBase):
address: int = 0
handle: int = 0
@ -1085,7 +1086,7 @@ class BluetoothDeviceRequestType(APIIntEnum):
CLEAR_CACHE = 6
@dataclass(frozen=True)
@_frozen_dataclass_decorator
class VoiceAssistantCommand(APIModelBase):
start: bool = False
conversation_id: str = ""