python-rako-2025 0.3.8__tar.gz → 0.3.10__tar.gz

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.
Files changed (23) hide show
  1. {python_rako_2025-0.3.8 → python_rako_2025-0.3.10}/PKG-INFO +1 -1
  2. python_rako_2025-0.3.10/python_rako/__version__.py +1 -0
  3. {python_rako_2025-0.3.8 → python_rako_2025-0.3.10}/python_rako/bridge.py +13 -5
  4. {python_rako_2025-0.3.8 → python_rako_2025-0.3.10}/python_rako_2025.egg-info/PKG-INFO +1 -1
  5. python_rako_2025-0.3.8/python_rako/__version__.py +0 -1
  6. {python_rako_2025-0.3.8 → python_rako_2025-0.3.10}/LICENSE +0 -0
  7. {python_rako_2025-0.3.8 → python_rako_2025-0.3.10}/README.md +0 -0
  8. {python_rako_2025-0.3.8 → python_rako_2025-0.3.10}/pyproject.toml +0 -0
  9. {python_rako_2025-0.3.8 → python_rako_2025-0.3.10}/python_rako/__init__.py +0 -0
  10. {python_rako_2025-0.3.8 → python_rako_2025-0.3.10}/python_rako/const.py +0 -0
  11. {python_rako_2025-0.3.8 → python_rako_2025-0.3.10}/python_rako/exceptions.py +0 -0
  12. {python_rako_2025-0.3.8 → python_rako_2025-0.3.10}/python_rako/helpers.py +0 -0
  13. {python_rako_2025-0.3.8 → python_rako_2025-0.3.10}/python_rako/model.py +0 -0
  14. {python_rako_2025-0.3.8 → python_rako_2025-0.3.10}/python_rako/py.typed +0 -0
  15. {python_rako_2025-0.3.8 → python_rako_2025-0.3.10}/python_rako_2025.egg-info/SOURCES.txt +0 -0
  16. {python_rako_2025-0.3.8 → python_rako_2025-0.3.10}/python_rako_2025.egg-info/dependency_links.txt +0 -0
  17. {python_rako_2025-0.3.8 → python_rako_2025-0.3.10}/python_rako_2025.egg-info/requires.txt +0 -0
  18. {python_rako_2025-0.3.8 → python_rako_2025-0.3.10}/python_rako_2025.egg-info/top_level.txt +0 -0
  19. {python_rako_2025-0.3.8 → python_rako_2025-0.3.10}/setup.cfg +0 -0
  20. {python_rako_2025-0.3.8 → python_rako_2025-0.3.10}/setup.py +0 -0
  21. {python_rako_2025-0.3.8 → python_rako_2025-0.3.10}/tests/test_bridge.py +0 -0
  22. {python_rako_2025-0.3.8 → python_rako_2025-0.3.10}/tests/test_helpers.py +0 -0
  23. {python_rako_2025-0.3.8 → python_rako_2025-0.3.10}/tests/test_model.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-rako-2025
3
- Version: 0.3.8
3
+ Version: 0.3.10
4
4
  Summary: Asynchronous Python client for Rako Controls Lighting
5
5
  Author-email: Simon Leigh <simonleigh@users.noreply.github.com>
6
6
  Project-URL: Homepage, https://github.com/simonleigh/python-rako
@@ -0,0 +1 @@
1
+ 0.3.10
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import asyncio
4
4
  import logging
5
+ import threading
5
6
  from collections.abc import AsyncGenerator, Generator
6
7
  from typing import Any
7
8
 
@@ -39,6 +40,9 @@ from python_rako.model import (
39
40
 
40
41
  _LOGGER = logging.getLogger(__name__)
41
42
 
43
+ # Thread lock for XML parsing to ensure concurrency safety
44
+ _XML_PARSE_LOCK = threading.Lock()
45
+
42
46
 
43
47
  class _BridgeCommander:
44
48
  def __init__(self, host: str, port: int):
@@ -149,6 +153,7 @@ class Bridge:
149
153
  self.level_cache: LevelCache = LevelCache()
150
154
  self.scene_cache: SceneCache = SceneCache()
151
155
  self._cached_xml: str | None = None
156
+ self._xml_fetch_lock = asyncio.Lock()
152
157
 
153
158
  @property
154
159
  def _discovery_url(self) -> str:
@@ -157,9 +162,10 @@ class Bridge:
157
162
  async def get_rako_xml(
158
163
  self, session: aiohttp.ClientSession, force_refresh: bool = False
159
164
  ) -> str:
160
- if self._cached_xml is None or force_refresh:
161
- async with session.get(self._discovery_url) as response:
162
- self._cached_xml = await response.text()
165
+ async with self._xml_fetch_lock:
166
+ if self._cached_xml is None or force_refresh:
167
+ async with session.get(self._discovery_url) as response:
168
+ self._cached_xml = await response.text()
163
169
  assert self._cached_xml is not None
164
170
  return self._cached_xml
165
171
 
@@ -227,7 +233,8 @@ class Bridge:
227
233
 
228
234
  @staticmethod
229
235
  def get_bridge_info_from_discovery_xml(xml: str) -> BridgeInfo:
230
- xml_dict = xmltodict.parse(xml)
236
+ with _XML_PARSE_LOCK:
237
+ xml_dict = xmltodict.parse(xml)
231
238
  info = xml_dict["rako"].get("info", dict())
232
239
  config = xml_dict["rako"].get("config", dict())
233
240
  return BridgeInfo(
@@ -270,7 +277,8 @@ class Bridge:
270
277
  else:
271
278
  target_types = set(device_types)
272
279
 
273
- xml_dict = xmltodict.parse(xml, force_list={"Room"})
280
+ with _XML_PARSE_LOCK:
281
+ xml_dict = xmltodict.parse(xml, force_list={"Room"})
274
282
  for room in xml_dict["rako"]["rooms"]["Room"]:
275
283
  room_id = int(room["@id"])
276
284
  room_type = room.get("Type", "Lights")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-rako-2025
3
- Version: 0.3.8
3
+ Version: 0.3.10
4
4
  Summary: Asynchronous Python client for Rako Controls Lighting
5
5
  Author-email: Simon Leigh <simonleigh@users.noreply.github.com>
6
6
  Project-URL: Homepage, https://github.com/simonleigh/python-rako
@@ -1 +0,0 @@
1
- 0.3.8