uiprotect 1.13.0__py3-none-any.whl → 1.15.0__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.

Potentially problematic release.


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

uiprotect/data/base.py CHANGED
@@ -485,68 +485,44 @@ class ProtectBaseObject(BaseModel):
485
485
 
486
486
  return new_data
487
487
 
488
- def _inject_api(
489
- self,
490
- data: dict[str, Any],
491
- api: ProtectApiClient | None,
492
- ) -> dict[str, Any]:
493
- data["api"] = api
494
- unifi_objs_sets = self._get_protect_objs_set()
495
- has_unifi_objs = bool(unifi_objs_sets)
496
- unifi_lists_sets = self._get_protect_lists_set()
497
- has_unifi_lists = bool(unifi_lists_sets)
498
- unifi_dicts_sets = self._get_protect_dicts_set()
499
- has_unifi_dicts = bool(unifi_dicts_sets)
500
- for key, value in data.items():
501
- if has_unifi_objs and key in unifi_objs_sets and isinstance(value, dict):
502
- value["api"] = api
503
- elif (
504
- has_unifi_lists and key in unifi_lists_sets and isinstance(value, list)
505
- ):
506
- for item in value:
507
- if isinstance(item, dict):
508
- item["api"] = api
509
- elif (
510
- has_unifi_dicts and key in unifi_dicts_sets and isinstance(value, dict)
511
- ):
512
- for item in value.values():
513
- if isinstance(item, dict):
514
- item["api"] = api
488
+ def update_from_dict(cls: ProtectObject, data: dict[str, Any]) -> ProtectObject:
489
+ """
490
+ Updates current object from a cleaned UFP JSON dict.
515
491
 
516
- return data
492
+ The api client is injected into each dict for any child
493
+ UFP objects that are detected.
494
+ """
495
+ unifi_objs = cls._get_protect_objs()
496
+ has_unifi_objs = bool(unifi_objs)
497
+ unifi_lists = cls._get_protect_lists()
498
+ has_unifi_lists = bool(unifi_lists)
517
499
 
518
- def update_from_dict(self: ProtectObject, data: dict[str, Any]) -> ProtectObject:
519
- """Updates current object from a cleaned UFP JSON dict"""
520
- data_set = set(data)
521
- for key in self._get_protect_objs_set().intersection(data_set):
522
- unifi_obj: Any | None = getattr(self, key)
523
- if unifi_obj is not None and isinstance(unifi_obj, ProtectBaseObject):
524
- item = data.pop(key)
525
- if item is not None:
526
- item = unifi_obj.update_from_dict(item)
527
- setattr(self, key, item)
528
-
529
- data = self._inject_api(data, self._api)
530
- unifi_lists = self._get_protect_lists()
531
- for key in self._get_protect_lists_set().intersection(data_set):
532
- if not isinstance(data[key], list):
533
- continue
534
- klass = unifi_lists[key]
535
- new_items = []
536
- for item in data.pop(key):
537
- if item is not None and isinstance(item, ProtectBaseObject):
538
- new_items.append(item)
539
- elif isinstance(item, dict):
540
- new_items.append(klass(**item))
541
- setattr(self, key, new_items)
542
-
543
- # Always injected above
544
- del data["api"]
545
-
546
- for key in data:
547
- setattr(self, key, convert_unifi_data(data[key], self.__fields__[key]))
548
-
549
- return self
500
+ api = cls._api
501
+ _fields = cls.__fields__
502
+ unifi_obj: ProtectBaseObject | None
503
+ if "api" in data:
504
+ del data["api"]
505
+ value: Any
506
+
507
+ for key, item in data.items():
508
+ if has_unifi_objs and key in unifi_objs and isinstance(item, dict):
509
+ if (unifi_obj := getattr(cls, key)) is not None:
510
+ value = unifi_obj.update_from_dict(item)
511
+ else:
512
+ value = None
513
+ elif has_unifi_lists and key in unifi_lists and isinstance(item, list):
514
+ klass = unifi_lists[key]
515
+ value = [
516
+ klass(**i, api=api) if isinstance(i, dict) else i
517
+ for i in item
518
+ if i is not None and isinstance(i, (dict, ProtectBaseObject))
519
+ ]
520
+ else:
521
+ value = convert_unifi_data(item, _fields[key])
522
+
523
+ setattr(cls, key, value)
524
+
525
+ return cls
550
526
 
551
527
  def dict_with_excludes(self) -> dict[str, Any]:
552
528
  """Returns a dict of the current object without any UFP objects converted to dicts."""
@@ -9,7 +9,7 @@ from copy import deepcopy
9
9
  from dataclasses import dataclass
10
10
  from datetime import datetime
11
11
  from functools import cache
12
- from typing import TYPE_CHECKING, Any, cast
12
+ from typing import TYPE_CHECKING, Any
13
13
 
14
14
  from aiohttp.client_exceptions import ServerDisconnectedError
15
15
 
@@ -298,20 +298,20 @@ class Bootstrap(ProtectBaseObject):
298
298
 
299
299
  def get_device_from_mac(self, mac: str) -> ProtectAdoptableDeviceModel | None:
300
300
  """Retrieve a device from MAC address."""
301
- ref = self.mac_lookup.get(normalize_mac(mac))
302
- if ref is None:
303
- return None
304
-
305
- devices: dict[str, ProtectModelWithId] = getattr(self, ref.model.devices_key)
306
- return cast(ProtectAdoptableDeviceModel, devices.get(ref.id))
301
+ return self._get_device_from_ref(self.mac_lookup.get(normalize_mac(mac)))
307
302
 
308
303
  def get_device_from_id(self, device_id: str) -> ProtectAdoptableDeviceModel | None:
309
304
  """Retrieve a device from device ID (without knowing model type)."""
310
- ref = self.id_lookup.get(device_id)
305
+ return self._get_device_from_ref(self.id_lookup.get(device_id))
306
+
307
+ def _get_device_from_ref(
308
+ self, ref: ProtectDeviceRef | None
309
+ ) -> ProtectAdoptableDeviceModel | None:
311
310
  if ref is None:
312
311
  return None
313
- devices: dict[str, ProtectModelWithId] = getattr(self, ref.model.devices_key)
314
- return cast(ProtectAdoptableDeviceModel, devices.get(ref.id))
312
+ devices_key = ref.model.devices_key
313
+ devices: dict[str, ProtectAdoptableDeviceModel] = getattr(self, devices_key)
314
+ return devices[ref.id]
315
315
 
316
316
  def process_event(self, event: Event) -> None:
317
317
  event_type = event.type
@@ -386,9 +386,8 @@ class Bootstrap(ProtectBaseObject):
386
386
  def _process_remove_packet(
387
387
  self, model_type: ModelType, packet: WSPacket
388
388
  ) -> WSSubscriptionMessage | None:
389
- devices: dict[str, ProtectDeviceModel] | None = getattr(
390
- self, model_type.devices_key, None
391
- )
389
+ devices_key = model_type.devices_key
390
+ devices: dict[str, ProtectDeviceModel] | None = getattr(self, devices_key, None)
392
391
 
393
392
  if devices is None:
394
393
  return None
@@ -615,9 +614,8 @@ class Bootstrap(ProtectBaseObject):
615
614
  if isinstance(device, NVR):
616
615
  self.nvr = device
617
616
  else:
618
- devices: dict[str, ProtectModelWithId] = getattr(
619
- self, model_type.devices_key
620
- )
617
+ devices_key = model_type.devices_key
618
+ devices: dict[str, ProtectModelWithId] = getattr(self, devices_key)
621
619
  devices[device.id] = device
622
620
  _LOGGER.debug("Successfully refresh model: %s %s", model_type, device_id)
623
621
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: uiprotect
3
- Version: 1.13.0
3
+ Version: 1.15.0
4
4
  Summary: Python API for Unifi Protect (Unofficial)
5
5
  Home-page: https://github.com/uilibs/uiprotect
6
6
  License: MIT
@@ -14,8 +14,8 @@ uiprotect/cli/nvr.py,sha256=TwxEg2XT8jXAbOqv6gc7KFXELKadeItEDYweSL4_-e8,4260
14
14
  uiprotect/cli/sensors.py,sha256=fQtcDJCVxs4VbAqcavgBy2ABiVxAW3GXtna6_XFBp2k,8153
15
15
  uiprotect/cli/viewers.py,sha256=2cyrp104ffIvgT0wYGIO0G35QMkEbFe7fSVqLwDXQYQ,2171
16
16
  uiprotect/data/__init__.py,sha256=OcfuJl2qXfHcj_mdnrHhzZ5tEIZrw8auziX5IE7dn-I,2938
17
- uiprotect/data/base.py,sha256=yzGm5RCeo9AqmgArWC8O7LhBp_Qxz1XSel3xRyhNAbM,37718
18
- uiprotect/data/bootstrap.py,sha256=wjRFVrv1rOFVDcij6ZYm7dzMe0iz6AqYciQozC-J2TI,21893
17
+ uiprotect/data/base.py,sha256=OWKeMWk7n5VaHF_meTt2Ykw7H9zx6U47u-P2vLNDWzE,36627
18
+ uiprotect/data/bootstrap.py,sha256=copw7uL_YIthNH-PraSoqg5vL-UpGrt95zKy1FpHn5w,21881
19
19
  uiprotect/data/convert.py,sha256=8h6Il_DhMkPRDPj9F_rA2UZIlTuchS3BQD24peKpk2A,2185
20
20
  uiprotect/data/devices.py,sha256=Nq3bOko5PFf5LvEBoD4JV8kmbq50laRdh3VHMWX7t-0,111809
21
21
  uiprotect/data/nvr.py,sha256=XC4NO1c_Mom-hIpzj9ksKFcgKbHd6ToqWjkgzxJ1PJY,47636
@@ -30,8 +30,8 @@ uiprotect/test_util/__init__.py,sha256=d2g7afa0LSdixQ0kjEDYwafDFME_UlW2LzxpamZ2B
30
30
  uiprotect/test_util/anonymize.py,sha256=f-8ijU-_y9r-uAbhIPn0f0I6hzJpAkvJzc8UpWihObI,8478
31
31
  uiprotect/utils.py,sha256=6OLY8hNiCzk418PjJJIlFW7jjPzVt1vxBKEzBSqMeTk,18418
32
32
  uiprotect/websocket.py,sha256=JHI_2EZeRPqPyQopsBZS0dr3tu0HaTiqeLazfBXhW_8,7339
33
- uiprotect-1.13.0.dist-info/LICENSE,sha256=INx18jhdbVXMEiiBANeKEbrbz57ckgzxk5uutmmcxGk,1111
34
- uiprotect-1.13.0.dist-info/METADATA,sha256=64mSJs-bol2iFi_YUobezZybOEwOovljmPod2f9ELiw,10985
35
- uiprotect-1.13.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
36
- uiprotect-1.13.0.dist-info/entry_points.txt,sha256=J78AUTPrTTxgI3s7SVgrmGqDP7piX2wuuEORzhDdVRA,47
37
- uiprotect-1.13.0.dist-info/RECORD,,
33
+ uiprotect-1.15.0.dist-info/LICENSE,sha256=INx18jhdbVXMEiiBANeKEbrbz57ckgzxk5uutmmcxGk,1111
34
+ uiprotect-1.15.0.dist-info/METADATA,sha256=vGRfaDV2IzMD9WNxZ2Z9VDsSEwsegr1hJJET3YvBa5E,10985
35
+ uiprotect-1.15.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
36
+ uiprotect-1.15.0.dist-info/entry_points.txt,sha256=J78AUTPrTTxgI3s7SVgrmGqDP7piX2wuuEORzhDdVRA,47
37
+ uiprotect-1.15.0.dist-info/RECORD,,