uiprotect 1.19.3__py3-none-any.whl → 1.20.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/__init__.py +16 -0
- uiprotect/utils.py +56 -1
- {uiprotect-1.19.3.dist-info → uiprotect-1.20.0.dist-info}/METADATA +1 -1
- {uiprotect-1.19.3.dist-info → uiprotect-1.20.0.dist-info}/RECORD +7 -7
- {uiprotect-1.19.3.dist-info → uiprotect-1.20.0.dist-info}/LICENSE +0 -0
- {uiprotect-1.19.3.dist-info → uiprotect-1.20.0.dist-info}/WHEEL +0 -0
- {uiprotect-1.19.3.dist-info → uiprotect-1.20.0.dist-info}/entry_points.txt +0 -0
uiprotect/__init__.py
CHANGED
|
@@ -4,10 +4,26 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from .api import ProtectApiClient
|
|
6
6
|
from .exceptions import Invalid, NotAuthorized, NvrError
|
|
7
|
+
from .utils import (
|
|
8
|
+
get_nested_attr,
|
|
9
|
+
get_nested_attr_as_bool,
|
|
10
|
+
get_top_level_attr,
|
|
11
|
+
get_top_level_attr_as_bool,
|
|
12
|
+
make_enabled_getter,
|
|
13
|
+
make_required_getter,
|
|
14
|
+
make_value_getter,
|
|
15
|
+
)
|
|
7
16
|
|
|
8
17
|
__all__ = [
|
|
9
18
|
"Invalid",
|
|
10
19
|
"NotAuthorized",
|
|
11
20
|
"NvrError",
|
|
12
21
|
"ProtectApiClient",
|
|
22
|
+
"get_nested_attr",
|
|
23
|
+
"get_nested_attr_as_bool",
|
|
24
|
+
"get_top_level_attr",
|
|
25
|
+
"get_top_level_attr_as_bool",
|
|
26
|
+
"make_value_getter",
|
|
27
|
+
"make_enabled_getter",
|
|
28
|
+
"make_required_getter",
|
|
13
29
|
]
|
uiprotect/utils.py
CHANGED
|
@@ -17,11 +17,12 @@ from copy import deepcopy
|
|
|
17
17
|
from datetime import datetime, timedelta, timezone, tzinfo
|
|
18
18
|
from decimal import Decimal
|
|
19
19
|
from enum import Enum
|
|
20
|
-
from functools import cache, lru_cache
|
|
20
|
+
from functools import cache, lru_cache, partial
|
|
21
21
|
from hashlib import sha224
|
|
22
22
|
from http.cookies import Morsel
|
|
23
23
|
from inspect import isclass
|
|
24
24
|
from ipaddress import IPv4Address, IPv6Address, ip_address
|
|
25
|
+
from operator import attrgetter
|
|
25
26
|
from pathlib import Path
|
|
26
27
|
from typing import TYPE_CHECKING, Any, TypeVar, Union, overload
|
|
27
28
|
from uuid import UUID
|
|
@@ -619,3 +620,57 @@ def clamp_value(value: float, step_size: float) -> float:
|
|
|
619
620
|
def normalize_mac(mac: str) -> str:
|
|
620
621
|
"""Normalize MAC address."""
|
|
621
622
|
return mac.lower().replace(":", "").replace("-", "").replace("_", "")
|
|
623
|
+
|
|
624
|
+
|
|
625
|
+
_SENTINEL = object()
|
|
626
|
+
|
|
627
|
+
|
|
628
|
+
def get_nested_attr(attrs: tuple[str, ...], obj: Any) -> Any:
|
|
629
|
+
"""Fetch a nested attribute."""
|
|
630
|
+
value = obj
|
|
631
|
+
for key in attrs:
|
|
632
|
+
if (value := getattr(value, key, _SENTINEL)) is _SENTINEL:
|
|
633
|
+
return None
|
|
634
|
+
return value.value if isinstance(value, Enum) else value
|
|
635
|
+
|
|
636
|
+
|
|
637
|
+
def get_nested_attr_as_bool(attrs: tuple[str, ...], obj: Any) -> bool:
|
|
638
|
+
"""Fetch a nested attribute as a bool."""
|
|
639
|
+
value = obj
|
|
640
|
+
for key in attrs:
|
|
641
|
+
if (value := getattr(value, key, _SENTINEL)) is _SENTINEL:
|
|
642
|
+
return False
|
|
643
|
+
return bool(value.value if isinstance(value, Enum) else value)
|
|
644
|
+
|
|
645
|
+
|
|
646
|
+
def get_top_level_attr(attr: str, obj: Any) -> Any:
|
|
647
|
+
"""Fetch a top level attribute."""
|
|
648
|
+
value = getattr(obj, attr)
|
|
649
|
+
return value.value if isinstance(value, Enum) else value
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
def get_top_level_attr_as_bool(attr: str, obj: Any) -> Any:
|
|
653
|
+
"""Fetch a top level attribute as a bool."""
|
|
654
|
+
value = getattr(obj, attr)
|
|
655
|
+
return bool(value.value if isinstance(value, Enum) else value)
|
|
656
|
+
|
|
657
|
+
|
|
658
|
+
def make_value_getter(ufp_value: str) -> Callable[[T], Any]:
|
|
659
|
+
"""Return a function to get a value from a Protect device."""
|
|
660
|
+
if "." not in ufp_value:
|
|
661
|
+
return partial(get_top_level_attr, ufp_value)
|
|
662
|
+
return partial(get_nested_attr, tuple(ufp_value.split(".")))
|
|
663
|
+
|
|
664
|
+
|
|
665
|
+
def make_enabled_getter(ufp_enabled: str) -> Callable[[T], bool]:
|
|
666
|
+
"""Return a function to get a value from a Protect device."""
|
|
667
|
+
if "." not in ufp_enabled:
|
|
668
|
+
return attrgetter(ufp_enabled)
|
|
669
|
+
return partial(get_nested_attr, tuple(ufp_enabled.split(".")))
|
|
670
|
+
|
|
671
|
+
|
|
672
|
+
def make_required_getter(ufp_required_field: str) -> Callable[[T], bool]:
|
|
673
|
+
"""Return a function to get a value from a Protect device."""
|
|
674
|
+
if "." not in ufp_required_field:
|
|
675
|
+
return partial(get_top_level_attr_as_bool, ufp_required_field)
|
|
676
|
+
return partial(get_nested_attr_as_bool, tuple(ufp_required_field.split(".")))
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
uiprotect/__init__.py,sha256=
|
|
1
|
+
uiprotect/__init__.py,sha256=UdpRSSLSy7pdDfTKf0zRIfy6KRGt_Jv-fMzYWgibbG4,686
|
|
2
2
|
uiprotect/__main__.py,sha256=C_bHCOkv5qj6WMy-6ELoY3Y6HDhLxOa1a30CzmbZhsg,462
|
|
3
3
|
uiprotect/api.py,sha256=SvAni2arXGtP8HzvTljKNLclSfzpRL03RaEF8o1o6K4,65561
|
|
4
4
|
uiprotect/cli/__init__.py,sha256=sSLW9keVQOkgFcMW18HTDjRrt9sJ0KWjn9DJDA6f9Pc,8658
|
|
@@ -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=3SJFF8qs1Jz8t3mD8qwc1hFSocolFjdXI_v4yVlC7o4,20088
|
|
32
32
|
uiprotect/websocket.py,sha256=JHI_2EZeRPqPyQopsBZS0dr3tu0HaTiqeLazfBXhW_8,7339
|
|
33
|
-
uiprotect-1.
|
|
34
|
-
uiprotect-1.
|
|
35
|
-
uiprotect-1.
|
|
36
|
-
uiprotect-1.
|
|
37
|
-
uiprotect-1.
|
|
33
|
+
uiprotect-1.20.0.dist-info/LICENSE,sha256=INx18jhdbVXMEiiBANeKEbrbz57ckgzxk5uutmmcxGk,1111
|
|
34
|
+
uiprotect-1.20.0.dist-info/METADATA,sha256=2tR-i6s0-c1E1PzpEfVbFq9V9jA2RjilNdhywYM9NW0,10983
|
|
35
|
+
uiprotect-1.20.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
36
|
+
uiprotect-1.20.0.dist-info/entry_points.txt,sha256=J78AUTPrTTxgI3s7SVgrmGqDP7piX2wuuEORzhDdVRA,47
|
|
37
|
+
uiprotect-1.20.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|