PyPlumIO 0.5.22__py3-none-any.whl → 0.5.24__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyPlumIO
3
- Version: 0.5.22
3
+ Version: 0.5.24
4
4
  Summary: PyPlumIO is a native ecoNET library for Plum ecoMAX controllers.
5
5
  Author-email: Denis Paavilainen <denpa@denpa.pro>
6
6
  License: MIT License
@@ -22,23 +22,25 @@ Classifier: Topic :: Home Automation
22
22
  Requires-Python: >=3.9
23
23
  Description-Content-Type: text/markdown
24
24
  License-File: LICENSE
25
+ Requires-Dist: dataslots ==1.2.0
25
26
  Requires-Dist: pyserial-asyncio ==0.6
27
+ Requires-Dist: typing-extensions ==4.12.2
26
28
  Provides-Extra: dev
27
29
  Requires-Dist: pyplumio[docs,test] ; extra == 'dev'
28
- Requires-Dist: pre-commit ==3.7.1 ; extra == 'dev'
30
+ Requires-Dist: pre-commit ==3.8.0 ; extra == 'dev'
29
31
  Requires-Dist: tomli ==2.0.1 ; extra == 'dev'
30
32
  Provides-Extra: docs
31
- Requires-Dist: sphinx ==7.4.0 ; extra == 'docs'
33
+ Requires-Dist: sphinx ==7.4.7 ; extra == 'docs'
32
34
  Requires-Dist: sphinx-rtd-theme ==2.0.0 ; extra == 'docs'
33
35
  Requires-Dist: readthedocs-sphinx-search ==0.3.2 ; extra == 'docs'
34
36
  Provides-Extra: test
35
37
  Requires-Dist: codespell ==2.3.0 ; extra == 'test'
36
38
  Requires-Dist: coverage ==7.6.0 ; extra == 'test'
37
- Requires-Dist: mypy ==1.10.1 ; extra == 'test'
38
- Requires-Dist: pyserial-asyncio-fast ==0.13 ; extra == 'test'
39
- Requires-Dist: pytest ==8.2.2 ; extra == 'test'
40
- Requires-Dist: pytest-asyncio ==0.23.7 ; extra == 'test'
41
- Requires-Dist: ruff ==0.5.2 ; extra == 'test'
39
+ Requires-Dist: mypy ==1.11.1 ; extra == 'test'
40
+ Requires-Dist: pyserial-asyncio-fast ==0.14 ; extra == 'test'
41
+ Requires-Dist: pytest ==8.3.2 ; extra == 'test'
42
+ Requires-Dist: pytest-asyncio ==0.23.8 ; extra == 'test'
43
+ Requires-Dist: ruff ==0.5.5 ; extra == 'test'
42
44
  Requires-Dist: tox ==4.16.0 ; extra == 'test'
43
45
  Requires-Dist: types-pyserial ==3.5.0.20240527 ; extra == 'test'
44
46
 
@@ -1,28 +1,28 @@
1
1
  pyplumio/__init__.py,sha256=ditJTIOFGJDg60atHzOpiggdUrZHpSynno7MtpZUGVk,3299
2
2
  pyplumio/__main__.py,sha256=3IwHHSq-iay5FaeMc95klobe-xv82yydSKcBE7BFZ6M,500
3
- pyplumio/_version.py,sha256=7uyNQzq4TwYgrtNcQJPZodOcwZA-26alCK4Ab94ma2M,413
4
- pyplumio/connection.py,sha256=QefTnJyMfFQV4f9TLRdkgP2aE9AmMjjfpFADQXgQqDE,6002
3
+ pyplumio/_version.py,sha256=CKGR3DDYRjbp1jSyT2Qw0jSOOwUMwfxFMWArTx28rgk,413
4
+ pyplumio/connection.py,sha256=6mUbcjGxxEhMVIbzZgCqH-Ez-fcYoRj7ZbVSzpikpNA,5949
5
5
  pyplumio/const.py,sha256=8rpiVbVb5R_6Rm6J2sgCnaVrkD-2Fzhd1RYMz0MBgwo,3915
6
6
  pyplumio/exceptions.py,sha256=Wn-y5AJ5xfaBlHhTUVKB27_0Us8_OVHqh-sicnr9sYA,700
7
7
  pyplumio/filters.py,sha256=IZkvrRAHdv6s3CplK73mHomRHpo3rnoyX2u26FVr9XU,11386
8
- pyplumio/protocol.py,sha256=m2yPMXT2TcV-bv0jOQnwoanCpypYYh9fh7eZVOg7KTM,8108
8
+ pyplumio/protocol.py,sha256=e6-ns5i5DWlFD5tKot-kQtmZt3CJMFK6zFa5RMIKshw,8140
9
9
  pyplumio/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  pyplumio/stream.py,sha256=IVCQFKBtRafRgUkr93p_wN5mXZAD3Jw1d091dfEIK20,4479
11
11
  pyplumio/utils.py,sha256=TnBzRopinyp92wruguijxcIYmaeyNVTFX0dygI5FCMU,823
12
- pyplumio/devices/__init__.py,sha256=nbbi65b6bYzhXdUNQjSN4ViBVoKuxcuPIPflA_C_UME,6584
13
- pyplumio/devices/ecomax.py,sha256=Oe0_i_EvcPI12zfcKVNwL_dDeK6ipusQArzypp3LBCo,17066
12
+ pyplumio/devices/__init__.py,sha256=sb4wFJSM-j1rwJGQ0G7RSCF1t9-ZEwKzJl9mFrSr0EI,6564
13
+ pyplumio/devices/ecomax.py,sha256=jaIX0LySnryPrwFsYH4ES7U52P3ZaAxTdMKJAJ_XY5Q,16949
14
14
  pyplumio/devices/ecoster.py,sha256=J4YtPmFmFwaq4LzYf28aMmB97cRAbMsVyUdBLGki42g,313
15
- pyplumio/devices/mixer.py,sha256=j3ysCnRpbzAycBQYiRi5y1mgHRH0EidKpdIVClWs6rA,3313
16
- pyplumio/devices/thermostat.py,sha256=kDTtoMcMAeSDf07vWnAOLh6EQuarh7HIz2W-5Eyg2j8,2649
15
+ pyplumio/devices/mixer.py,sha256=pxZXoAOrZ52OxMirZdoCtbJ4b2yHg1A2Kn_QPZZqynQ,3271
16
+ pyplumio/devices/thermostat.py,sha256=9jI_cacIQoFq_ImAqAYhcnAx7PVO3FWZz4WdfatGNiw,2607
17
17
  pyplumio/frames/__init__.py,sha256=uMjLWY0rCbCTBfXafA_TSfLORYBT0wLyhHSZEePsRxw,7504
18
18
  pyplumio/frames/messages.py,sha256=7vyOjcxGDnaRlyB4jPsCt00yCc3Axme8NN7uK922DS8,3622
19
19
  pyplumio/frames/requests.py,sha256=Ra8xH5oKYhkEUtadN-9ZsJKkt5xZkz5O7edQVsDhNsM,7221
20
20
  pyplumio/frames/responses.py,sha256=j4awA2-MfsoPdENC4Fvae4_Oa70rDhH19ebmEoAqhh8,6532
21
21
  pyplumio/helpers/__init__.py,sha256=H2xxdkF-9uADLwEbfBUoxNTdwru3L5Z2cfJjgsuRsn0,31
22
22
  pyplumio/helpers/data_types.py,sha256=5yxHCnsoKLw5kBM3s6SxwsuKs1C0yK2khyeSrrPXQsQ,8255
23
- pyplumio/helpers/event_manager.py,sha256=PW1cczTVHx4VBGWtBbqT7Ay6G5vSQTb_WFCkJp4HZ8o,6195
23
+ pyplumio/helpers/event_manager.py,sha256=yH_VjEvIkuYwk31qb3rXtFDfKAStbA-YWWc4ED17jVI,6443
24
24
  pyplumio/helpers/factory.py,sha256=eiTkYUCernUn0VNDDdEN4IyjNPrXK8vnJESXyLaqFzE,1017
25
- pyplumio/helpers/parameter.py,sha256=Av__MjrM4k7-AwJ71t6W1zyhMq8XdTeI2vh1-p_p1-4,9437
25
+ pyplumio/helpers/parameter.py,sha256=GoQIp7_JMpFdjPL1iUGI49IQyD-kvFUMqnuIX-v5dao,11137
26
26
  pyplumio/helpers/schedule.py,sha256=-IZJ-CU4PhFlsE586wTw--ovDrTo2Hs4JneCHhc0e-Y,5013
27
27
  pyplumio/helpers/task_manager.py,sha256=HAd69yGTRL0zQsu-ywnbLu1UXiJzgHWuhYWA--vs4lQ,1181
28
28
  pyplumio/helpers/timeout.py,sha256=XM58yaz93cNsxW7Ok6hfBw8i_92HdsGFQVBhpqbCZ70,770
@@ -31,13 +31,13 @@ pyplumio/structures/__init__.py,sha256=EjK-5qJZ0F7lpP2b6epvTMg9cIBl4Kn91nqNkEcLw
31
31
  pyplumio/structures/alerts.py,sha256=wX58xWr1dJgZiQtEEMLRu8bcu6dTcc-aqEIY69gYGu0,3640
32
32
  pyplumio/structures/boiler_load.py,sha256=p3mOzZUU-g7A2tG_yp8podEqpI81hlsOZmHELyPNRY8,838
33
33
  pyplumio/structures/boiler_power.py,sha256=72qsvccg49FdRdXv2f2K5sGpjT7wAOLFjlIGWpO-DVg,901
34
- pyplumio/structures/ecomax_parameters.py,sha256=oHKjqeX1fCCJpGMs385-2qJ3ondCvpJRpj5rS06ibf8,28076
34
+ pyplumio/structures/ecomax_parameters.py,sha256=a7sq2yhUSt6XiZWv48KkClWyjxsGAEJbES13-sx6G78,27710
35
35
  pyplumio/structures/fan_power.py,sha256=Q5fv-7_2NVuLeQPIVIylvgN7M8-a9D8rRUE0QGjyS3w,871
36
36
  pyplumio/structures/frame_versions.py,sha256=OMWU8tjnsrRWQsMSbmCJCmiKDwBmA75BcPZ6CqvKMLc,1566
37
37
  pyplumio/structures/fuel_consumption.py,sha256=_p2dI4H67Eopn7IF0Gj77A8c_8lNKhhDDAtmugxLd4s,976
38
38
  pyplumio/structures/fuel_level.py,sha256=mJpp1dnRD1wXi_6EyNX7TNXosjcr905rSHOnuZ5VD74,1069
39
39
  pyplumio/structures/lambda_sensor.py,sha256=JNSCiBJoM8Uk3OGbmFIigaLOntQST5U_UrmCpaQBlM0,1595
40
- pyplumio/structures/mixer_parameters.py,sha256=l4EQSEjmpjIULUWR-ulXiYWmBLTSfRoMvK8afKTVH6M,8763
40
+ pyplumio/structures/mixer_parameters.py,sha256=BQXC6vHx_b0OL-T6IU3bi2trjarLmlcMU1mmM5Q3AbI,8871
41
41
  pyplumio/structures/mixer_sensors.py,sha256=O91929Ts1YXFmKdPRc1r_BYDgrqkv5QVtE1nGzLpuAI,2260
42
42
  pyplumio/structures/modules.py,sha256=ukju4TQmRRJfgl94QU4zytZLU5px8nw3sgfSLn9JysU,2520
43
43
  pyplumio/structures/network_info.py,sha256=rxGoTdjlUmgEzR4BjOh9XQgEqKI6OSIbhOJ8tsXocts,4063
@@ -48,13 +48,13 @@ pyplumio/structures/product_info.py,sha256=uiEN6DFQlzmBvQByTirFzXQShoex0YGdFS9WI
48
48
  pyplumio/structures/program_version.py,sha256=p3Hzn1igxGyZ99jJjPswNGCAAQdJ5_-sgZPIy-MGISI,2506
49
49
  pyplumio/structures/regulator_data.py,sha256=Dun3RjfHHoV2W5RTSQcAimBL0Or3O957vYQj7Pbi7CM,2309
50
50
  pyplumio/structures/regulator_data_schema.py,sha256=BMshEpiP-lwTgSkbTuow9KlxCwKwQXV0nFPcBpW0SJg,1505
51
- pyplumio/structures/schedules.py,sha256=-koo05nLkpKuj1ZPiC1NB_21MAFn1FzQ6VLC0DboYeg,6346
51
+ pyplumio/structures/schedules.py,sha256=tm5DVCUnJ3FTUMl8wPGgM5_DsL_9R_UQqx5bfPAuvUM,6717
52
52
  pyplumio/structures/statuses.py,sha256=wkoynyMRr1VREwfBC6vU48kPA8ZQ83pcXuciy2xHJrk,1166
53
53
  pyplumio/structures/temperatures.py,sha256=1CDzehNmbALz1Jyt_9gZNIk52q6Wv-xQXjijVDCVYec,2337
54
- pyplumio/structures/thermostat_parameters.py,sha256=1QkgOnDndBMWpGa8GEJLdewLkdF8UqF03yhoVzYqYJE,7796
54
+ pyplumio/structures/thermostat_parameters.py,sha256=ybsab49teETR8pMsSCmPidNe5IclTq8tj7uxtHXGEAY,8045
55
55
  pyplumio/structures/thermostat_sensors.py,sha256=ZmjWgYtTZ5M8Lnz_Q5N4JD8G3MvEmByPFjYsy6XZOmo,3177
56
- PyPlumIO-0.5.22.dist-info/LICENSE,sha256=m-UuZFjXJ22uPTGm9kSHS8bqjsf5T8k2wL9bJn1Y04o,1088
57
- PyPlumIO-0.5.22.dist-info/METADATA,sha256=3u07pneJ8FCqq5Mj1WfLJQAd_iBqYRvlwC_I1vby3hI,5415
58
- PyPlumIO-0.5.22.dist-info/WHEEL,sha256=rWxmBtp7hEUqVLOnTaDOPpR-cZpCDkzhhcBce-Zyd5k,91
59
- PyPlumIO-0.5.22.dist-info/top_level.txt,sha256=kNBz9UPPkPD9teDn3U_sEy5LjzwLm9KfADCXtBlbw8A,9
60
- PyPlumIO-0.5.22.dist-info/RECORD,,
56
+ PyPlumIO-0.5.24.dist-info/LICENSE,sha256=m-UuZFjXJ22uPTGm9kSHS8bqjsf5T8k2wL9bJn1Y04o,1088
57
+ PyPlumIO-0.5.24.dist-info/METADATA,sha256=gfvAKaTQ9zSS--habg2vmcwrMe7q29dIMU32PFjTWh8,5490
58
+ PyPlumIO-0.5.24.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
59
+ PyPlumIO-0.5.24.dist-info/top_level.txt,sha256=kNBz9UPPkPD9teDn3U_sEy5LjzwLm9KfADCXtBlbw8A,9
60
+ PyPlumIO-0.5.24.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (71.0.4)
2
+ Generator: setuptools (72.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
pyplumio/_version.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.5.22'
16
- __version_tuple__ = version_tuple = (0, 5, 22)
15
+ __version__ = version = '0.5.24'
16
+ __version_tuple__ = version_tuple = (0, 5, 24)
pyplumio/connection.py CHANGED
@@ -4,7 +4,6 @@ from __future__ import annotations
4
4
 
5
5
  from abc import ABC, abstractmethod
6
6
  import asyncio
7
- from collections.abc import MutableMapping
8
7
  import logging
9
8
  from typing import Any, Final, cast
10
9
 
@@ -36,7 +35,7 @@ class Connection(ABC, TaskManager):
36
35
 
37
36
  _protocol: Protocol
38
37
  _reconnect_on_failure: bool
39
- _kwargs: MutableMapping[str, Any]
38
+ _kwargs: dict[str, Any]
40
39
 
41
40
  def __init__(
42
41
  self,
@@ -63,7 +63,7 @@ class Device(ABC, EventManager):
63
63
  :param name: Name of the parameter
64
64
  :type name: str
65
65
  :param value: New value for the parameter
66
- :type value: int | float | bool | Literal["on"] | Literal["off"]
66
+ :type value: int | float | bool | Literal["off", "on"]
67
67
  :param timeout: Wait this amount of seconds for confirmation,
68
68
  defaults to `None`
69
69
  :type timeout: float, optional
@@ -95,7 +95,7 @@ class Device(ABC, EventManager):
95
95
  :param name: Name of the parameter
96
96
  :type name: str
97
97
  :param value: New value for the parameter
98
- :type value: int | float | bool | Literal["on"] | Literal["off"]
98
+ :type value: int | float | bool | Literal["off", "on"]
99
99
  :param timeout: Wait this amount of seconds for confirmation.
100
100
  As this method operates in the background without waiting,
101
101
  this value is used to determine failure when
@@ -31,9 +31,9 @@ from pyplumio.structures.ecomax_parameters import (
31
31
  ECOMAX_CONTROL_PARAMETER,
32
32
  ECOMAX_PARAMETERS,
33
33
  THERMOSTAT_PROFILE_PARAMETER,
34
- EcomaxBinaryParameter,
35
- EcomaxBinaryParameterDescription,
36
- EcomaxParameter,
34
+ EcomaxNumber,
35
+ EcomaxSwitch,
36
+ EcomaxSwitchDescription,
37
37
  )
38
38
  from pyplumio.structures.frame_versions import ATTR_FRAME_VERSIONS
39
39
  from pyplumio.structures.fuel_consumption import ATTR_FUEL_CONSUMPTION
@@ -47,9 +47,9 @@ from pyplumio.structures.schedules import (
47
47
  ATTR_SCHEDULES,
48
48
  SCHEDULE_PARAMETERS,
49
49
  SCHEDULES,
50
- ScheduleBinaryParameter,
51
- ScheduleBinaryParameterDescription,
52
- ScheduleParameter,
50
+ ScheduleNumber,
51
+ ScheduleSwitch,
52
+ ScheduleSwitchDescription,
53
53
  )
54
54
  from pyplumio.structures.thermostat_parameters import (
55
55
  ATTR_THERMOSTAT_PARAMETERS,
@@ -209,9 +209,9 @@ class EcoMAX(AddressableDevice):
209
209
  )
210
210
 
211
211
  handler = (
212
- EcomaxBinaryParameter
213
- if isinstance(description, EcomaxBinaryParameterDescription)
214
- else EcomaxParameter
212
+ EcomaxSwitch
213
+ if isinstance(description, EcomaxSwitchDescription)
214
+ else EcomaxNumber
215
215
  )
216
216
  yield self.dispatch(
217
217
  description.name,
@@ -325,9 +325,9 @@ class EcoMAX(AddressableDevice):
325
325
  for index, values in parameters:
326
326
  description = SCHEDULE_PARAMETERS[index]
327
327
  handler = (
328
- ScheduleBinaryParameter
329
- if isinstance(description, ScheduleBinaryParameterDescription)
330
- else ScheduleParameter
328
+ ScheduleSwitch
329
+ if isinstance(description, ScheduleSwitchDescription)
330
+ else ScheduleNumber
331
331
  )
332
332
  yield self.dispatch(
333
333
  description.name,
@@ -357,7 +357,7 @@ class EcoMAX(AddressableDevice):
357
357
  """Create ecoMAX control parameter instance and dispatch an event."""
358
358
  await self.dispatch(
359
359
  ECOMAX_CONTROL_PARAMETER.name,
360
- EcomaxBinaryParameter.create_or_update(
360
+ EcomaxSwitch.create_or_update(
361
361
  description=ECOMAX_CONTROL_PARAMETER,
362
362
  device=self,
363
363
  values=ParameterValues(
@@ -391,12 +391,12 @@ class EcoMAX(AddressableDevice):
391
391
 
392
392
  async def _add_thermostat_profile_parameter(
393
393
  self, values: ParameterValues | None
394
- ) -> EcomaxParameter | None:
394
+ ) -> EcomaxNumber | None:
395
395
  """Add thermostat profile parameter to the dataset."""
396
396
  if not values:
397
397
  return None
398
398
 
399
- return EcomaxParameter(
399
+ return EcomaxNumber(
400
400
  device=self, description=THERMOSTAT_PROFILE_PARAMETER, values=values
401
401
  )
402
402
 
@@ -425,7 +425,7 @@ class EcoMAX(AddressableDevice):
425
425
  async def turn_on(self) -> bool:
426
426
  """Turn on the ecoMAX controller."""
427
427
  try:
428
- ecomax_control: EcomaxBinaryParameter = self.data[ATTR_ECOMAX_CONTROL]
428
+ ecomax_control: EcomaxSwitch = self.data[ATTR_ECOMAX_CONTROL]
429
429
  return await ecomax_control.turn_on()
430
430
  except KeyError:
431
431
  _LOGGER.error("ecoMAX control isn't available, please try later")
@@ -434,7 +434,7 @@ class EcoMAX(AddressableDevice):
434
434
  async def turn_off(self) -> bool:
435
435
  """Turn off the ecoMAX controller."""
436
436
  try:
437
- ecomax_control: EcomaxBinaryParameter = self.data[ATTR_ECOMAX_CONTROL]
437
+ ecomax_control: EcomaxSwitch = self.data[ATTR_ECOMAX_CONTROL]
438
438
  return await ecomax_control.turn_off()
439
439
  except KeyError:
440
440
  _LOGGER.error("ecoMAX control isn't available, please try later")
pyplumio/devices/mixer.py CHANGED
@@ -12,9 +12,9 @@ from pyplumio.helpers.parameter import ParameterValues
12
12
  from pyplumio.structures.mixer_parameters import (
13
13
  ATTR_MIXER_PARAMETERS,
14
14
  MIXER_PARAMETERS,
15
- MixerBinaryParameter,
16
- MixerBinaryParameterDescription,
17
- MixerParameter,
15
+ MixerNumber,
16
+ MixerSwitch,
17
+ MixerSwitchDescription,
18
18
  )
19
19
  from pyplumio.structures.mixer_sensors import ATTR_MIXER_SENSORS
20
20
  from pyplumio.structures.product_info import ATTR_PRODUCT, ProductInfo
@@ -78,9 +78,9 @@ class Mixer(SubDevice):
78
78
  return
79
79
 
80
80
  handler = (
81
- MixerBinaryParameter
82
- if isinstance(description, MixerBinaryParameterDescription)
83
- else MixerParameter
81
+ MixerSwitch
82
+ if isinstance(description, MixerSwitchDescription)
83
+ else MixerNumber
84
84
  )
85
85
  yield self.dispatch(
86
86
  description.name,
@@ -11,9 +11,9 @@ from pyplumio.helpers.parameter import ParameterValues
11
11
  from pyplumio.structures.thermostat_parameters import (
12
12
  ATTR_THERMOSTAT_PARAMETERS,
13
13
  THERMOSTAT_PARAMETERS,
14
- ThermostatBinaryParameter,
15
- ThermostatBinaryParameterDescription,
16
- ThermostatParameter,
14
+ ThermostatNumber,
15
+ ThermostatSwitch,
16
+ ThermostatSwitchDescription,
17
17
  )
18
18
  from pyplumio.structures.thermostat_sensors import ATTR_THERMOSTAT_SENSORS
19
19
 
@@ -57,9 +57,9 @@ class Thermostat(SubDevice):
57
57
  for index, values in parameters:
58
58
  description = THERMOSTAT_PARAMETERS[index]
59
59
  handler = (
60
- ThermostatBinaryParameter
61
- if isinstance(description, ThermostatBinaryParameterDescription)
62
- else ThermostatParameter
60
+ ThermostatSwitch
61
+ if isinstance(description, ThermostatSwitchDescription)
62
+ else ThermostatNumber
63
63
  )
64
64
  yield self.dispatch(
65
65
  description.name,
@@ -4,20 +4,23 @@ from __future__ import annotations
4
4
 
5
5
  import asyncio
6
6
  from collections.abc import Callable, Coroutine
7
- from typing import Any, TypeVar
7
+ from typing import Any, Generic, TypeVar, overload
8
+
9
+ from typing_extensions import TypeAlias
8
10
 
9
11
  from pyplumio.helpers.task_manager import TaskManager
10
12
 
11
- Callback = Callable[[Any], Coroutine[Any, Any, Any]]
13
+ Callback: TypeAlias = Callable[[Any], Coroutine[Any, Any, Any]]
12
14
  CallbackT = TypeVar("CallbackT", bound=Callback)
15
+ T = TypeVar("T")
13
16
 
14
17
 
15
- class EventManager(TaskManager):
18
+ class EventManager(TaskManager, Generic[T]):
16
19
  """Represents an event manager."""
17
20
 
18
21
  __slots__ = ("data", "_events", "_callbacks")
19
22
 
20
- data: dict[str, Any]
23
+ data: dict[str, T]
21
24
  _events: dict[str, asyncio.Event]
22
25
  _callbacks: dict[str, list[Callback]]
23
26
 
@@ -28,7 +31,7 @@ class EventManager(TaskManager):
28
31
  self._events = {}
29
32
  self._callbacks = {}
30
33
 
31
- def __getattr__(self, name: str) -> Any:
34
+ def __getattr__(self, name: str) -> T:
32
35
  """Return attributes from the underlying data dictionary."""
33
36
  try:
34
37
  return self.data[name]
@@ -48,7 +51,7 @@ class EventManager(TaskManager):
48
51
  if name not in self.data:
49
52
  await asyncio.wait_for(self.create_event(name).wait(), timeout=timeout)
50
53
 
51
- async def get(self, name: str, timeout: float | None = None) -> Any:
54
+ async def get(self, name: str, timeout: float | None = None) -> T:
52
55
  """Get the value by name.
53
56
 
54
57
  :param name: Event name or ID
@@ -62,6 +65,12 @@ class EventManager(TaskManager):
62
65
  await self.wait_for(name, timeout=timeout)
63
66
  return self.data[name]
64
67
 
68
+ @overload
69
+ def get_nowait(self, name: str, default: None = ...) -> T | None: ...
70
+
71
+ @overload
72
+ def get_nowait(self, name: str, default: T) -> T: ...
73
+
65
74
  def get_nowait(self, name: str, default: Any = None) -> Any:
66
75
  """Get the value by name without waiting.
67
76
 
@@ -136,7 +145,7 @@ class EventManager(TaskManager):
136
145
 
137
146
  return False
138
147
 
139
- async def dispatch(self, name: str, value: Any) -> None:
148
+ async def dispatch(self, name: str, value: T) -> None:
140
149
  """Call registered callbacks and dispatch the event."""
141
150
  if callbacks := self._callbacks.get(name, None):
142
151
  for callback in list(callbacks):
@@ -146,17 +155,17 @@ class EventManager(TaskManager):
146
155
  self.data[name] = value
147
156
  self.set_event(name)
148
157
 
149
- def dispatch_nowait(self, name: str, value: Any) -> None:
158
+ def dispatch_nowait(self, name: str, value: T) -> None:
150
159
  """Call a registered callbacks and dispatch the event without waiting."""
151
160
  self.create_task(self.dispatch(name, value))
152
161
 
153
- async def load(self, data: dict[str, Any]) -> None:
162
+ async def load(self, data: dict[str, T]) -> None:
154
163
  """Load event data."""
155
164
  await asyncio.gather(
156
165
  *(self.dispatch(name, value) for name, value in data.items())
157
166
  )
158
167
 
159
- def load_nowait(self, data: dict[str, Any]) -> None:
168
+ def load_nowait(self, data: dict[str, T]) -> None:
160
169
  """Load event data without waiting."""
161
170
  self.create_task(self.load(data))
162
171