Skip to content

Commit 3ecd25a

Browse files
committed
avoid imports outside top level and put models in correct module
1 parent 97557d1 commit 3ecd25a

File tree

12 files changed

+172
-168
lines changed

12 files changed

+172
-168
lines changed

tests/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
WebSocketClientGateway,
3030
WebSocketServerGateway,
3131
)
32-
from zha.application.helpers import (
32+
from zha.application.model import (
3333
AlarmControlPanelOptions,
3434
CoordinatorConfiguration,
3535
LightOptions,

tests/test_discover.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
from zha.application import Platform, discovery
5353
from zha.application.discovery import ENDPOINT_PROBE, EndpointProbe
5454
from zha.application.gateway import Gateway
55-
from zha.application.helpers import DeviceOverridesConfiguration
55+
from zha.application.model import DeviceOverridesConfiguration
5656
from zha.application.platforms import binary_sensor, sensor
5757
from zha.application.registries import SINGLE_INPUT_CLUSTER_DEVICE_CLASS
5858
from zha.zigbee.cluster_handlers import ClusterHandler

tests/test_gateway.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
RawDeviceInitializedDeviceInfo,
3434
RawDeviceInitializedEvent,
3535
)
36-
from zha.application.helpers import ZHAData
36+
from zha.application.model import ZHAData
3737
from zha.application.platforms import GroupEntity
3838
from zha.application.platforms.light.const import EFFECT_OFF, LightEntityFeature
3939
from zha.zigbee.device import Device

tests/websocket/test_websocket_server_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from tests.conftest import CombinedWebsocketGateways
1010
from zha.application.gateway import WebSocketClientGateway, WebSocketServerGateway
11-
from zha.application.helpers import ZHAData
11+
from zha.application.model import ZHAData
1212
from zha.websocket import ZHAWebSocketException
1313
from zha.websocket.client.client import Client
1414
from zha.websocket.client.helpers import ClientHelper

zha/application/discovery.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
from zigpy.zcl.clusters.general import Ota
2323

2424
from zha.application import Platform, const as zha_const
25-
from zha.application.helpers import DeviceOverridesConfiguration
2625
from zha.application.platforms import ( # noqa: F401 pylint: disable=unused-import
2726
alarm_control_panel,
2827
binary_sensor,
@@ -108,6 +107,7 @@
108107

109108
if TYPE_CHECKING:
110109
from zha.application.gateway import Gateway
110+
from zha.application.model import DeviceOverridesConfiguration
111111
from zha.zigbee.device import Device
112112
from zha.zigbee.endpoint import Endpoint
113113

zha/application/gateway.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
ZHA_GW_MSG_RAW_INIT,
5252
RadioType,
5353
)
54-
from zha.application.helpers import DeviceAvailabilityChecker, GlobalUpdater, ZHAData
54+
from zha.application.helpers import DeviceAvailabilityChecker, GlobalUpdater
5555
from zha.application.model import (
5656
ConnectionLostEvent,
5757
DeviceFullyInitializedEvent,
@@ -69,6 +69,7 @@
6969
GroupRemovedEvent,
7070
RawDeviceInitializedDeviceInfo,
7171
RawDeviceInitializedEvent,
72+
ZHAData,
7273
)
7374
from zha.application.platforms.websocket_api import load_platform_entity_apis
7475
from zha.application.websocket_api import load_api as load_zigbee_controller_api
@@ -78,6 +79,7 @@
7879
gather_with_limited_concurrency,
7980
)
8081
from zha.event import EventBase
82+
from zha.model import BaseEvent
8183
from zha.websocket import ZHAWebSocketException
8284
from zha.websocket.client.client import Client
8385
from zha.websocket.client.helpers import (
@@ -173,6 +175,10 @@ async def async_remove_zigpy_group(self, group_id: int) -> None:
173175
async def shutdown(self) -> None:
174176
"""Stop ZHA Controller Application."""
175177

178+
@abstractmethod
179+
def broadcast_event(self, event: BaseEvent) -> None:
180+
"""Broadcast an event to all listeners."""
181+
176182

177183
class Gateway(AsyncUtilMixin, BaseGateway):
178184
"""Gateway that handles events that happen on the ZHA Zigbee network."""
@@ -800,6 +806,9 @@ def handle_message( # pylint: disable=unused-argument
800806
self.devices[sender.ieee].on_network = True
801807
self.async_update_device(sender, available=True)
802808

809+
def broadcast_event(self, event: BaseEvent) -> None:
810+
"""Broadcast an event to all listeners."""
811+
803812

804813
class WebSocketServerGateway(Gateway):
805814
"""ZHA websocket server implementation."""
@@ -897,6 +906,10 @@ async def __aexit__(
897906
await self.stop_server()
898907
await self.wait_closed()
899908

909+
def broadcast_event(self, event: BaseEvent) -> None:
910+
"""Broadcast an event to all listeners."""
911+
self.emit(event.event, event)
912+
900913
def _register_api_commands(self) -> None:
901914
"""Load server API commands."""
902915

@@ -1199,3 +1212,6 @@ def handle_group_removed(self, event: GroupRemovedEvent) -> None:
11991212

12001213
def connection_lost(self, exc: Exception) -> None:
12011214
"""Handle connection lost event."""
1215+
1216+
def broadcast_event(self, event: BaseEvent) -> None:
1217+
"""Broadcast an event to all listeners."""

zha/application/helpers.py

Lines changed: 2 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,13 @@
44

55
import asyncio
66
import binascii
7-
import collections
87
from collections.abc import Callable
9-
import dataclasses
108
from dataclasses import dataclass
11-
import datetime
129
import enum
1310
import logging
1411
import re
1512
from typing import TYPE_CHECKING, Any, ParamSpec, TypeVar
1613

17-
from aiohttp import ClientSession
18-
from pydantic import Field
1914
import voluptuous as vol
2015
import zigpy.exceptions
2116
import zigpy.types
@@ -24,16 +19,10 @@
2419
from zigpy.zcl.foundation import CommandSchema
2520
import zigpy.zdo.types as zdo_types
2621

27-
from zha.application import Platform
28-
from zha.application.const import (
29-
CLUSTER_TYPE_IN,
30-
CLUSTER_TYPE_OUT,
31-
CONF_DEFAULT_CONSIDER_UNAVAILABLE_BATTERY,
32-
CONF_DEFAULT_CONSIDER_UNAVAILABLE_MAINS,
33-
)
22+
from zha.application.const import CLUSTER_TYPE_IN, CLUSTER_TYPE_OUT
3423
from zha.async_ import gather_with_limited_concurrency
3524
from zha.decorators import periodic
36-
from zha.model import BaseModel
25+
from zha.zigbee.cluster_handlers.registries import BINDABLE_CLUSTERS
3726

3827
if TYPE_CHECKING:
3928
from zha.application.gateway import Gateway
@@ -92,9 +81,6 @@ async def get_matched_clusters(
9281
source_zha_device: Device, target_zha_device: Device
9382
) -> list[BindingPair]:
9483
"""Get matched input/output cluster pairs for 2 devices."""
95-
from zha.zigbee.cluster_handlers.registries import ( # pylint: disable=import-outside-toplevel
96-
BINDABLE_CLUSTERS,
97-
)
9884

9985
source_clusters = source_zha_device.async_get_std_clusters()
10086
target_clusters = target_zha_device.async_get_std_clusters()
@@ -168,9 +154,6 @@ def convert_to_zcl_values(
168154

169155
def async_is_bindable_target(source_zha_device: Device, target_zha_device: Device):
170156
"""Determine if target is bindable to source."""
171-
from zha.zigbee.cluster_handlers.registries import ( # pylint: disable=import-outside-toplevel
172-
BINDABLE_CLUSTERS,
173-
)
174157

175158
if target_zha_device.nwk == 0x0000:
176159
return True
@@ -264,113 +247,6 @@ def qr_to_install_code(qr_code: str) -> tuple[zigpy.types.EUI64, zigpy.types.Key
264247
raise vol.Invalid(f"couldn't convert qr code: {qr_code}")
265248

266249

267-
class LightOptions(BaseModel):
268-
"""ZHA light options."""
269-
270-
default_light_transition: float = Field(default=0)
271-
enable_enhanced_light_transition: bool = Field(default=False)
272-
enable_light_transitioning_flag: bool = Field(default=True)
273-
always_prefer_xy_color_mode: bool = Field(default=True)
274-
group_members_assume_state: bool = Field(default=True)
275-
276-
277-
class DeviceOptions(BaseModel):
278-
"""ZHA device options."""
279-
280-
enable_identify_on_join: bool = Field(default=True)
281-
consider_unavailable_mains: int = Field(
282-
default=CONF_DEFAULT_CONSIDER_UNAVAILABLE_MAINS
283-
)
284-
consider_unavailable_battery: int = Field(
285-
default=CONF_DEFAULT_CONSIDER_UNAVAILABLE_BATTERY
286-
)
287-
enable_mains_startup_polling: bool = Field(default=True)
288-
289-
290-
class AlarmControlPanelOptions(BaseModel):
291-
"""ZHA alarm control panel options."""
292-
293-
master_code: str = Field(default="1234")
294-
failed_tries: int = Field(default=3)
295-
arm_requires_code: bool = Field(default=False)
296-
297-
298-
class CoordinatorConfiguration(BaseModel):
299-
"""ZHA coordinator configuration."""
300-
301-
path: str
302-
baudrate: int = Field(default=115200)
303-
flow_control: str = Field(default="hardware")
304-
radio_type: str = Field(default="ezsp")
305-
306-
307-
class QuirksConfiguration(BaseModel):
308-
"""ZHA quirks configuration."""
309-
310-
enabled: bool = Field(default=True)
311-
custom_quirks_path: str | None = Field(default=None)
312-
313-
314-
class DeviceOverridesConfiguration(BaseModel):
315-
"""ZHA device overrides configuration."""
316-
317-
type: Platform
318-
319-
320-
class WebsocketServerConfiguration(BaseModel):
321-
"""Websocket Server configuration for zha."""
322-
323-
host: str = "0.0.0.0"
324-
port: int = 8001
325-
network_auto_start: bool = False
326-
327-
328-
class WebsocketClientConfiguration(BaseModel):
329-
"""Websocket client configuration for zha."""
330-
331-
host: str = "0.0.0.0"
332-
port: int = 8001
333-
aiohttp_session: ClientSession | None = None
334-
335-
336-
class ZHAConfiguration(BaseModel):
337-
"""ZHA configuration."""
338-
339-
coordinator_configuration: CoordinatorConfiguration = Field(
340-
default_factory=CoordinatorConfiguration
341-
)
342-
quirks_configuration: QuirksConfiguration = Field(
343-
default_factory=QuirksConfiguration
344-
)
345-
device_overrides: dict[str, DeviceOverridesConfiguration] = Field(
346-
default_factory=dict
347-
)
348-
light_options: LightOptions = Field(default_factory=LightOptions)
349-
device_options: DeviceOptions = Field(default_factory=DeviceOptions)
350-
alarm_control_panel_options: AlarmControlPanelOptions = Field(
351-
default_factory=AlarmControlPanelOptions
352-
)
353-
354-
355-
@dataclasses.dataclass(kw_only=True, slots=True)
356-
class ZHAData:
357-
"""ZHA data stored in `gateway.data`."""
358-
359-
config: ZHAConfiguration
360-
ws_server_config: WebsocketServerConfiguration | None = None
361-
ws_client_config: WebsocketClientConfiguration | None = None
362-
zigpy_config: dict[str, Any] = dataclasses.field(default_factory=dict)
363-
platforms: collections.defaultdict[Platform, list] = dataclasses.field(
364-
default_factory=lambda: collections.defaultdict(list)
365-
)
366-
gateway: Gateway | None = dataclasses.field(default=None)
367-
device_trigger_cache: dict[str, tuple[str, dict]] = dataclasses.field(
368-
default_factory=dict
369-
)
370-
allow_polling: bool = dataclasses.field(default=False)
371-
local_timezone: datetime.tzinfo = dataclasses.field(default=datetime.UTC)
372-
373-
374250
class GlobalUpdater:
375251
"""Global updater for ZHA.
376252

0 commit comments

Comments
 (0)