uiprotect 1.11.0__tar.gz → 1.11.1__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.

Potentially problematic release.


This version of uiprotect might be problematic. Click here for more details.

Files changed (36) hide show
  1. {uiprotect-1.11.0 → uiprotect-1.11.1}/PKG-INFO +1 -1
  2. {uiprotect-1.11.0 → uiprotect-1.11.1}/pyproject.toml +1 -1
  3. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/data/base.py +1 -2
  4. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/data/bootstrap.py +38 -19
  5. {uiprotect-1.11.0 → uiprotect-1.11.1}/LICENSE +0 -0
  6. {uiprotect-1.11.0 → uiprotect-1.11.1}/README.md +0 -0
  7. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/__init__.py +0 -0
  8. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/__main__.py +0 -0
  9. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/api.py +0 -0
  10. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/cli/__init__.py +0 -0
  11. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/cli/backup.py +0 -0
  12. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/cli/base.py +0 -0
  13. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/cli/cameras.py +0 -0
  14. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/cli/chimes.py +0 -0
  15. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/cli/doorlocks.py +0 -0
  16. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/cli/events.py +0 -0
  17. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/cli/lights.py +0 -0
  18. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/cli/liveviews.py +0 -0
  19. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/cli/nvr.py +0 -0
  20. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/cli/sensors.py +0 -0
  21. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/cli/viewers.py +0 -0
  22. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/data/__init__.py +0 -0
  23. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/data/convert.py +0 -0
  24. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/data/devices.py +0 -0
  25. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/data/nvr.py +0 -0
  26. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/data/types.py +0 -0
  27. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/data/user.py +0 -0
  28. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/data/websocket.py +0 -0
  29. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/exceptions.py +0 -0
  30. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/py.typed +0 -0
  31. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/release_cache.json +0 -0
  32. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/stream.py +0 -0
  33. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/test_util/__init__.py +0 -0
  34. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/test_util/anonymize.py +0 -0
  35. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/utils.py +0 -0
  36. {uiprotect-1.11.0 → uiprotect-1.11.1}/src/uiprotect/websocket.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: uiprotect
3
- Version: 1.11.0
3
+ Version: 1.11.1
4
4
  Summary: Python API for Unifi Protect (Unofficial)
5
5
  Home-page: https://github.com/uilibs/uiprotect
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "uiprotect"
3
- version = "1.11.0"
3
+ version = "1.11.1"
4
4
  description = "Python API for Unifi Protect (Unofficial)"
5
5
  authors = ["UI Protect Maintainers <ui@koston.org>"]
6
6
  license = "MIT"
@@ -6,7 +6,7 @@ import asyncio
6
6
  import logging
7
7
  from collections.abc import Callable
8
8
  from datetime import datetime, timedelta
9
- from functools import cache, cached_property
9
+ from functools import cache
10
10
  from ipaddress import IPv4Address
11
11
  from typing import TYPE_CHECKING, Any, ClassVar, TypeVar
12
12
  from uuid import UUID
@@ -89,7 +89,6 @@ class ProtectBaseObject(BaseModel):
89
89
  arbitrary_types_allowed = True
90
90
  validate_assignment = True
91
91
  copy_on_model_validation = "shallow"
92
- keep_untouched = (cached_property,)
93
92
 
94
93
  def __init__(self, api: ProtectApiClient | None = None, **data: Any) -> None:
95
94
  """
@@ -8,7 +8,7 @@ from collections.abc import Iterable
8
8
  from copy import deepcopy
9
9
  from dataclasses import dataclass
10
10
  from datetime import datetime
11
- from functools import cache, cached_property
11
+ from functools import cache
12
12
  from typing import TYPE_CHECKING, Any, cast
13
13
 
14
14
  from aiohttp.client_exceptions import ServerDisconnectedError
@@ -181,6 +181,10 @@ class Bootstrap(ProtectBaseObject):
181
181
  mac_lookup: dict[str, ProtectDeviceRef] = {}
182
182
  id_lookup: dict[str, ProtectDeviceRef] = {}
183
183
  _ws_stats: list[WSStat] = PrivateAttr([])
184
+ _has_doorbell: bool | None = PrivateAttr(None)
185
+ _has_smart: bool | None = PrivateAttr(None)
186
+ _has_media: bool | None = PrivateAttr(None)
187
+ _recording_start: datetime | None = PrivateAttr(None)
184
188
  _refresh_tasks: set[asyncio.Task[None]] = PrivateAttr(set())
185
189
 
186
190
  @classmethod
@@ -248,33 +252,48 @@ class Bootstrap(ProtectBaseObject):
248
252
  def auth_user(self) -> User:
249
253
  return self._api.bootstrap.users[self.auth_user_id]
250
254
 
251
- @cached_property
255
+ @property
252
256
  def has_doorbell(self) -> bool:
253
- return any(c.feature_flags.is_doorbell for c in self.cameras.values())
257
+ if self._has_doorbell is None:
258
+ self._has_doorbell = any(
259
+ c.feature_flags.is_doorbell for c in self.cameras.values()
260
+ )
261
+
262
+ return self._has_doorbell
254
263
 
255
- @cached_property
264
+ @property
256
265
  def recording_start(self) -> datetime | None:
257
- """Get earliest recording date."""
258
- try:
259
- return min(
260
- c.stats.video.recording_start
261
- for c in self.cameras.values()
262
- if c.stats.video.recording_start is not None
263
- )
264
- except ValueError:
265
- return None
266
+ """Get earilest recording date."""
267
+ if self._recording_start is None:
268
+ try:
269
+ self._recording_start = min(
270
+ c.stats.video.recording_start
271
+ for c in self.cameras.values()
272
+ if c.stats.video.recording_start is not None
273
+ )
274
+ except ValueError:
275
+ return None
276
+ return self._recording_start
266
277
 
267
- @cached_property
278
+ @property
268
279
  def has_smart_detections(self) -> bool:
269
280
  """Check if any camera has smart detections."""
270
- return any(c.feature_flags.has_smart_detect for c in self.cameras.values())
281
+ if self._has_smart is None:
282
+ self._has_smart = any(
283
+ c.feature_flags.has_smart_detect for c in self.cameras.values()
284
+ )
285
+ return self._has_smart
271
286
 
272
- @cached_property
287
+ @property
273
288
  def has_media(self) -> bool:
274
289
  """Checks if user can read media for any camera."""
275
- if self.recording_start is None:
276
- return False
277
- return any(c.can_read_media(self.auth_user) for c in self.cameras.values())
290
+ if self._has_media is None:
291
+ if self.recording_start is None:
292
+ return False
293
+ self._has_media = any(
294
+ c.can_read_media(self.auth_user) for c in self.cameras.values()
295
+ )
296
+ return self._has_media
278
297
 
279
298
  def get_device_from_mac(self, mac: str) -> ProtectAdoptableDeviceModel | None:
280
299
  """Retrieve a device from MAC address."""
File without changes
File without changes