uiprotect 1.4.1__tar.gz → 1.6.0__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.4.1 → uiprotect-1.6.0}/PKG-INFO +1 -1
  2. {uiprotect-1.4.1 → uiprotect-1.6.0}/pyproject.toml +1 -1
  3. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/data/base.py +59 -90
  4. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/data/types.py +1 -1
  5. {uiprotect-1.4.1 → uiprotect-1.6.0}/LICENSE +0 -0
  6. {uiprotect-1.4.1 → uiprotect-1.6.0}/README.md +0 -0
  7. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/__init__.py +0 -0
  8. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/__main__.py +0 -0
  9. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/api.py +0 -0
  10. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/cli/__init__.py +0 -0
  11. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/cli/backup.py +0 -0
  12. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/cli/base.py +0 -0
  13. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/cli/cameras.py +0 -0
  14. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/cli/chimes.py +0 -0
  15. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/cli/doorlocks.py +0 -0
  16. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/cli/events.py +0 -0
  17. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/cli/lights.py +0 -0
  18. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/cli/liveviews.py +0 -0
  19. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/cli/nvr.py +0 -0
  20. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/cli/sensors.py +0 -0
  21. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/cli/viewers.py +0 -0
  22. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/data/__init__.py +0 -0
  23. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/data/bootstrap.py +0 -0
  24. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/data/convert.py +0 -0
  25. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/data/devices.py +0 -0
  26. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/data/nvr.py +0 -0
  27. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/data/user.py +0 -0
  28. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/data/websocket.py +0 -0
  29. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/exceptions.py +0 -0
  30. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/py.typed +0 -0
  31. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/release_cache.json +0 -0
  32. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/stream.py +0 -0
  33. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/test_util/__init__.py +0 -0
  34. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/test_util/anonymize.py +0 -0
  35. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/utils.py +0 -0
  36. {uiprotect-1.4.1 → uiprotect-1.6.0}/src/uiprotect/websocket.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: uiprotect
3
- Version: 1.4.1
3
+ Version: 1.6.0
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.4.1"
3
+ version = "1.6.0"
4
4
  description = "Python API for Unifi Protect (Unofficial)"
5
5
  authors = ["UI Protect Maintainers <ui@koston.org>"]
6
6
  license = "MIT"
@@ -139,34 +139,25 @@ class ProtectBaseObject(BaseModel):
139
139
  @classmethod
140
140
  def construct(cls, _fields_set: set[str] | None = None, **values: Any) -> Self:
141
141
  api: ProtectApiClient | None = values.pop("api", None)
142
- values_set = set(values)
143
-
144
- if (unifi_objs := cls._get_protect_objs()) and (
145
- intersections := cls._get_protect_objs_set().intersection(values_set)
146
- ):
147
- for key in intersections:
148
- if isinstance(values[key], dict):
149
- values[key] = unifi_objs[key].construct(**values[key])
150
-
151
- if (unifi_lists := cls._get_protect_lists()) and (
152
- intersections := cls._get_protect_lists_set().intersection(values_set)
153
- ):
154
- for key in intersections:
155
- if isinstance(values[key], list):
156
- values[key] = [
157
- unifi_lists[key].construct(**v) if isinstance(v, dict) else v
158
- for v in values[key]
159
- ]
160
-
161
- if (unifi_dicts := cls._get_protect_dicts()) and (
162
- intersections := cls._get_protect_dicts_set().intersection(values_set)
163
- ):
164
- for key in intersections:
165
- if isinstance(values[key], dict):
166
- values[key] = {
167
- k: unifi_dicts[key].construct(**v) if isinstance(v, dict) else v
168
- for k, v in values[key].items()
169
- }
142
+ unifi_objs = cls._get_protect_objs()
143
+ has_unifi_objs = bool(unifi_objs)
144
+ unifi_lists = cls._get_protect_lists()
145
+ has_unifi_lists = bool(unifi_lists)
146
+ unifi_dicts = cls._get_protect_dicts()
147
+ has_unifi_dicts = bool(unifi_dicts)
148
+ for key, value in values.items():
149
+ if has_unifi_objs and key in unifi_objs and isinstance(value, dict):
150
+ values[key] = unifi_objs[key].construct(**value)
151
+ elif has_unifi_lists and key in unifi_lists and isinstance(value, list):
152
+ values[key] = [
153
+ unifi_lists[key].construct(**v) if isinstance(v, dict) else v
154
+ for v in value
155
+ ]
156
+ elif has_unifi_dicts and key in unifi_dicts and isinstance(value, dict):
157
+ values[key] = {
158
+ k: unifi_dicts[key].construct(**v) if isinstance(v, dict) else v
159
+ for k, v in value.items()
160
+ }
170
161
 
171
162
  obj = super().construct(_fields_set=_fields_set, **values)
172
163
  if api is not None:
@@ -341,16 +332,16 @@ class ProtectBaseObject(BaseModel):
341
332
  cls._api if isinstance(cls, ProtectBaseObject) else None
342
333
  )
343
334
 
344
- # remap keys that will not be converted correctly by snake_case convert
345
- if (remaps := cls._get_unifi_remaps()) and (
346
- intersections := cls._get_unifi_remaps_set().intersection(data)
347
- ):
348
- for from_key in intersections:
349
- data[remaps[from_key]] = data.pop(from_key)
350
-
335
+ remaps = cls._get_unifi_remaps()
351
336
  # convert to snake_case and remove extra fields
352
337
  _fields = cls.__fields__
353
338
  for key in list(data):
339
+ if key in remaps:
340
+ # remap keys that will not be converted correctly by snake_case convert
341
+ remapped_key = remaps[key]
342
+ data[remapped_key] = data.pop(key)
343
+ key = remapped_key
344
+
354
345
  new_key = to_snake_case(key)
355
346
  data[new_key] = data.pop(key)
356
347
  key = new_key
@@ -363,36 +354,23 @@ class ProtectBaseObject(BaseModel):
363
354
  continue
364
355
  data[key] = convert_unifi_data(data[key], _fields[key])
365
356
 
366
- # clean child UFP objs
367
- data_set = set(data)
368
-
369
- if (unifi_objs := cls._get_protect_objs()) and (
370
- intersections := cls._get_protect_objs_set().intersection(data_set)
371
- ):
372
- for key in intersections:
373
- data[key] = cls._clean_protect_obj(data[key], unifi_objs[key], api)
357
+ if not data:
358
+ return data
374
359
 
375
- if (unifi_lists := cls._get_protect_lists()) and (
376
- intersections := cls._get_protect_lists_set().intersection(data_set)
377
- ):
378
- for key in intersections:
379
- if isinstance(data[key], list):
380
- data[key] = cls._clean_protect_obj_list(
381
- data[key],
382
- unifi_lists[key],
383
- api,
384
- )
385
-
386
- if (unifi_dicts := cls._get_protect_dicts()) and (
387
- intersections := cls._get_protect_dicts_set().intersection(data_set)
388
- ):
389
- for key in intersections:
390
- if isinstance(data[key], dict):
391
- data[key] = cls._clean_protect_obj_dict(
392
- data[key],
393
- unifi_dicts[key],
394
- api,
395
- )
360
+ # clean child UFP objs
361
+ unifi_objs = cls._get_protect_objs()
362
+ has_unifi_objs = bool(unifi_objs)
363
+ unifi_lists = cls._get_protect_lists()
364
+ has_unifi_lists = bool(unifi_lists)
365
+ unifi_dicts = cls._get_protect_dicts()
366
+ has_unifi_dicts = bool(unifi_dicts)
367
+ for key, value in data.items():
368
+ if has_unifi_objs and key in unifi_objs:
369
+ data[key] = cls._clean_protect_obj(value, unifi_objs[key], api)
370
+ elif has_unifi_lists and key in unifi_lists and isinstance(value, list):
371
+ data[key] = cls._clean_protect_obj_list(value, unifi_lists[key], api)
372
+ elif has_unifi_dicts and key in unifi_dicts and isinstance(value, dict):
373
+ data[key] = cls._clean_protect_obj_dict(value, unifi_dicts[key], api)
396
374
 
397
375
  return data
398
376
 
@@ -518,36 +496,27 @@ class ProtectBaseObject(BaseModel):
518
496
  api: ProtectApiClient | None,
519
497
  ) -> dict[str, Any]:
520
498
  data["api"] = api
521
- data_set = set(data)
522
-
523
- if (unifi_objs_sets := self._get_protect_objs_set()) and (
524
- intersections := unifi_objs_sets.intersection(data_set)
525
- ):
526
- for key in intersections:
527
- unifi_obj: Any | None = getattr(self, key)
528
- if unifi_obj is not None and isinstance(unifi_obj, dict):
529
- unifi_obj["api"] = api
530
-
531
- if (unifi_lists_sets := self._get_protect_lists_set()) and (
532
- intersections := unifi_lists_sets.intersection(data_set)
533
- ):
534
- for key in intersections:
535
- new_items = []
536
- for item in data[key]:
499
+ unifi_objs_sets = self._get_protect_objs_set()
500
+ has_unifi_objs = bool(unifi_objs_sets)
501
+ unifi_lists_sets = self._get_protect_lists_set()
502
+ has_unifi_lists = bool(unifi_lists_sets)
503
+ unifi_dicts_sets = self._get_protect_dicts_set()
504
+ has_unifi_dicts = bool(unifi_dicts_sets)
505
+ for key, value in data.items():
506
+ if has_unifi_objs and key in unifi_objs_sets and isinstance(value, dict):
507
+ value["api"] = api
508
+ elif (
509
+ has_unifi_lists and key in unifi_lists_sets and isinstance(value, list)
510
+ ):
511
+ for item in value:
537
512
  if isinstance(item, dict):
538
513
  item["api"] = api
539
- new_items.append(item)
540
- data[key] = new_items
541
-
542
- if (unifi_dicts_sets := self._get_protect_dicts_set()) and (
543
- intersections := unifi_dicts_sets.intersection(data_set)
544
- ):
545
- for key in intersections:
546
- inner_dict: dict[str, Any] = data[key]
547
- for item_key, item in inner_dict.items():
514
+ elif (
515
+ has_unifi_dicts and key in unifi_dicts_sets and isinstance(value, dict)
516
+ ):
517
+ for item in value.values():
548
518
  if isinstance(item, dict):
549
519
  item["api"] = api
550
- inner_dict[item_key] = item
551
520
 
552
521
  return data
553
522
 
@@ -304,7 +304,7 @@ class SmartDetectObjectType(str, ValuesEnumMixin, enum.Enum):
304
304
  CAR = "car"
305
305
  PET = "pet"
306
306
 
307
- @property
307
+ @cached_property
308
308
  def audio_type(self) -> SmartDetectAudioType | None:
309
309
  return OBJECT_TO_AUDIO_MAP.get(self)
310
310
 
File without changes
File without changes