python-izone 1.3.5__py3-none-any.whl → 1.3.7__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.
pizone/__init__.py CHANGED
@@ -29,10 +29,14 @@ from types import ModuleType
29
29
  from typing import Any
30
30
 
31
31
  from . import power as power_mod
32
- from .const import PLACEHOLDER_DEVICE_UID
33
32
  from .controller import Controller
34
33
  from .discovery import DiscoveryService, Listener, create_discovery, discovery
35
- from .exceptions import ControllerCommandError, ResponseDecodeError, UnpairedBridgeError
34
+ from .exceptions import (
35
+ ControllerAlreadyClaimedError,
36
+ ControllerCommandError,
37
+ ResponseDecodeError,
38
+ UnpairedBridgeError,
39
+ )
36
40
  from .power import BatteryLevel, Power, PowerChannel, PowerDevice, PowerGroup
37
41
  from .types import ControllerEndpoint
38
42
  from .zone import Zone
@@ -60,9 +64,9 @@ sys.modules[__name__].__class__ = _PizoneModule
60
64
 
61
65
  __all__ = [
62
66
  "ENABLE_POWER",
63
- "PLACEHOLDER_DEVICE_UID",
64
67
  "BatteryLevel",
65
68
  "Controller",
69
+ "ControllerAlreadyClaimedError",
66
70
  "ControllerCommandError",
67
71
  "ControllerEndpoint",
68
72
  "DiscoveryService",
pizone/discovery.py CHANGED
@@ -24,7 +24,7 @@ import ifaddr
24
24
 
25
25
  from .const import PLACEHOLDER_DEVICE_UID
26
26
  from .controller import Controller
27
- from .exceptions import raise_if_placeholder_uid
27
+ from .exceptions import ControllerAlreadyClaimedError, raise_if_placeholder_uid
28
28
  from .types import ControllerEndpoint
29
29
  from .zone import Zone
30
30
 
@@ -50,7 +50,7 @@ DISCOVERY_RESCAN = 20.0
50
50
  RESCAN_COOLDOWN = 5.0
51
51
 
52
52
  # disposition: 1.4 — active discover_by_uid / discover_all wait
53
- SCAN_TIMEOUT = 20.0
53
+ SCAN_TIMEOUT = 5.0
54
54
 
55
55
  _LOG = logging.getLogger("pizone.discovery")
56
56
 
@@ -405,7 +405,9 @@ class DiscoveryService:
405
405
  def _ensure_endpoint_available(self, endpoint: ControllerEndpoint) -> None:
406
406
  """Raise if *endpoint* is already claimed."""
407
407
  if endpoint.uid in self._claimed_endpoints:
408
- raise RuntimeError(f"Controller {endpoint.uid} already created")
408
+ raise ControllerAlreadyClaimedError(
409
+ f"Controller {endpoint.uid} already created"
410
+ )
409
411
 
410
412
  # disposition: 1.4
411
413
  def _claim_endpoint(self, endpoint: ControllerEndpoint) -> None:
@@ -451,7 +453,9 @@ class DiscoveryService:
451
453
  """
452
454
  claimed = self._endpoint_by_host(self._claimed_endpoints, host)
453
455
  if claimed is not None:
454
- raise RuntimeError(f"Controller {claimed.uid} already created")
456
+ raise ControllerAlreadyClaimedError(
457
+ f"Controller {claimed.uid} already created"
458
+ )
455
459
  known = self._endpoint_by_host(self._known_endpoints, host)
456
460
  if known is not None:
457
461
  return known
@@ -476,7 +480,7 @@ class DiscoveryService:
476
480
  """
477
481
  raise_if_placeholder_uid(uid)
478
482
  if uid in self._claimed_endpoints:
479
- raise RuntimeError(f"Controller {uid} already created")
483
+ raise ControllerAlreadyClaimedError(f"Controller {uid} already created")
480
484
  endpoint = self._known_endpoints.get(uid)
481
485
  if endpoint is not None:
482
486
  return endpoint
@@ -569,7 +573,7 @@ class DiscoveryService:
569
573
 
570
574
  Raises:
571
575
  UnpairedBridgeError: If *uid* is the unpaired placeholder (no I/O).
572
- RuntimeError: If a controller with *uid* already exists.
576
+ ControllerAlreadyClaimedError: If a controller with *uid* already exists.
573
577
  ConnectionError: If the controller cannot be reached after
574
578
  address fallback.
575
579
  ControllerCommandError: If the device rejects the protocol request.
@@ -579,7 +583,7 @@ class DiscoveryService:
579
583
  """
580
584
  raise_if_placeholder_uid(uid)
581
585
  if uid in self._claimed_endpoints:
582
- raise RuntimeError(f"Controller {uid} already created")
586
+ raise ControllerAlreadyClaimedError(f"Controller {uid} already created")
583
587
  pending_address_changed: ControllerEndpoint | None = None
584
588
 
585
589
  try:
@@ -756,8 +760,13 @@ class DiscoveryService:
756
760
  return
757
761
  _LOG.info("Close called on discovery service.")
758
762
  self._close_task = current
759
- if self._transport:
763
+ if self._transport is not None:
764
+ # DatagramTransport.close() only schedules sock release via
765
+ # call_soon(_call_connection_lost). Wait until connection_lost
766
+ # clears _transport so a following create_discovery can bind :7005.
760
767
  self._transport.close()
768
+ while self._transport is not None:
769
+ await asyncio.sleep(0)
761
770
 
762
771
  pending = [task for task in list(self._tasks) if task is not current]
763
772
  for task in pending:
@@ -773,6 +782,7 @@ class DiscoveryService:
773
782
 
774
783
  def _on_connection_lost(self, exc: Exception | None) -> None:
775
784
  _LOG.debug("Connection Lost")
785
+ self._transport = None
776
786
  if not self._close_task:
777
787
  _LOG.error("Connection Lost unexpectedly: %s", repr(exc))
778
788
  self.create_task(self.close())
@@ -1002,5 +1012,12 @@ async def create_discovery(
1002
1012
  on_endpoint_discovered=on_endpoint_discovered,
1003
1013
  )
1004
1014
  _active_discovery = service
1005
- await service.start_discovery()
1015
+ try:
1016
+ await service.start_discovery()
1017
+ except BaseException:
1018
+ # close() clears the global when it finishes; clear again if close never ran.
1019
+ with suppress(BaseException):
1020
+ await service.close()
1021
+ _clear_discovery_global(service)
1022
+ raise
1006
1023
  return service
pizone/exceptions.py CHANGED
@@ -28,6 +28,14 @@ class UnpairedBridgeError(ValueError):
28
28
  """
29
29
 
30
30
 
31
+ class ControllerAlreadyClaimedError(Exception):
32
+ """A controller UID or host is already claimed on this discovery service.
33
+
34
+ Raised when ``discover_by_host``, ``discover_by_uid``, or ``create_controller``
35
+ would duplicate an active controller registration.
36
+ """
37
+
38
+
31
39
  def raise_if_placeholder_uid(uid: str) -> None:
32
40
  """Raise :exc:`UnpairedBridgeError` if *uid* is the unpaired placeholder."""
33
41
  if uid == PLACEHOLDER_DEVICE_UID:
pizone/version.py CHANGED
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '1.3.5'
22
- __version_tuple__ = version_tuple = (1, 3, 5)
21
+ __version__ = version = '1.3.7'
22
+ __version_tuple__ = version_tuple = (1, 3, 7)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-izone
3
- Version: 1.3.5
3
+ Version: 1.3.7
4
4
  Summary: A python interface to the iZone airconditioner controller
5
5
  Project-URL: Homepage, https://github.com/Swamp-Ig/pizone
6
6
  Author-email: Penny Wood <pypl@ninjateaparty.com>
@@ -0,0 +1,14 @@
1
+ pizone/__init__.py,sha256=9EbQzqD1XfS5fSE-zgFieuzxAfZcQb9a3wNXsMp0JKc,2644
2
+ pizone/const.py,sha256=0skTh6zBe61AJ_57fqdBrxz3aVBM3T4Ak_cPSkOx2Bo,153
3
+ pizone/controller.py,sha256=nctzAF8Y75T0_Ue9Hxxv9OfEex4zoNseOMjGfI6wHFE,41109
4
+ pizone/discovery.py,sha256=9akqPwsB8gcsmqnT5GQ3CCilo4m3jYL7cA3MWFOU1Uc,37442
5
+ pizone/exceptions.py,sha256=qzYNHzQBMDcuvLfxlvOsk6J2Lp0gtzlHqJWpzyEunvU,1603
6
+ pizone/power.py,sha256=bXoDRVD6gCfq0kJv132sjfy13DHGd6p2uBg9HcxRSxA,10343
7
+ pizone/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ pizone/types.py,sha256=fZrnec0Q815HyG2sFciLqNX0QDbTq1_0wTF92GXQh78,200
9
+ pizone/version.py,sha256=qggYsfTliS2fgO5WngEhVPgiQ-AREJyDah_xDSuzcIM,520
10
+ pizone/zone.py,sha256=tqiLJAJCmp1cehCtVPjawUNY9qyYypC4x3igI5jtDNo,7446
11
+ python_izone-1.3.7.dist-info/METADATA,sha256=t1FnN14YONJRs8bYY-sNsbADvzt6VaQbQLfOGlzCzDQ,2703
12
+ python_izone-1.3.7.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
13
+ python_izone-1.3.7.dist-info/licenses/licence.txt,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
14
+ python_izone-1.3.7.dist-info/RECORD,,
@@ -1,14 +0,0 @@
1
- pizone/__init__.py,sha256=IAZBU-UVisaiR2oHEVcLCRzuxieyU57xZ70uPjgsSLw,2627
2
- pizone/const.py,sha256=0skTh6zBe61AJ_57fqdBrxz3aVBM3T4Ak_cPSkOx2Bo,153
3
- pizone/controller.py,sha256=nctzAF8Y75T0_Ue9Hxxv9OfEex4zoNseOMjGfI6wHFE,41109
4
- pizone/discovery.py,sha256=vMdOunGrVS1ZWOgUAmm-dLdUOM9blGPKUcYr7683IV4,36659
5
- pizone/exceptions.py,sha256=wRO-COpyNyKL6P1vG0MlAVwbwo2iOvH0kRO7O75PUlo,1327
6
- pizone/power.py,sha256=bXoDRVD6gCfq0kJv132sjfy13DHGd6p2uBg9HcxRSxA,10343
7
- pizone/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- pizone/types.py,sha256=fZrnec0Q815HyG2sFciLqNX0QDbTq1_0wTF92GXQh78,200
9
- pizone/version.py,sha256=8n48nP6UfUYjAJjgHmQr6-hzX4qoTllJ-v-32sLOJbA,520
10
- pizone/zone.py,sha256=tqiLJAJCmp1cehCtVPjawUNY9qyYypC4x3igI5jtDNo,7446
11
- python_izone-1.3.5.dist-info/METADATA,sha256=u7byaXu4JhVKdbSZrYupB1xdy6MAYBAzSR_IPostzgU,2703
12
- python_izone-1.3.5.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
13
- python_izone-1.3.5.dist-info/licenses/licence.txt,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
14
- python_izone-1.3.5.dist-info/RECORD,,