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 +20 -17
- uiprotect/cli/backup.py +1 -1
- uiprotect/data/base.py +31 -35
- uiprotect/data/devices.py +1 -1
- uiprotect/data/nvr.py +5 -5
- uiprotect/data/types.py +1 -1
- uiprotect/utils.py +1 -1
- {uiprotect-0.6.0.dist-info → uiprotect-0.8.0.dist-info}/METADATA +1 -1
- {uiprotect-0.6.0.dist-info → uiprotect-0.8.0.dist-info}/RECORD +12 -12
- {uiprotect-0.6.0.dist-info → uiprotect-0.8.0.dist-info}/LICENSE +0 -0
- {uiprotect-0.6.0.dist-info → uiprotect-0.8.0.dist-info}/WHEEL +0 -0
- {uiprotect-0.6.0.dist-info → uiprotect-0.8.0.dist-info}/entry_points.txt +0 -0
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
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
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
|
|
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
|
|
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
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
cls.
|
|
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
|
-
|
|
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
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
cls.
|
|
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
|
-
|
|
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
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
cls.
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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"]
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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,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=
|
|
3
|
+
uiprotect/api.py,sha256=Ic6Jc4mO4okrGYxdXoHT85fqaNRfhYnoKt9yHUBxx-k,66102
|
|
4
4
|
uiprotect/cli/__init__.py,sha256=sSLW9keVQOkgFcMW18HTDjRrt9sJ0KWjn9DJDA6f9Pc,8658
|
|
5
|
-
uiprotect/cli/backup.py,sha256=
|
|
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=
|
|
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=
|
|
21
|
-
uiprotect/data/nvr.py,sha256=
|
|
22
|
-
uiprotect/data/types.py,sha256=
|
|
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=
|
|
31
|
+
uiprotect/utils.py,sha256=kXEr1xEoPAwUYuVPd6QoVnTf8MQwzQXQQ4JLyJsiRfY,18219
|
|
32
32
|
uiprotect/websocket.py,sha256=iMTdchymaCgVHsmY1bRbxkcymqt6WQircIHYNxCu178,7289
|
|
33
|
-
uiprotect-0.
|
|
34
|
-
uiprotect-0.
|
|
35
|
-
uiprotect-0.
|
|
36
|
-
uiprotect-0.
|
|
37
|
-
uiprotect-0.
|
|
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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|