uiprotect 1.1.0__tar.gz → 1.2.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.1.0 → uiprotect-1.2.1}/PKG-INFO +1 -1
  2. {uiprotect-1.1.0 → uiprotect-1.2.1}/pyproject.toml +1 -1
  3. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/data/base.py +87 -62
  4. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/data/nvr.py +9 -10
  5. {uiprotect-1.1.0 → uiprotect-1.2.1}/LICENSE +0 -0
  6. {uiprotect-1.1.0 → uiprotect-1.2.1}/README.md +0 -0
  7. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/__init__.py +0 -0
  8. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/__main__.py +0 -0
  9. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/api.py +0 -0
  10. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/cli/__init__.py +0 -0
  11. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/cli/backup.py +0 -0
  12. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/cli/base.py +0 -0
  13. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/cli/cameras.py +0 -0
  14. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/cli/chimes.py +0 -0
  15. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/cli/doorlocks.py +0 -0
  16. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/cli/events.py +0 -0
  17. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/cli/lights.py +0 -0
  18. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/cli/liveviews.py +0 -0
  19. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/cli/nvr.py +0 -0
  20. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/cli/sensors.py +0 -0
  21. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/cli/viewers.py +0 -0
  22. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/data/__init__.py +0 -0
  23. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/data/bootstrap.py +0 -0
  24. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/data/convert.py +0 -0
  25. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/data/devices.py +0 -0
  26. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/data/types.py +0 -0
  27. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/data/user.py +0 -0
  28. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/data/websocket.py +0 -0
  29. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/exceptions.py +0 -0
  30. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/py.typed +0 -0
  31. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/release_cache.json +0 -0
  32. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/stream.py +0 -0
  33. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/test_util/__init__.py +0 -0
  34. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/test_util/anonymize.py +0 -0
  35. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/utils.py +0 -0
  36. {uiprotect-1.1.0 → uiprotect-1.2.1}/src/uiprotect/websocket.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: uiprotect
3
- Version: 1.1.0
3
+ Version: 1.2.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.1.0"
3
+ version = "1.2.1"
4
4
  description = "Python API for Unifi Protect (Unofficial)"
5
5
  authors = ["UI Protect Maintainers <ui@koston.org>"]
6
6
  license = "MIT"
@@ -141,26 +141,32 @@ class ProtectBaseObject(BaseModel):
141
141
  api: ProtectApiClient | None = values.pop("api", None)
142
142
  values_set = set(values)
143
143
 
144
- unifi_objs = cls._get_protect_objs()
145
- for key in cls._get_protect_objs_set().intersection(values_set):
146
- if isinstance(values[key], dict):
147
- values[key] = unifi_objs[key].construct(**values[key])
148
-
149
- unifi_lists = cls._get_protect_lists()
150
- for key in cls._get_protect_lists_set().intersection(values_set):
151
- if isinstance(values[key], list):
152
- values[key] = [
153
- unifi_lists[key].construct(**v) if isinstance(v, dict) else v
154
- for v in values[key]
155
- ]
156
-
157
- unifi_dicts = cls._get_protect_dicts()
158
- for key in cls._get_protect_dicts_set().intersection(values_set):
159
- if isinstance(values[key], dict):
160
- values[key] = {
161
- k: unifi_dicts[key].construct(**v) if isinstance(v, dict) else v
162
- for k, v in values[key].items()
163
- }
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
+ }
164
170
 
165
171
  obj = super().construct(_fields_set=_fields_set, **values)
166
172
  if api is not None:
@@ -336,11 +342,14 @@ class ProtectBaseObject(BaseModel):
336
342
  )
337
343
 
338
344
  # remap keys that will not be converted correctly by snake_case convert
339
- remaps = cls._get_unifi_remaps()
340
- for from_key in cls._get_unifi_remaps_set().intersection(data):
341
- data[remaps[from_key]] = data.pop(from_key)
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)
342
350
 
343
351
  # convert to snake_case and remove extra fields
352
+ _fields = cls.__fields__
344
353
  for key in list(data):
345
354
  new_key = to_snake_case(key)
346
355
  data[new_key] = data.pop(key)
@@ -349,35 +358,41 @@ class ProtectBaseObject(BaseModel):
349
358
  if key == "api":
350
359
  continue
351
360
 
352
- if key not in cls.__fields__:
361
+ if key not in _fields:
353
362
  del data[key]
354
363
  continue
355
- data[key] = convert_unifi_data(data[key], cls.__fields__[key])
364
+ data[key] = convert_unifi_data(data[key], _fields[key])
356
365
 
357
366
  # clean child UFP objs
358
367
  data_set = set(data)
359
368
 
360
- unifi_objs = cls._get_protect_objs()
361
- for key in cls._get_protect_objs_set().intersection(data_set):
362
- data[key] = cls._clean_protect_obj(data[key], unifi_objs[key], api)
363
-
364
- unifi_lists = cls._get_protect_lists()
365
- for key in cls._get_protect_lists_set().intersection(data_set):
366
- if isinstance(data[key], list):
367
- data[key] = cls._clean_protect_obj_list(
368
- data[key],
369
- unifi_lists[key],
370
- api,
371
- )
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)
372
374
 
373
- unifi_dicts = cls._get_protect_dicts()
374
- for key in cls._get_protect_dicts_set().intersection(data_set):
375
- if isinstance(data[key], dict):
376
- data[key] = cls._clean_protect_obj_dict(
377
- data[key],
378
- unifi_dicts[key],
379
- api,
380
- )
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
+ )
381
396
 
382
397
  return data
383
398
 
@@ -505,24 +520,34 @@ class ProtectBaseObject(BaseModel):
505
520
  data["api"] = api
506
521
  data_set = set(data)
507
522
 
508
- for key in self._get_protect_objs_set().intersection(data_set):
509
- unifi_obj: Any | None = getattr(self, key)
510
- if unifi_obj is not None and isinstance(unifi_obj, dict):
511
- unifi_obj["api"] = api
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
512
530
 
513
- for key in self._get_protect_lists_set().intersection(data_set):
514
- new_items = []
515
- for item in data[key]:
516
- if isinstance(item, dict):
517
- item["api"] = api
518
- new_items.append(item)
519
- data[key] = new_items
520
-
521
- for key in self._get_protect_dicts_set().intersection(data_set):
522
- for item_key, item in data[key].items():
523
- if isinstance(item, dict):
524
- item["api"] = api
525
- data[key][item_key] = item
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]:
537
+ if isinstance(item, dict):
538
+ 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():
548
+ if isinstance(item, dict):
549
+ item["api"] = api
550
+ inner_dict[item_key] = item
526
551
 
527
552
  return data
528
553
 
@@ -1198,16 +1198,15 @@ class NVR(ProtectDeviceModel):
1198
1198
 
1199
1199
  async def _read_cache_file(self, file_path: Path) -> set[Version] | None:
1200
1200
  versions: set[Version] | None = None
1201
-
1202
- if file_path.is_file():
1203
- try:
1204
- _LOGGER.debug("Reading release cache file: %s", file_path)
1205
- async with aiofiles.open(file_path, "rb") as cache_file:
1206
- versions = {
1207
- Version(v) for v in orjson.loads(await cache_file.read())
1208
- }
1209
- except Exception:
1210
- _LOGGER.warning("Failed to parse cache file: %s", file_path)
1201
+ try:
1202
+ _LOGGER.debug("Reading release cache file: %s", file_path)
1203
+ async with aiofiles.open(file_path, "rb") as cache_file:
1204
+ versions = {Version(v) for v in orjson.loads(await cache_file.read())}
1205
+ except FileNotFoundError:
1206
+ # ignore missing file
1207
+ pass
1208
+ except Exception:
1209
+ _LOGGER.warning("Failed to parse cache file: %s", file_path)
1211
1210
 
1212
1211
  return versions
1213
1212
 
File without changes
File without changes