uiprotect 0.6.0__py3-none-any.whl → 0.8.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/api.py CHANGED
@@ -818,23 +818,26 @@ class ProtectApiClient(BaseApiClient):
818
818
  return self._bootstrap
819
819
 
820
820
  def emit_message(self, msg: WSSubscriptionMessage) -> None:
821
- if msg.new_obj is not None:
822
- _LOGGER.debug(
823
- "emitting message: %s:%s:%s:%s",
824
- msg.action,
825
- msg.new_obj.model,
826
- msg.new_obj.id,
827
- list(msg.changed_data.keys()),
828
- )
829
- elif msg.old_obj is not None:
830
- _LOGGER.debug(
831
- "emitting message: %s:%s:%s",
832
- msg.action,
833
- msg.old_obj.model,
834
- msg.old_obj.id,
835
- )
836
- else:
837
- _LOGGER.debug("emitting message: %s", msg.action)
821
+ """Emit message to all subscriptions."""
822
+ if _LOGGER.isEnabledFor(logging.DEBUG):
823
+ if msg.new_obj is not None:
824
+ _LOGGER.debug(
825
+ "emitting message: %s:%s:%s:%s",
826
+ msg.action,
827
+ msg.new_obj.model,
828
+ msg.new_obj.id,
829
+ list(msg.changed_data),
830
+ )
831
+ elif msg.old_obj is not None:
832
+ _LOGGER.debug(
833
+ "emitting message: %s:%s:%s",
834
+ msg.action,
835
+ msg.old_obj.model,
836
+ msg.old_obj.id,
837
+ )
838
+ else:
839
+ _LOGGER.debug("emitting message: %s", msg.action)
840
+
838
841
  for sub in self._ws_subscriptions:
839
842
  try:
840
843
  sub(msg)
uiprotect/cli/backup.py CHANGED
@@ -814,7 +814,7 @@ def _add_metadata(path: Path, creation: datetime, title: str) -> bool:
814
814
  in_to_out[stream] = output_file.add_stream(template=stream) # type: ignore[index]
815
815
  in_to_out[stream].metadata["creation_time"] = creation.isoformat() # type: ignore[index]
816
816
 
817
- for packet in input_file.demux(list(in_to_out.keys())):
817
+ for packet in input_file.demux(list(in_to_out)):
818
818
  if packet.dts is None:
819
819
  continue
820
820
 
uiprotect/data/base.py CHANGED
@@ -56,11 +56,10 @@ if TYPE_CHECKING:
56
56
  from ..data.user import User
57
57
 
58
58
  try:
59
- from pydantic.v1.typing import DictStrAny, SetStr
59
+ from pydantic.v1.typing import DictStrAny
60
60
  except ImportError:
61
61
  from pydantic.typing import ( # type: ignore[assignment, no-redef]
62
62
  DictStrAny,
63
- SetStr,
64
63
  )
65
64
 
66
65
 
@@ -88,11 +87,8 @@ class ProtectBaseObject(BaseModel):
88
87
  _api: ProtectApiClient | None = PrivateAttr(None)
89
88
 
90
89
  _protect_objs: ClassVar[dict[str, type[ProtectBaseObject]] | None] = None
91
- _protect_objs_set: ClassVar[SetStr | None] = None
92
90
  _protect_lists: ClassVar[dict[str, type[ProtectBaseObject]] | None] = None
93
- _protect_lists_set: ClassVar[SetStr | None] = None
94
91
  _protect_dicts: ClassVar[dict[str, type[ProtectBaseObject]] | None] = None
95
- _protect_dicts_set: ClassVar[SetStr | None] = None
96
92
  _to_unifi_remaps: ClassVar[DictStrAny | None] = None
97
93
 
98
94
  class Config:
@@ -192,6 +188,12 @@ class ProtectBaseObject(BaseModel):
192
188
  """
193
189
  return {}
194
190
 
191
+ @classmethod
192
+ @cache
193
+ def _get_unifi_remaps_set(self) -> set[str]:
194
+ """Helper method to get set of all child UFP objects."""
195
+ return set(self._get_unifi_remaps())
196
+
195
197
  @classmethod
196
198
  def _get_to_unifi_remaps(cls) -> dict[str, str]:
197
199
  """
@@ -231,55 +233,49 @@ class ProtectBaseObject(BaseModel):
231
233
  pass
232
234
 
233
235
  @classmethod
236
+ @cache
234
237
  def _get_protect_objs(cls) -> dict[str, type[ProtectBaseObject]]:
235
238
  """Helper method to get all child UFP objects"""
236
- if cls._protect_objs is not None:
237
- return cls._protect_objs
238
-
239
- cls._set_protect_subtypes()
240
- return cls._protect_objs # type: ignore[return-value]
239
+ if cls._protect_objs is None:
240
+ cls._set_protect_subtypes()
241
+ assert cls._protect_objs is not None
242
+ return cls._protect_objs
241
243
 
242
244
  @classmethod
245
+ @cache
243
246
  def _get_protect_objs_set(cls) -> set[str]:
244
247
  """Helper method to get all child UFP objects"""
245
- if cls._protect_objs_set is None:
246
- cls._protect_objs_set = set(cls._get_protect_objs().keys())
247
-
248
- return cls._protect_objs_set
248
+ return set(cls._get_protect_objs())
249
249
 
250
250
  @classmethod
251
+ @cache
251
252
  def _get_protect_lists(cls) -> dict[str, type[ProtectBaseObject]]:
252
253
  """Helper method to get all child of UFP objects (lists)"""
253
- if cls._protect_lists is not None:
254
- return cls._protect_lists
255
-
256
- cls._set_protect_subtypes()
257
- return cls._protect_lists # type: ignore[return-value]
254
+ if cls._protect_lists is None:
255
+ cls._set_protect_subtypes()
256
+ assert cls._protect_lists is not None
257
+ return cls._protect_lists
258
258
 
259
259
  @classmethod
260
+ @cache
260
261
  def _get_protect_lists_set(cls) -> set[str]:
261
262
  """Helper method to get all child UFP objects"""
262
- if cls._protect_lists_set is None:
263
- cls._protect_lists_set = set(cls._get_protect_lists().keys())
264
-
265
- return cls._protect_lists_set
263
+ return set(cls._get_protect_lists())
266
264
 
267
265
  @classmethod
266
+ @cache
268
267
  def _get_protect_dicts(cls) -> dict[str, type[ProtectBaseObject]]:
269
268
  """Helper method to get all child of UFP objects (dicts)"""
270
- if cls._protect_dicts is not None:
271
- return cls._protect_dicts
272
-
273
- cls._set_protect_subtypes()
274
- return cls._protect_dicts # type: ignore[return-value]
269
+ if cls._protect_dicts is None:
270
+ cls._set_protect_subtypes()
271
+ assert cls._protect_dicts is not None
272
+ return cls._protect_dicts
275
273
 
276
274
  @classmethod
275
+ @cache
277
276
  def _get_protect_dicts_set(cls) -> set[str]:
278
277
  """Helper method to get all child UFP objects"""
279
- if cls._protect_dicts_set is None:
280
- cls._protect_dicts_set = set(cls._get_protect_dicts().keys())
281
-
282
- return cls._protect_dicts_set
278
+ return set(cls._get_protect_dicts())
283
279
 
284
280
  @classmethod
285
281
  def _clean_protect_obj(
@@ -338,11 +334,11 @@ class ProtectBaseObject(BaseModel):
338
334
 
339
335
  # remap keys that will not be converted correctly by snake_case convert
340
336
  remaps = cls._get_unifi_remaps()
341
- for from_key in set(remaps).intersection(data):
337
+ for from_key in cls._get_unifi_remaps_set().intersection(data):
342
338
  data[remaps[from_key]] = data.pop(from_key)
343
339
 
344
340
  # convert to snake_case and remove extra fields
345
- for key in list(data.keys()):
341
+ for key in list(data):
346
342
  new_key = to_snake_case(key)
347
343
  data[new_key] = data.pop(key)
348
344
  key = new_key
@@ -769,7 +765,7 @@ class ProtectModelWithId(ProtectModel):
769
765
  if updated == {}:
770
766
  return
771
767
 
772
- read_only_keys = read_only_fields.intersection(updated.keys())
768
+ read_only_keys = read_only_fields.intersection(updated)
773
769
  if len(read_only_keys) > 0:
774
770
  self.revert_changes(data_before_changes)
775
771
  raise BadRequest(
uiprotect/data/devices.py CHANGED
@@ -1034,7 +1034,7 @@ class Camera(ProtectMotionDeviceModel):
1034
1034
  @classmethod
1035
1035
  def unifi_dict_to_dict(cls, data: dict[str, Any]) -> dict[str, Any]:
1036
1036
  # LCD messages comes back as empty dict {}
1037
- if "lcdMessage" in data and len(data["lcdMessage"].keys()) == 0:
1037
+ if "lcdMessage" in data and len(data["lcdMessage"]) == 0:
1038
1038
  del data["lcdMessage"]
1039
1039
  if "chimeDuration" in data and not isinstance(data["chimeDuration"], timedelta):
1040
1040
  data["chimeDuration"] = timedelta(milliseconds=data["chimeDuration"])
uiprotect/data/nvr.py CHANGED
@@ -152,7 +152,7 @@ class EventThumbnailAttributes(ProtectBaseObject):
152
152
  ) -> dict[str, Any]:
153
153
  data = super().unifi_dict(data=data, exclude=exclude)
154
154
 
155
- for key in DELETE_KEYS_THUMB.intersection(data.keys()):
155
+ for key in DELETE_KEYS_THUMB.intersection(data):
156
156
  if data[key] is None:
157
157
  del data[key]
158
158
 
@@ -240,7 +240,7 @@ class EventMetadata(ProtectBaseObject):
240
240
 
241
241
  @classmethod
242
242
  def unifi_dict_to_dict(cls, data: dict[str, Any]) -> dict[str, Any]:
243
- for key in cls._collapse_keys.intersection(data.keys()):
243
+ for key in cls._collapse_keys.intersection(data):
244
244
  if isinstance(data[key], dict):
245
245
  data[key] = data[key]["text"]
246
246
 
@@ -258,7 +258,7 @@ class EventMetadata(ProtectBaseObject):
258
258
  if value is None:
259
259
  del data[key]
260
260
 
261
- for key in self._collapse_keys.intersection(data.keys()):
261
+ for key in self._collapse_keys.intersection(data):
262
262
  # AI Theta/Hotplug exception
263
263
  if key != "type" or data[key] not in {"audio", "video", "extender"}:
264
264
  data[key] = {"text": data[key]}
@@ -308,7 +308,7 @@ class Event(ProtectModelWithId):
308
308
 
309
309
  @classmethod
310
310
  def unifi_dict_to_dict(cls, data: dict[str, Any]) -> dict[str, Any]:
311
- for key in {"start", "end", "timestamp", "deletedAt"}.intersection(data.keys()):
311
+ for key in {"start", "end", "timestamp", "deletedAt"}.intersection(data):
312
312
  data[key] = process_datetime(data, key)
313
313
 
314
314
  return super().unifi_dict_to_dict(data)
@@ -320,7 +320,7 @@ class Event(ProtectModelWithId):
320
320
  ) -> dict[str, Any]:
321
321
  data = super().unifi_dict(data=data, exclude=exclude)
322
322
 
323
- for key in DELETE_KEYS_EVENT.intersection(data.keys()):
323
+ for key in DELETE_KEYS_EVENT.intersection(data):
324
324
  if data[key] is None:
325
325
  del data[key]
326
326
 
uiprotect/data/types.py CHANGED
@@ -50,7 +50,7 @@ class FixSizeOrderedDict(dict[KT, VT]):
50
50
  """Set an update up to the max size."""
51
51
  dict.__setitem__(self, key, value)
52
52
  if self._max_size > 0 and len(self) > 0 and len(self) > self._max_size:
53
- del self[next(iter(self.keys()))]
53
+ del self[next(iter(self))]
54
54
 
55
55
 
56
56
  class ValuesEnumMixin:
uiprotect/utils.py CHANGED
@@ -278,7 +278,7 @@ def serialize_unifi_obj(value: Any, levels: int = -1) -> Any:
278
278
 
279
279
  def serialize_dict(data: dict[str, Any], levels: int = -1) -> dict[str, Any]:
280
280
  """Serializes UFP data dict"""
281
- for key in list(data.keys()):
281
+ for key in list(data):
282
282
  set_key = key
283
283
  if set_key not in SNAKE_CASE_KEYS:
284
284
  set_key = to_camel_case(set_key)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: uiprotect
3
- Version: 0.6.0
3
+ Version: 0.8.0
4
4
  Summary: Python API for Unifi Protect (Unofficial)
5
5
  Home-page: https://github.com/uilibs/uiprotect
6
6
  License: MIT
@@ -1,8 +1,8 @@
1
1
  uiprotect/__init__.py,sha256=llnQNtiBfwQG8IkQXovvFz4LZeFjrJx7XdmmUhu3a9E,289
2
2
  uiprotect/__main__.py,sha256=C_bHCOkv5qj6WMy-6ELoY3Y6HDhLxOa1a30CzmbZhsg,462
3
- uiprotect/api.py,sha256=1eIAuA4GC32-mpibk-Avd4vU59fT_UgxqjKVP9ISTkY,65943
3
+ uiprotect/api.py,sha256=Ic6Jc4mO4okrGYxdXoHT85fqaNRfhYnoKt9yHUBxx-k,66102
4
4
  uiprotect/cli/__init__.py,sha256=sSLW9keVQOkgFcMW18HTDjRrt9sJ0KWjn9DJDA6f9Pc,8658
5
- uiprotect/cli/backup.py,sha256=SxUyFFwLHcU60qsI8qBS_Xw7RLJeqUEdMAyjwk30MKw,36715
5
+ uiprotect/cli/backup.py,sha256=ZiS7RZnJGKI8TJKLW2cOUzkRM8nyTvE5Ov_jZZGtvSM,36708
6
6
  uiprotect/cli/base.py,sha256=zpTm2kyJe_GLixnv3Uadke__iRLh64AEwQzp-2hqS7g,7730
7
7
  uiprotect/cli/cameras.py,sha256=YvvMccQEYG3Wih0Ix8tan1R1vfaJ6cogg6YKWLzMUV8,16973
8
8
  uiprotect/cli/chimes.py,sha256=XANn21bQVkestkKOm9HjxSM8ZGrRrqvUXLouaQ3LTqs,5326
@@ -14,12 +14,12 @@ 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=esEXOzJt2xKOeYASwCcCotjeZLQEPiT08bnGzNv-k8c,37501
17
+ uiprotect/data/base.py,sha256=ex-UC9CJUtzxMFqtYokSiXM8pNHVBqCzq7r8WrEf1Mw,37178
18
18
  uiprotect/data/bootstrap.py,sha256=ibfCHqNhH44iw-JsuQs41zBCjb9ksSXz_QQq7qDbLsQ,21876
19
19
  uiprotect/data/convert.py,sha256=rOQplUMIdTMD2SbAx_iI9BNPDscnhDvyRVLEMDhtADg,2047
20
- uiprotect/data/devices.py,sha256=AsCQCoOpswdIU7X5ty1XhhOl2v6CkQCXu2Y-lIS_6_k,111712
21
- uiprotect/data/nvr.py,sha256=c8WxXpBcMaZ5REzCUb8aqmlLkttFYO1O5jLMhus5rkw,47605
22
- uiprotect/data/types.py,sha256=MTi9dVzKTp_8XtAmWKtbZujwE5plKGHdjglFGcJ4Yxs,15789
20
+ uiprotect/data/devices.py,sha256=LHVBT8ihMAZen7gIlQNbiYxukRrBpi_TNKNmV_5R6Xc,111705
21
+ uiprotect/data/nvr.py,sha256=OJso6oewA_jY7ovKbD2U2Onp1GqheT5bCW0F6dC53DQ,47570
22
+ uiprotect/data/types.py,sha256=1I5Tu7W0KkS4Y30CuTJJS8jn4KDvDsapVr5ybX7d_zY,15782
23
23
  uiprotect/data/user.py,sha256=yBnUQ3qpHL745hLhR41WjWv_Yx51RlmfHapgvK0KSgM,7067
24
24
  uiprotect/data/websocket.py,sha256=lkdobRh5SPu7YzLHyhZVe7qlh5W3L8LKzS63Md-4DOk,6048
25
25
  uiprotect/exceptions.py,sha256=kgn0cRM6lTtgLza09SDa3ZiX6ue1QqHCOogQ4qu6KTQ,965
@@ -28,10 +28,10 @@ uiprotect/release_cache.json,sha256=NamnSFy78hOWY0DPO87J9ELFCAN6NnVquv8gQO75ZG4,
28
28
  uiprotect/stream.py,sha256=McV3XymKyjn-1uV5jdQHcpaDjqLS4zWyMASQ8ubcyb4,4924
29
29
  uiprotect/test_util/__init__.py,sha256=d2g7afa0LSdixQ0kjEDYwafDFME_UlW2LzxpamZ2BC0,18556
30
30
  uiprotect/test_util/anonymize.py,sha256=f-8ijU-_y9r-uAbhIPn0f0I6hzJpAkvJzc8UpWihObI,8478
31
- uiprotect/utils.py,sha256=gCLoZBQ94Yi9PqefiqTZK7WrvT3Byue79a4jvDc0k44,18226
31
+ uiprotect/utils.py,sha256=kXEr1xEoPAwUYuVPd6QoVnTf8MQwzQXQQ4JLyJsiRfY,18219
32
32
  uiprotect/websocket.py,sha256=iMTdchymaCgVHsmY1bRbxkcymqt6WQircIHYNxCu178,7289
33
- uiprotect-0.6.0.dist-info/LICENSE,sha256=INx18jhdbVXMEiiBANeKEbrbz57ckgzxk5uutmmcxGk,1111
34
- uiprotect-0.6.0.dist-info/METADATA,sha256=bWI_c91BlR_JzCp3RhTjbiTUVR-adQJH61fNBqZt5fE,10984
35
- uiprotect-0.6.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
36
- uiprotect-0.6.0.dist-info/entry_points.txt,sha256=J78AUTPrTTxgI3s7SVgrmGqDP7piX2wuuEORzhDdVRA,47
37
- uiprotect-0.6.0.dist-info/RECORD,,
33
+ uiprotect-0.8.0.dist-info/LICENSE,sha256=INx18jhdbVXMEiiBANeKEbrbz57ckgzxk5uutmmcxGk,1111
34
+ uiprotect-0.8.0.dist-info/METADATA,sha256=jPp4COkfIkBfuy1zdZKO1WpfKfJPLuU9bHwT726PoFE,10984
35
+ uiprotect-0.8.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
36
+ uiprotect-0.8.0.dist-info/entry_points.txt,sha256=J78AUTPrTTxgI3s7SVgrmGqDP7piX2wuuEORzhDdVRA,47
37
+ uiprotect-0.8.0.dist-info/RECORD,,