pyg90alarm 2.2.0__py3-none-any.whl → 2.3.1__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.
pyg90alarm/alarm.py CHANGED
@@ -566,10 +566,11 @@ class G90Alarm(G90NotificationProtocol):
566
566
  sensor._set_occupancy(False)
567
567
  sensor.state_callback.invoke(sensor.occupancy)
568
568
 
569
+ alert_config_flags = await self.alert_config.flags
569
570
  # Determine if door close notifications are available for the given
570
571
  # sensor
571
- door_close_alert_enabled = await self.alert_config.get_flag(
572
- G90AlertConfigFlags.DOOR_CLOSE
572
+ door_close_alert_enabled = (
573
+ G90AlertConfigFlags.DOOR_CLOSE in alert_config_flags
573
574
  )
574
575
  # The condition intentionally doesn't account for cord sensors of
575
576
  # subtype door, since those won't send door open/close alerts, only
@@ -587,7 +588,7 @@ class G90Alarm(G90NotificationProtocol):
587
588
  ' closing event will be emulated upon'
588
589
  ' %s seconds',
589
590
  name, sensor.type,
590
- await self.alert_config.flags,
591
+ alert_config_flags,
591
592
  self._reset_occupancy_interval)
592
593
  G90Callback.invoke_delayed(
593
594
  self._reset_occupancy_interval,
@@ -1230,6 +1231,7 @@ class G90Alarm(G90NotificationProtocol):
1230
1231
  local_port=notifications_local_port
1231
1232
  )
1232
1233
 
1234
+ # pylint: disable=too-many-positional-arguments
1233
1235
  async def use_cloud_notifications(
1234
1236
  self, cloud_local_host: str = CLOUD_NOTIFICATIONS_HOST,
1235
1237
  cloud_local_port: int = CLOUD_NOTIFICATIONS_PORT,
@@ -69,7 +69,8 @@ class G90CloudNotifications(G90NotificationsBase, asyncio.Protocol):
69
69
  :param keep_single_connection: Whether to keep only a single device
70
70
  connection
71
71
  """
72
- # pylint:disable=too-many-arguments
72
+ # pylint:disable=too-many-positional-arguments,too-many-arguments
73
+ # pylint:disable=too-many-statements
73
74
  def __init__(
74
75
  self,
75
76
  protocol_factory: Callable[[], G90NotificationProtocol],
@@ -68,7 +68,7 @@ class G90BaseList(Generic[T], ABC):
68
68
 
69
69
  :return: Async generator of entities
70
70
  """
71
- yield cast(T, None)
71
+ yield cast(T, None) # pragma: no cover
72
72
 
73
73
  @property
74
74
  async def entities(self) -> List[T]:
@@ -231,25 +231,30 @@ class G90BaseList(Generic[T], ABC):
231
231
  # Collect indexes in use by the existing entities
232
232
  occupied_indexes = set(x.index for x in entities)
233
233
  # Generate a set of possible indexes from 0 to the maximum index in
234
- # use
235
- possible_indexes = set(range(0, max(occupied_indexes)))
234
+ # use, or provide an empty set if there are no existing entities
235
+ if occupied_indexes:
236
+ possible_indexes = set(range(0, max(occupied_indexes)))
237
+ else:
238
+ # No occupied indexes, so possible_indexes is empty
239
+ possible_indexes = set()
236
240
 
237
241
  try:
238
242
  # Find the first free index by taking difference between
239
243
  # possible indexes and occupied ones, and then taking the minimum
240
244
  # value off the difference
241
245
  free_idx = min(
242
- set(possible_indexes).difference(occupied_indexes)
246
+ possible_indexes.difference(occupied_indexes)
243
247
  )
244
- _LOGGER.debug(
245
- 'Found free index: %s out of occupied indexes: %s',
246
- free_idx, occupied_indexes
247
- )
248
- return free_idx
249
248
  except ValueError:
250
249
  # If no gaps in existing indexes, then return the index next to
251
250
  # the last existing entity
252
- return len(entities)
251
+ free_idx = len(entities)
252
+
253
+ _LOGGER.debug(
254
+ 'Found free index=%s out of occupied indexes: %s',
255
+ free_idx, occupied_indexes
256
+ )
257
+ return free_idx
253
258
 
254
259
  @property
255
260
  def list_change_callback(self) -> Optional[ListChangeCallback[T]]:
@@ -59,11 +59,11 @@ class G90BaseCommand(DatagramProtocol):
59
59
  # Lock need to be shared across all of the class instances
60
60
  _sk_lock = asyncio.Lock()
61
61
 
62
+ # pylint: disable=too-many-positional-arguments,too-many-arguments
62
63
  def __init__(self, host: str, port: int, code: G90Commands,
63
64
  data: Optional[G90BaseCommandData] = None,
64
65
  local_port: Optional[int] = None,
65
66
  timeout: float = 3.0, retries: int = 3) -> None:
66
- # pylint: disable=too-many-arguments
67
67
  self._remote_host = host
68
68
  self._remote_port = port
69
69
  self._local_port = local_port
@@ -22,7 +22,7 @@
22
22
  Represents various configuration aspects of the alarm panel.
23
23
  """
24
24
  from __future__ import annotations
25
- from typing import TYPE_CHECKING, Optional
25
+ from typing import TYPE_CHECKING
26
26
  import logging
27
27
  from dataclasses import dataclass
28
28
  from enum import IntFlag
@@ -79,22 +79,9 @@ class G90AlertConfig:
79
79
  Represents alert configuration as received from the alarm panel.
80
80
  """
81
81
  def __init__(self, parent: G90Alarm) -> None:
82
- self._alert_config: Optional[G90AlertConfigData] = None
83
82
  self.parent = parent
84
83
 
85
84
  async def _get(self) -> G90AlertConfigData:
86
- """
87
- Retrieves the alert configuration flags from the device. Please note
88
- the configuration is cached upon first call, so you need to
89
- re-instantiate the class to reflect any updates there.
90
-
91
- :return: The alerts configured
92
- """
93
- if not self._alert_config:
94
- self._alert_config = await self._get_uncached()
95
- return self._alert_config
96
-
97
- async def _get_uncached(self) -> G90AlertConfigData:
98
85
  """
99
86
  Retrieves the alert configuration flags directly from the device.
100
87
 
@@ -110,22 +97,23 @@ class G90AlertConfig:
110
97
  return data
111
98
 
112
99
  async def set(self, flags: G90AlertConfigFlags) -> None:
100
+ """
101
+ .. deprecated:: 2.3.0
102
+
103
+ This method is deprecated and will always raise a RuntimeError.
104
+ Please use :meth:`set_flag` to set individual flags.
105
+ """
106
+ raise RuntimeError(
107
+ 'The set() method is deprecated. Please use set_flag() to set'
108
+ ' individual flags instead.'
109
+ )
110
+
111
+ async def _set(self, flags: G90AlertConfigFlags) -> None:
113
112
  """
114
113
  Sets the alert configuration flags on the device.
115
114
  """
116
- # Use uncached method retrieving the alert configuration, to ensure the
117
- # actual value retrieved from the device
118
115
  _LOGGER.debug('Setting alert configuration to %s', repr(flags))
119
- alert_config = await self._get_uncached()
120
- if alert_config != self._alert_config:
121
- _LOGGER.warning(
122
- 'Alert configuration changed externally,'
123
- ' overwriting (read "%s", will be set to "%s")',
124
- repr(alert_config), repr(flags)
125
- )
126
116
  await self.parent.command(G90Commands.SETNOTICEFLAG, [flags.value])
127
- # Update the alert configuration stored
128
- (await self._get()).flags = flags
129
117
 
130
118
  async def get_flag(self, flag: G90AlertConfigFlags) -> bool:
131
119
  """
@@ -135,20 +123,31 @@ class G90AlertConfig:
135
123
 
136
124
  async def set_flag(self, flag: G90AlertConfigFlags, value: bool) -> None:
137
125
  """
126
+ Sets the given flag to the desired value.
127
+
128
+ Uses read-modify-write approach.
129
+
138
130
  :param flag: The flag to set
139
131
  :param value: The value to set
140
132
  """
133
+ # Retrieve current flags
134
+ current_flags = await self.flags
141
135
  # Skip updating the flag if it has the desired value
142
- if await self.get_flag(flag) == value:
136
+ if (flag in current_flags) == value:
143
137
  _LOGGER.debug(
144
138
  'Flag %s already set to %s, skipping update',
145
139
  repr(flag), value
146
140
  )
147
141
  return
148
142
 
149
- # Invert corresponding user flag and set it
150
- flags = await self.flags ^ flag
151
- await self.set(flags)
143
+ # Set or reset corresponding user flag depending on desired value
144
+ if value:
145
+ current_flags |= flag
146
+ else:
147
+ current_flags &= ~flag
148
+
149
+ # Set the updated flags
150
+ await self._set(current_flags)
152
151
 
153
152
  @property
154
153
  async def flags(self) -> G90AlertConfigFlags:
@@ -55,7 +55,8 @@ class G90LocalNotifications(G90NotificationsBase, DatagramProtocol):
55
55
  :param local_host: The host on which the local host is listening for
56
56
  notifications.
57
57
  """
58
- def __init__( # pylint:disable=too-many-arguments
58
+ # pylint:disable=too-many-positional-arguments,too-many-arguments
59
+ def __init__(
59
60
  self, protocol_factory: Callable[[], G90NotificationProtocol],
60
61
  port: int, host: str, local_port: int, local_host: str,
61
62
  ):
@@ -48,11 +48,11 @@ class G90PaginatedCommand(G90BaseCommand):
48
48
  """
49
49
  Implements paginated command for alarm panel protocol.
50
50
  """
51
+ # pylint: disable=too-many-positional-arguments,too-many-arguments
51
52
  def __init__(
52
53
  self, host: str, port: int, code: G90Commands, start: int, end: int,
53
54
  **kwargs: Any
54
55
  ) -> None:
55
- # pylint: disable=too-many-arguments
56
56
  self._start = start
57
57
  self._end = end
58
58
  self._expected_nelems = end - start + 1
@@ -49,11 +49,11 @@ class G90PaginatedResult:
49
49
  Processes paginated response from G90 corresponding panel commands.
50
50
  """
51
51
  # pylint: disable=too-few-public-methods
52
+ # pylint: disable=too-many-positional-arguments,too-many-arguments
52
53
  def __init__(
53
54
  self, host: str, port: int, code: G90Commands, start: int = 1,
54
55
  end: Optional[int] = None, **kwargs: Any
55
56
  ):
56
- # pylint: disable=too-many-arguments
57
57
  self._host = host
58
58
  self._port = port
59
59
  self._code = code
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyg90alarm
3
- Version: 2.2.0
3
+ Version: 2.3.1
4
4
  Summary: G90 Alarm system protocol
5
5
  Home-page: https://github.com/hostcc/pyg90alarm
6
6
  Author: Ilia Sotnikov
@@ -1,5 +1,5 @@
1
1
  pyg90alarm/__init__.py,sha256=9RyHo4m46owUxAdPMFOkrr0VSd1lXK9QWyXMQlia7tM,3018
2
- pyg90alarm/alarm.py,sha256=Lyg1dWNHfUhEzmA_wSzZgR8NUQqK8MvT296L-_bAslY,46939
2
+ pyg90alarm/alarm.py,sha256=Y80AsrC5-s4xfsCnFcVpNPKbIWBZ8yDo_bTCsthL4iM,47033
3
3
  pyg90alarm/callback.py,sha256=9PVtjRs2MLn80AgiM-UJNL8ZJF4_PxcopJIpxMmB3vc,4707
4
4
  pyg90alarm/const.py,sha256=w2BzsVRDxfdwOb9590zsntGMlVWEH80zbQ4djojft9U,6851
5
5
  pyg90alarm/exceptions.py,sha256=9LleQC2SkJXjv80FlWMeaHs9ZjXxCvZx9UtYdrvejyY,1951
@@ -7,7 +7,7 @@ pyg90alarm/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  pyg90alarm/cloud/__init__.py,sha256=u7ZzrIwCsdgmBmgtpCe6c_Kipdo8nG8PEOEcaAHXCxI,1407
8
8
  pyg90alarm/cloud/const.py,sha256=FYUxkj0DSI7nnXZHsJMfv8RNQiXKV3TYKGHSdfHdMjg,2113
9
9
  pyg90alarm/cloud/messages.py,sha256=L3cpP3IbDRdw3W6FeQxTPXoDlpUv7Fm4t-RkH9Uj4dg,18032
10
- pyg90alarm/cloud/notifications.py,sha256=4n0pIpv_TH_9EXZQyqTjNc_AOJPT8DmxlpiPAGz0D1o,15598
10
+ pyg90alarm/cloud/notifications.py,sha256=0RxCBVcvDuwE0I1m3SLDXDQqCJimDcN4f45gr-Hvt1A,15669
11
11
  pyg90alarm/cloud/protocol.py,sha256=82l2IXSM12tv_iWkTrAQZ-aw5UR4tmWFQJKVcgBfIww,16159
12
12
  pyg90alarm/definitions/__init__.py,sha256=s0NZnkW_gMH718DJbgez28z9WA231CyszUf1O_ojUiI,68
13
13
  pyg90alarm/definitions/base.py,sha256=Q2DQXfFks9u-ke65_5xVTqCUXJmJGxBxFTeWnite1bw,6757
@@ -15,28 +15,28 @@ pyg90alarm/definitions/devices.py,sha256=K0DQnyE-1hlhIGwRfZojKJYMSmlJzmyWcZ_98ur
15
15
  pyg90alarm/definitions/sensors.py,sha256=bDecBGyUo7wFVNuD5Fu1JNZQHcMDv-234BuNKioaQQs,27426
16
16
  pyg90alarm/entities/__init__.py,sha256=hHb6AOiC4Tz--rOWiiICMdLaZDs1Tf_xpWk_HeS_gO4,66
17
17
  pyg90alarm/entities/base_entity.py,sha256=hNhhuuwNuir54uVMZzPbjE0N6WL8wKvoW_KZa4R8L8U,2680
18
- pyg90alarm/entities/base_list.py,sha256=Ot4kd44CUheSvYETjEQBQNT_HaOTWZhKa-4L5pr8LMI,9276
18
+ pyg90alarm/entities/base_list.py,sha256=vNP0T8qg7lgrES0IBs4zOggQM6Uxyfarfds46bbAnH0,9482
19
19
  pyg90alarm/entities/device.py,sha256=eWE_N83hiDs5I-TT5F_W0Vb8sVugLldrDc9Lj9sgVLo,3700
20
20
  pyg90alarm/entities/device_list.py,sha256=PKnHEazeT3iUEaz70bW1OaWh0wq-7WOY-7dpV4FVCTc,5984
21
21
  pyg90alarm/entities/sensor.py,sha256=hunu-X-RhC8Wp52VMeanfqQg8rBSP8TG0qacJiFZEhg,27653
22
22
  pyg90alarm/entities/sensor_list.py,sha256=0S88bhTn91O45WgbIIMQ0iXaNjlUWmMBOOFwj2Hg73U,6993
23
23
  pyg90alarm/local/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
- pyg90alarm/local/base_cmd.py,sha256=7n8vRyJ3jPjkTy8WD4GJJojDFuj4chFGj_L-KZQhy0E,10465
25
- pyg90alarm/local/config.py,sha256=nlcNNxOJ5QAJVzrCCckvjs_iS8J5nOmIENNJXYYJrts,5290
24
+ pyg90alarm/local/base_cmd.py,sha256=f0PozHJjErIg08vn0sAacHbigJSFor8q5jdxfXiM27c,10491
25
+ pyg90alarm/local/config.py,sha256=AYDswfeM1aZImoAr6ZB-4fVIvMuTiNgkF_bLIROVckI,4922
26
26
  pyg90alarm/local/discovery.py,sha256=8YVIXuNe57lhas0VSRf7QXZH83pEDGNj9oehNY4Kh2U,3576
27
27
  pyg90alarm/local/history.py,sha256=v_deRl62tHeysydyeLRvyHJwcBMnKonsEbXXSXb8XP8,9138
28
28
  pyg90alarm/local/host_info.py,sha256=4lFIaFEpYd3EvgNrDJmKijTrzX9i29nFISLLlXGnkmE,2759
29
29
  pyg90alarm/local/host_status.py,sha256=WHGtw-A0wHILqVWP4DnZhXj8DPRGyS26AV0bL1isTz4,1863
30
- pyg90alarm/local/notifications.py,sha256=HAyDQivc1AEtSjNwOWOws_1CP1OirZNI8Gu-3BsSTZg,4558
31
- pyg90alarm/local/paginated_cmd.py,sha256=bUCtuCYec2pWkufY43sx3gCYE0prysbFY7seegUtkRw,4441
32
- pyg90alarm/local/paginated_result.py,sha256=knvFKtpswtVnC-1Av5vbVYhL5bue60qKmo4p6FCv0_k,5448
30
+ pyg90alarm/local/notifications.py,sha256=Vs6NQJciYqDALV-WwzH6wIcTGdX_UD4XBuHWjSOpCDY,4591
31
+ pyg90alarm/local/paginated_cmd.py,sha256=5pPVP8f4ydjgu8Yq6MwqINJAUt52fFlD17wO4AI88Pc,4467
32
+ pyg90alarm/local/paginated_result.py,sha256=2tW3kMYkfCoNIhXi0N8acoIAhGhZYIbWdc347CH-Pjg,5474
33
33
  pyg90alarm/local/targeted_discovery.py,sha256=Ik2C2VBtVLurf3-RKko4O2R3B6MrmFdOskd457uyASU,5516
34
34
  pyg90alarm/local/user_data_crc.py,sha256=JQBOPY3RlOgVtvR55R-rM8OuKjYW-BPXQ0W4pi6CEH0,1689
35
35
  pyg90alarm/notifications/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
36
  pyg90alarm/notifications/base.py,sha256=_YX0kL9bqMAOdKBRZ5M-SIrwR4xotnZwgxqWoyEgxAk,16032
37
37
  pyg90alarm/notifications/protocol.py,sha256=mvn6hVNopOUgwQy4nWHKp7ydt5r84lsDWCCaWYJjL9Q,4422
38
- pyg90alarm-2.2.0.dist-info/licenses/LICENSE,sha256=f884inRbeNv-O-hbwz62Ro_1J8xiHRTnJ2cCx6A0WvU,1070
39
- pyg90alarm-2.2.0.dist-info/METADATA,sha256=jZSTiPv1k_NLibmwb-CrryWLg-_fajhEpWx3GBA9k2E,12568
40
- pyg90alarm-2.2.0.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
41
- pyg90alarm-2.2.0.dist-info/top_level.txt,sha256=czHiGxYMyTk5QEDTDb0EpPiKqUMRa8zI4zx58Ii409M,11
42
- pyg90alarm-2.2.0.dist-info/RECORD,,
38
+ pyg90alarm-2.3.1.dist-info/licenses/LICENSE,sha256=f884inRbeNv-O-hbwz62Ro_1J8xiHRTnJ2cCx6A0WvU,1070
39
+ pyg90alarm-2.3.1.dist-info/METADATA,sha256=2t6egkAMkWvJjEhBAK_4MYn7tlCnuQYq85WQOz0Vtx8,12568
40
+ pyg90alarm-2.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
41
+ pyg90alarm-2.3.1.dist-info/top_level.txt,sha256=czHiGxYMyTk5QEDTDb0EpPiKqUMRa8zI4zx58Ii409M,11
42
+ pyg90alarm-2.3.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.8.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5