uiprotect 3.4.0__tar.gz → 3.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-3.4.0 → uiprotect-3.6.0}/PKG-INFO +1 -1
  2. {uiprotect-3.4.0 → uiprotect-3.6.0}/pyproject.toml +1 -1
  3. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/data/base.py +2 -6
  4. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/data/devices.py +53 -65
  5. {uiprotect-3.4.0 → uiprotect-3.6.0}/LICENSE +0 -0
  6. {uiprotect-3.4.0 → uiprotect-3.6.0}/README.md +0 -0
  7. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/__init__.py +0 -0
  8. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/__main__.py +0 -0
  9. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/api.py +0 -0
  10. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/cli/__init__.py +0 -0
  11. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/cli/backup.py +0 -0
  12. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/cli/base.py +0 -0
  13. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/cli/cameras.py +0 -0
  14. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/cli/chimes.py +0 -0
  15. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/cli/doorlocks.py +0 -0
  16. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/cli/events.py +0 -0
  17. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/cli/lights.py +0 -0
  18. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/cli/liveviews.py +0 -0
  19. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/cli/nvr.py +0 -0
  20. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/cli/sensors.py +0 -0
  21. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/cli/viewers.py +0 -0
  22. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/data/__init__.py +0 -0
  23. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/data/bootstrap.py +0 -0
  24. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/data/convert.py +0 -0
  25. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/data/nvr.py +0 -0
  26. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/data/types.py +0 -0
  27. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/data/user.py +0 -0
  28. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/data/websocket.py +0 -0
  29. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/exceptions.py +0 -0
  30. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/py.typed +0 -0
  31. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/release_cache.json +0 -0
  32. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/stream.py +0 -0
  33. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/test_util/__init__.py +0 -0
  34. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/test_util/anonymize.py +0 -0
  35. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/utils.py +0 -0
  36. {uiprotect-3.4.0 → uiprotect-3.6.0}/src/uiprotect/websocket.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: uiprotect
3
- Version: 3.4.0
3
+ Version: 3.6.0
4
4
  Summary: Python API for Unifi Protect (Unofficial)
5
5
  Home-page: https://github.com/uilibs/uiprotect
6
6
  Author: UI Protect Maintainers
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "uiprotect"
3
- version = "3.4.0"
3
+ version = "3.6.0"
4
4
  description = "Python API for Unifi Protect (Unofficial)"
5
5
  authors = ["UI Protect Maintainers <ui@koston.org>"]
6
6
  readme = "README.md"
@@ -260,9 +260,7 @@ class ProtectBaseObject(BaseModel):
260
260
  klass: type[ProtectBaseObject],
261
261
  api: ProtectApiClient | None,
262
262
  ) -> list[Any]:
263
- for index, item in enumerate(items):
264
- items[index] = cls._clean_protect_obj(item, klass, api)
265
- return items
263
+ return [cls._clean_protect_obj(item, klass, api) for item in items]
266
264
 
267
265
  @classmethod
268
266
  def _clean_protect_obj_dict(
@@ -271,9 +269,7 @@ class ProtectBaseObject(BaseModel):
271
269
  klass: type[ProtectBaseObject],
272
270
  api: ProtectApiClient | None,
273
271
  ) -> dict[Any, Any]:
274
- for key, value in items.items():
275
- items[key] = cls._clean_protect_obj(value, klass, api)
276
- return items
272
+ return {k: cls._clean_protect_obj(v, klass, api) for k, v in items.items()}
277
273
 
278
274
  @classmethod
279
275
  @cache
@@ -1107,18 +1107,16 @@ class Camera(ProtectMotionDeviceModel):
1107
1107
 
1108
1108
  @property
1109
1109
  def last_ring_event(self) -> Event | None:
1110
- if self.last_ring_event_id is None:
1110
+ if (last_ring_event_id := self.last_ring_event_id) is None:
1111
1111
  return None
1112
-
1113
- return self._api.bootstrap.events.get(self.last_ring_event_id)
1112
+ return self._api.bootstrap.events.get(last_ring_event_id)
1114
1113
 
1115
1114
  @property
1116
1115
  def last_smart_detect_event(self) -> Event | None:
1117
1116
  """Get the last smart detect event id."""
1118
- if self.last_smart_detect_event_id is None:
1117
+ if (last_smart_detect_event_id := self.last_smart_detect_event_id) is None:
1119
1118
  return None
1120
-
1121
- return self._api.bootstrap.events.get(self.last_smart_detect_event_id)
1119
+ return self._api.bootstrap.events.get(last_smart_detect_event_id)
1122
1120
 
1123
1121
  @property
1124
1122
  def hdr_mode_display(self) -> Literal["auto", "off", "always"]:
@@ -1151,20 +1149,19 @@ class Camera(ProtectMotionDeviceModel):
1151
1149
  @property
1152
1150
  def last_smart_audio_detect_event(self) -> Event | None:
1153
1151
  """Get the last smart audio detect event id."""
1154
- if self.last_smart_audio_detect_event_id is None:
1152
+ if (
1153
+ last_smart_audio_detect_event_id := self.last_smart_audio_detect_event_id
1154
+ ) is None:
1155
1155
  return None
1156
-
1157
- return self._api.bootstrap.events.get(self.last_smart_audio_detect_event_id)
1156
+ return self._api.bootstrap.events.get(last_smart_audio_detect_event_id)
1158
1157
 
1159
1158
  def get_last_smart_audio_detect_event(
1160
1159
  self,
1161
1160
  smart_type: SmartDetectAudioType,
1162
1161
  ) -> Event | None:
1163
1162
  """Get the last smart audio detect event for given type."""
1164
- event_id = self.last_smart_audio_detect_event_ids.get(smart_type)
1165
- if event_id is None:
1163
+ if (event_id := self.last_smart_audio_detect_event_ids.get(smart_type)) is None:
1166
1164
  return None
1167
-
1168
1165
  return self._api.bootstrap.events.get(event_id)
1169
1166
 
1170
1167
  @property
@@ -1186,7 +1183,6 @@ class Camera(ProtectMotionDeviceModel):
1186
1183
  """
1187
1184
  if self.use_global:
1188
1185
  return self._api.bootstrap.nvr.is_global_recording_enabled
1189
-
1190
1186
  return self.recording_settings.mode is not RecordingMode.NEVER
1191
1187
 
1192
1188
  @property
@@ -1218,7 +1214,6 @@ class Camera(ProtectMotionDeviceModel):
1218
1214
  """Get active recording settings."""
1219
1215
  if self.use_global and self._api.bootstrap.nvr.global_camera_settings:
1220
1216
  return self._api.bootstrap.nvr.global_camera_settings.recording_settings
1221
-
1222
1217
  return self.recording_settings
1223
1218
 
1224
1219
  @property
@@ -1226,7 +1221,6 @@ class Camera(ProtectMotionDeviceModel):
1226
1221
  """Get active smart detection settings."""
1227
1222
  if self.use_global and self._api.bootstrap.nvr.global_camera_settings:
1228
1223
  return self._api.bootstrap.nvr.global_camera_settings.smart_detect_settings
1229
-
1230
1224
  return self.smart_detect_settings
1231
1225
 
1232
1226
  @property
@@ -1234,9 +1228,8 @@ class Camera(ProtectMotionDeviceModel):
1234
1228
  """Get active smart detection types."""
1235
1229
  if self.use_global:
1236
1230
  return set(self.smart_detect_settings.object_types).intersection(
1237
- set(self.feature_flags.smart_detect_types),
1231
+ self.feature_flags.smart_detect_types,
1238
1232
  )
1239
-
1240
1233
  return set(self.smart_detect_settings.object_types)
1241
1234
 
1242
1235
  @property
@@ -1244,7 +1237,7 @@ class Camera(ProtectMotionDeviceModel):
1244
1237
  """Get active audio detection types."""
1245
1238
  if self.use_global:
1246
1239
  return set(self.smart_detect_settings.audio_types or []).intersection(
1247
- set(self.feature_flags.smart_detect_audio_types or []),
1240
+ self.feature_flags.smart_detect_audio_types or [],
1248
1241
  )
1249
1242
 
1250
1243
  return set(self.smart_detect_settings.audio_types or [])
@@ -1504,8 +1497,11 @@ class Camera(ProtectMotionDeviceModel):
1504
1497
  audio_type = smart_type.audio_type
1505
1498
  return (
1506
1499
  audio_type is not None
1507
- and self.feature_flags.smart_detect_audio_types is not None
1508
- and audio_type in self.feature_flags.smart_detect_audio_types
1500
+ and (
1501
+ smart_detect_audio_types := self.feature_flags.smart_detect_audio_types
1502
+ )
1503
+ is not None
1504
+ and audio_type in smart_detect_audio_types
1509
1505
  )
1510
1506
 
1511
1507
  def _is_audio_enabled(self, smart_type: SmartDetectObjectType) -> bool:
@@ -1535,8 +1531,9 @@ class Camera(ProtectMotionDeviceModel):
1535
1531
  return (
1536
1532
  self.is_recording_enabled
1537
1533
  and bool(self.active_audio_detect_types)
1538
- and self.last_smart_audio_detect_event is not None
1539
- and self.last_smart_audio_detect_event.end is None
1534
+ and (last_smart_audio_detect_event := self.last_smart_audio_detect_event)
1535
+ is not None
1536
+ and last_smart_audio_detect_event.end is None
1540
1537
  )
1541
1538
 
1542
1539
  # region Smoke Alarm
@@ -1903,28 +1900,25 @@ class Camera(ProtectMotionDeviceModel):
1903
1900
 
1904
1901
  @property
1905
1902
  def is_high_fps_enabled(self) -> bool:
1906
- return self.video_mode == VideoMode.HIGH_FPS
1903
+ return self.video_mode is VideoMode.HIGH_FPS
1907
1904
 
1908
1905
  @property
1909
1906
  def is_video_ready(self) -> bool:
1910
1907
  return (
1911
- self.feature_flags.lens_type is None
1912
- or self.feature_flags.lens_type != LensType.NONE
1913
- )
1908
+ lens_type := self.feature_flags.lens_type
1909
+ ) is None or lens_type is not LensType.NONE
1914
1910
 
1915
1911
  @property
1916
1912
  def has_removable_lens(self) -> bool:
1917
1913
  return (
1918
- self.feature_flags.hotplug is not None
1919
- and self.feature_flags.hotplug.video is not None
1920
- )
1914
+ hotplug := self.feature_flags.hotplug
1915
+ ) is not None and hotplug.video is not None
1921
1916
 
1922
1917
  @property
1923
1918
  def has_removable_speaker(self) -> bool:
1924
1919
  return (
1925
- self.feature_flags.hotplug is not None
1926
- and self.feature_flags.hotplug.audio is not None
1927
- )
1920
+ hotplug := self.feature_flags.hotplug
1921
+ ) is not None and hotplug.audio is not None
1928
1922
 
1929
1923
  @property
1930
1924
  def has_mic(self) -> bool:
@@ -1933,11 +1927,11 @@ class Camera(ProtectMotionDeviceModel):
1933
1927
  @property
1934
1928
  def has_color_night_vision(self) -> bool:
1935
1929
  if (
1936
- self.feature_flags.hotplug is not None
1937
- and self.feature_flags.hotplug.extender is not None
1938
- and self.feature_flags.hotplug.extender.is_attached is not None
1930
+ (hotplug := self.feature_flags.hotplug) is not None
1931
+ and (extender := hotplug.extender) is not None
1932
+ and (is_attached := extender.is_attached) is not None
1939
1933
  ):
1940
- return self.feature_flags.hotplug.extender.is_attached
1934
+ return is_attached
1941
1935
 
1942
1936
  return False
1943
1937
 
@@ -1955,14 +1949,14 @@ class Camera(ProtectMotionDeviceModel):
1955
1949
  index, _ = self.get_privacy_zone()
1956
1950
  if index is None:
1957
1951
  zone_id = 0
1958
- if len(self.privacy_zones) > 0:
1959
- zone_id = self.privacy_zones[-1].id + 1
1952
+ privacy_zones = self.privacy_zones
1953
+ if len(privacy_zones) > 0:
1954
+ zone_id = privacy_zones[-1].id + 1
1960
1955
 
1961
- self.privacy_zones.append(CameraZone.create_privacy_zone(zone_id))
1956
+ privacy_zones.append(CameraZone.create_privacy_zone(zone_id))
1962
1957
 
1963
1958
  def remove_privacy_zone(self) -> None:
1964
1959
  index, _ = self.get_privacy_zone()
1965
-
1966
1960
  if index is not None:
1967
1961
  self.privacy_zones.pop(index)
1968
1962
 
@@ -2521,22 +2515,18 @@ class Camera(ProtectMotionDeviceModel):
2521
2515
 
2522
2516
  async def stop_audio(self) -> None:
2523
2517
  """Stop currently playing audio."""
2524
- stream = self.talkback_stream
2525
- if stream is None:
2518
+ if (stream := self.talkback_stream) is None:
2526
2519
  raise StreamError("No audio playing to stop")
2527
-
2528
2520
  await stream.stop()
2529
2521
 
2530
2522
  def can_read_media(self, user: User) -> bool:
2531
2523
  if self.model is None:
2532
2524
  return True
2533
-
2534
2525
  return user.can(self.model, PermissionNode.READ_MEDIA, self)
2535
2526
 
2536
2527
  def can_delete_media(self, user: User) -> bool:
2537
2528
  if self.model is None:
2538
2529
  return True
2539
-
2540
2530
  return user.can(self.model, PermissionNode.DELETE_MEDIA, self)
2541
2531
 
2542
2532
  # region PTZ
@@ -2818,10 +2808,9 @@ class Sensor(ProtectAdoptableDeviceModel):
2818
2808
  @property
2819
2809
  def camera(self) -> Camera | None:
2820
2810
  """Paired Camera will always be none if no camera is paired"""
2821
- if self.camera_id is None:
2811
+ if (camera_id := self.camera_id) is None:
2822
2812
  return None
2823
-
2824
- return self._api.bootstrap.cameras[self.camera_id]
2813
+ return self._api.bootstrap.cameras[camera_id]
2825
2814
 
2826
2815
  @property
2827
2816
  def is_tampering_detected(self) -> bool:
@@ -2839,25 +2828,28 @@ class Sensor(ProtectAdoptableDeviceModel):
2839
2828
 
2840
2829
  @property
2841
2830
  def is_motion_sensor_enabled(self) -> bool:
2842
- return self.mount_type != MountType.LEAK and self.motion_settings.is_enabled
2831
+ return self.mount_type is not MountType.LEAK and self.motion_settings.is_enabled
2843
2832
 
2844
2833
  @property
2845
2834
  def is_alarm_sensor_enabled(self) -> bool:
2846
- return self.mount_type != MountType.LEAK and self.alarm_settings.is_enabled
2835
+ return self.mount_type is not MountType.LEAK and self.alarm_settings.is_enabled
2847
2836
 
2848
2837
  @property
2849
2838
  def is_light_sensor_enabled(self) -> bool:
2850
- return self.mount_type != MountType.LEAK and self.light_settings.is_enabled
2839
+ return self.mount_type is not MountType.LEAK and self.light_settings.is_enabled
2851
2840
 
2852
2841
  @property
2853
2842
  def is_temperature_sensor_enabled(self) -> bool:
2854
2843
  return (
2855
- self.mount_type != MountType.LEAK and self.temperature_settings.is_enabled
2844
+ self.mount_type is not MountType.LEAK
2845
+ and self.temperature_settings.is_enabled
2856
2846
  )
2857
2847
 
2858
2848
  @property
2859
2849
  def is_humidity_sensor_enabled(self) -> bool:
2860
- return self.mount_type != MountType.LEAK and self.humidity_settings.is_enabled
2850
+ return (
2851
+ self.mount_type is not MountType.LEAK and self.humidity_settings.is_enabled
2852
+ )
2861
2853
 
2862
2854
  @property
2863
2855
  def is_leak_sensor_enabled(self) -> bool:
@@ -2869,31 +2861,27 @@ class Sensor(ProtectAdoptableDeviceModel):
2869
2861
 
2870
2862
  @property
2871
2863
  def last_motion_event(self) -> Event | None:
2872
- if self.last_motion_event_id is None:
2864
+ if (last_motion_event_id := self.last_motion_event_id) is None:
2873
2865
  return None
2874
-
2875
- return self._api.bootstrap.events.get(self.last_motion_event_id)
2866
+ return self._api.bootstrap.events.get(last_motion_event_id)
2876
2867
 
2877
2868
  @property
2878
2869
  def last_contact_event(self) -> Event | None:
2879
- if self.last_contact_event_id is None:
2870
+ if (last_contact_event_id := self.last_contact_event_id) is None:
2880
2871
  return None
2881
-
2882
- return self._api.bootstrap.events.get(self.last_contact_event_id)
2872
+ return self._api.bootstrap.events.get(last_contact_event_id)
2883
2873
 
2884
2874
  @property
2885
2875
  def last_value_event(self) -> Event | None:
2886
- if self.last_value_event_id is None:
2876
+ if (last_value_event_id := self.last_value_event_id) is None:
2887
2877
  return None
2888
-
2889
- return self._api.bootstrap.events.get(self.last_value_event_id)
2878
+ return self._api.bootstrap.events.get(last_value_event_id)
2890
2879
 
2891
2880
  @property
2892
2881
  def last_alarm_event(self) -> Event | None:
2893
- if self.last_alarm_event_id is None:
2882
+ if (last_alarm_event_id := self.last_alarm_event_id) is None:
2894
2883
  return None
2895
-
2896
- return self._api.bootstrap.events.get(self.last_alarm_event_id)
2884
+ return self._api.bootstrap.events.get(last_alarm_event_id)
2897
2885
 
2898
2886
  @property
2899
2887
  def is_leak_detected(self) -> bool:
File without changes
File without changes