uiprotect 0.4.1__py3-none-any.whl → 0.6.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 CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from uiprotect.api import ProtectApiClient
6
- from uiprotect.exceptions import Invalid, NotAuthorized, NvrError
5
+ from .api import ProtectApiClient
6
+ from .exceptions import Invalid, NotAuthorized, NvrError
7
7
 
8
8
  __all__ = [
9
9
  "Invalid",
uiprotect/__main__.py CHANGED
@@ -7,7 +7,7 @@ try:
7
7
  except ImportError:
8
8
  load_dotenv = None # type: ignore[assignment]
9
9
 
10
- from uiprotect.cli import app
10
+ from .cli import app
11
11
 
12
12
 
13
13
  def start() -> None:
uiprotect/api.py CHANGED
@@ -25,7 +25,7 @@ from aiohttp import CookieJar, client_exceptions
25
25
  from platformdirs import user_cache_dir, user_config_dir
26
26
  from yarl import URL
27
27
 
28
- from uiprotect.data import (
28
+ from .data import (
29
29
  NVR,
30
30
  Bootstrap,
31
31
  Bridge,
@@ -50,11 +50,11 @@ from uiprotect.data import (
50
50
  WSSubscriptionMessage,
51
51
  create_from_unifi_dict,
52
52
  )
53
- from uiprotect.data.base import ProtectModelWithId
54
- from uiprotect.data.devices import Chime
55
- from uiprotect.data.types import IteratorCallback, ProgressCallback, RecordingMode
56
- from uiprotect.exceptions import BadRequest, NotAuthorized, NvrError
57
- from uiprotect.utils import (
53
+ from .data.base import ProtectModelWithId
54
+ from .data.devices import Chime
55
+ from .data.types import IteratorCallback, ProgressCallback, RecordingMode
56
+ from .exceptions import BadRequest, NotAuthorized, NvrError
57
+ from .utils import (
58
58
  decode_token_cookie,
59
59
  get_response_reason,
60
60
  ip_from_host,
@@ -62,7 +62,7 @@ from uiprotect.utils import (
62
62
  to_js_time,
63
63
  utc_now,
64
64
  )
65
- from uiprotect.websocket import Websocket
65
+ from .websocket import Websocket
66
66
 
67
67
  TOKEN_COOKIE_MAX_EXP_SECONDS = 60
68
68
 
uiprotect/cli/__init__.py CHANGED
@@ -12,23 +12,24 @@ import typer
12
12
  from rich.progress import track
13
13
 
14
14
  from uiprotect.api import ProtectApiClient
15
- from uiprotect.cli.base import CliContext, OutputFormatEnum
16
- from uiprotect.cli.cameras import app as camera_app
17
- from uiprotect.cli.chimes import app as chime_app
18
- from uiprotect.cli.doorlocks import app as doorlock_app
19
- from uiprotect.cli.events import app as event_app
20
- from uiprotect.cli.lights import app as light_app
21
- from uiprotect.cli.liveviews import app as liveview_app
22
- from uiprotect.cli.nvr import app as nvr_app
23
- from uiprotect.cli.sensors import app as sensor_app
24
- from uiprotect.cli.viewers import app as viewer_app
25
- from uiprotect.data import Version, WSPacket
26
- from uiprotect.test_util import SampleDataGenerator
27
- from uiprotect.utils import RELEASE_CACHE, get_local_timezone, run_async
28
- from uiprotect.utils import profile_ws as profile_ws_job
15
+
16
+ from ..data import Version, WSPacket
17
+ from ..test_util import SampleDataGenerator
18
+ from ..utils import RELEASE_CACHE, get_local_timezone, run_async
19
+ from ..utils import profile_ws as profile_ws_job
20
+ from .base import CliContext, OutputFormatEnum
21
+ from .cameras import app as camera_app
22
+ from .chimes import app as chime_app
23
+ from .doorlocks import app as doorlock_app
24
+ from .events import app as event_app
25
+ from .lights import app as light_app
26
+ from .liveviews import app as liveview_app
27
+ from .nvr import app as nvr_app
28
+ from .sensors import app as sensor_app
29
+ from .viewers import app as viewer_app
29
30
 
30
31
  try:
31
- from uiprotect.cli.backup import app as backup_app
32
+ from .backup import app as backup_app
32
33
  except ImportError:
33
34
  backup_app = None # type: ignore[assignment]
34
35
 
uiprotect/cli/backup.py CHANGED
@@ -32,10 +32,10 @@ from sqlalchemy import event as saevent
32
32
  from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, create_async_engine
33
33
  from sqlalchemy.orm import Mapped, declarative_base, relationship
34
34
 
35
- from uiprotect import data as d
36
- from uiprotect.api import ProtectApiClient
37
- from uiprotect.cli import base
38
- from uiprotect.utils import (
35
+ from .. import data as d
36
+ from ..api import ProtectApiClient
37
+ from ..cli import base
38
+ from ..utils import (
39
39
  format_duration,
40
40
  get_local_timezone,
41
41
  local_datetime,
uiprotect/cli/base.py CHANGED
@@ -9,10 +9,10 @@ import orjson
9
9
  import typer
10
10
  from pydantic.v1 import ValidationError
11
11
 
12
- from uiprotect.api import ProtectApiClient
13
- from uiprotect.data import NVR, ProtectAdoptableDeviceModel, ProtectBaseObject
14
- from uiprotect.exceptions import BadRequest, NvrError, StreamError
15
- from uiprotect.utils import run_async
12
+ from ..api import ProtectApiClient
13
+ from ..data import NVR, ProtectAdoptableDeviceModel, ProtectBaseObject
14
+ from ..exceptions import BadRequest, NvrError, StreamError
15
+ from ..utils import run_async
16
16
 
17
17
  try:
18
18
  from pydantic.v1 import ValidationError
uiprotect/cli/cameras.py CHANGED
@@ -8,9 +8,9 @@ from typing import Optional, cast
8
8
  import typer
9
9
  from rich.progress import Progress
10
10
 
11
- from uiprotect import data as d
12
- from uiprotect.api import ProtectApiClient
13
- from uiprotect.cli import base
11
+ from .. import data as d
12
+ from ..api import ProtectApiClient
13
+ from ..cli import base
14
14
 
15
15
  app = typer.Typer(rich_markup_mode="rich")
16
16
 
uiprotect/cli/chimes.py CHANGED
@@ -5,9 +5,9 @@ from typing import Optional
5
5
 
6
6
  import typer
7
7
 
8
- from uiprotect.api import ProtectApiClient
9
- from uiprotect.cli import base
10
- from uiprotect.data import Chime
8
+ from ..api import ProtectApiClient
9
+ from ..cli import base
10
+ from ..data import Chime
11
11
 
12
12
  app = typer.Typer(rich_markup_mode="rich")
13
13
 
@@ -6,9 +6,9 @@ from typing import Optional
6
6
 
7
7
  import typer
8
8
 
9
- from uiprotect.api import ProtectApiClient
10
- from uiprotect.cli import base
11
- from uiprotect.data import Doorlock
9
+ from ..api import ProtectApiClient
10
+ from ..cli import base
11
+ from ..data import Doorlock
12
12
 
13
13
  app = typer.Typer(rich_markup_mode="rich")
14
14
 
uiprotect/cli/events.py CHANGED
@@ -9,11 +9,11 @@ from typing import Optional
9
9
  import typer
10
10
  from rich.progress import Progress
11
11
 
12
- from uiprotect import data as d
13
- from uiprotect.api import ProtectApiClient
14
- from uiprotect.cli import base
15
- from uiprotect.exceptions import NvrError
16
- from uiprotect.utils import local_datetime
12
+ from .. import data as d
13
+ from ..api import ProtectApiClient
14
+ from ..cli import base
15
+ from ..exceptions import NvrError
16
+ from ..utils import local_datetime
17
17
 
18
18
  app = typer.Typer(rich_markup_mode="rich")
19
19
 
uiprotect/cli/lights.py CHANGED
@@ -6,9 +6,9 @@ from typing import Optional
6
6
 
7
7
  import typer
8
8
 
9
- from uiprotect.api import ProtectApiClient
10
- from uiprotect.cli import base
11
- from uiprotect.data import Light
9
+ from ..api import ProtectApiClient
10
+ from ..cli import base
11
+ from ..data import Light
12
12
 
13
13
  app = typer.Typer(rich_markup_mode="rich")
14
14
 
@@ -5,9 +5,9 @@ from typing import Optional
5
5
 
6
6
  import typer
7
7
 
8
- from uiprotect.api import ProtectApiClient
9
- from uiprotect.cli import base
10
- from uiprotect.data import Liveview
8
+ from ..api import ProtectApiClient
9
+ from ..cli import base
10
+ from ..data import Liveview
11
11
 
12
12
  app = typer.Typer(rich_markup_mode="rich")
13
13
 
uiprotect/cli/nvr.py CHANGED
@@ -6,8 +6,8 @@ from datetime import timedelta
6
6
  import orjson
7
7
  import typer
8
8
 
9
- from uiprotect.cli import base
10
- from uiprotect.data import NVR, AnalyticsOption
9
+ from ..cli import base
10
+ from ..data import NVR, AnalyticsOption
11
11
 
12
12
  app = typer.Typer(rich_markup_mode="rich")
13
13
 
uiprotect/cli/sensors.py CHANGED
@@ -5,9 +5,9 @@ from typing import Optional
5
5
 
6
6
  import typer
7
7
 
8
- from uiprotect.api import ProtectApiClient
9
- from uiprotect.cli import base
10
- from uiprotect.data import MountType, Sensor
8
+ from ..api import ProtectApiClient
9
+ from ..cli import base
10
+ from ..data import MountType, Sensor
11
11
 
12
12
  app = typer.Typer(rich_markup_mode="rich")
13
13
 
uiprotect/cli/viewers.py CHANGED
@@ -5,9 +5,9 @@ from typing import Optional
5
5
 
6
6
  import typer
7
7
 
8
- from uiprotect.api import ProtectApiClient
9
- from uiprotect.cli import base
10
- from uiprotect.data import Viewer
8
+ from ..api import ProtectApiClient
9
+ from ..cli import base
10
+ from ..data import Viewer
11
11
 
12
12
  app = typer.Typer(rich_markup_mode="rich")
13
13
 
@@ -1,15 +1,15 @@
1
1
  from __future__ import annotations
2
2
 
3
- from uiprotect.data.base import (
3
+ from .base import (
4
4
  ProtectAdoptableDeviceModel,
5
5
  ProtectBaseObject,
6
6
  ProtectDeviceModel,
7
7
  ProtectModel,
8
8
  ProtectModelWithId,
9
9
  )
10
- from uiprotect.data.bootstrap import Bootstrap
11
- from uiprotect.data.convert import create_from_unifi_dict
12
- from uiprotect.data.devices import (
10
+ from .bootstrap import Bootstrap
11
+ from .convert import create_from_unifi_dict
12
+ from .devices import (
13
13
  Bridge,
14
14
  Camera,
15
15
  CameraChannel,
@@ -21,7 +21,7 @@ from uiprotect.data.devices import (
21
21
  Sensor,
22
22
  Viewer,
23
23
  )
24
- from uiprotect.data.nvr import (
24
+ from .nvr import (
25
25
  NVR,
26
26
  DoorbellMessage,
27
27
  Event,
@@ -30,7 +30,7 @@ from uiprotect.data.nvr import (
30
30
  SmartDetectItem,
31
31
  SmartDetectTrack,
32
32
  )
33
- from uiprotect.data.types import (
33
+ from .types import (
34
34
  DEFAULT,
35
35
  DEFAULT_TYPE,
36
36
  AnalyticsOption,
@@ -69,8 +69,8 @@ from uiprotect.data.types import (
69
69
  VideoMode,
70
70
  WDRLevel,
71
71
  )
72
- from uiprotect.data.user import CloudAccount, Group, Permission, User, UserLocation
73
- from uiprotect.data.websocket import (
72
+ from .user import CloudAccount, Group, Permission, User, UserLocation
73
+ from .websocket import (
74
74
  WS_HEADER_SIZE,
75
75
  WSAction,
76
76
  WSJSONPacketFrame,
uiprotect/data/base.py CHANGED
@@ -11,28 +11,28 @@ from ipaddress import IPv4Address
11
11
  from typing import TYPE_CHECKING, Any, ClassVar, TypeVar
12
12
  from uuid import UUID
13
13
 
14
- from uiprotect.data.types import (
14
+ from ..exceptions import BadRequest, ClientError, NotAuthorized
15
+ from ..utils import (
16
+ asyncio_timeout,
17
+ convert_unifi_data,
18
+ dict_diff,
19
+ is_debug,
20
+ process_datetime,
21
+ serialize_unifi_obj,
22
+ to_snake_case,
23
+ )
24
+ from .types import (
15
25
  ModelType,
16
26
  PercentFloat,
17
27
  PermissionNode,
18
28
  ProtectWSPayloadFormat,
19
29
  StateType,
20
30
  )
21
- from uiprotect.data.websocket import (
31
+ from .websocket import (
22
32
  WSJSONPacketFrame,
23
33
  WSPacket,
24
34
  WSPacketFrameHeader,
25
35
  )
26
- from uiprotect.exceptions import BadRequest, ClientError, NotAuthorized
27
- from uiprotect.utils import (
28
- asyncio_timeout,
29
- convert_unifi_data,
30
- dict_diff,
31
- is_debug,
32
- process_datetime,
33
- serialize_unifi_obj,
34
- to_snake_case,
35
- )
36
36
 
37
37
  try:
38
38
  from pydantic.v1 import BaseModel
@@ -50,10 +50,10 @@ if TYPE_CHECKING:
50
50
 
51
51
  from typing_extensions import Self # requires Python 3.11+
52
52
 
53
- from uiprotect.api import ProtectApiClient
54
- from uiprotect.data.devices import Bridge
55
- from uiprotect.data.nvr import Event
56
- from uiprotect.data.user import User
53
+ from ..api import ProtectApiClient
54
+ from ..data.devices import Bridge
55
+ from ..data.nvr import Event
56
+ from ..data.user import User
57
57
 
58
58
  try:
59
59
  from pydantic.v1.typing import DictStrAny, SetStr
@@ -140,7 +140,7 @@ class ProtectBaseObject(BaseModel):
140
140
 
141
141
  @classmethod
142
142
  def construct(cls, _fields_set: set[str] | None = None, **values: Any) -> Self:
143
- api = values.pop("api", None)
143
+ api: ProtectApiClient | None = values.pop("api", None)
144
144
  values_set = set(values)
145
145
 
146
146
  unifi_objs = cls._get_protect_objs()
@@ -281,14 +281,6 @@ class ProtectBaseObject(BaseModel):
281
281
 
282
282
  return cls._protect_dicts_set
283
283
 
284
- @classmethod
285
- def _get_api(cls, api: ProtectApiClient | None) -> ProtectApiClient | None:
286
- """Helper method to try to find and the current ProjtectAPIClient instance from given data"""
287
- if api is None and isinstance(cls, ProtectBaseObject) and hasattr(cls, "_api"): # type: ignore[unreachable]
288
- api = cls._api # type: ignore[unreachable]
289
-
290
- return api
291
-
292
284
  @classmethod
293
285
  def _clean_protect_obj(
294
286
  cls,
@@ -340,7 +332,9 @@ class ProtectBaseObject(BaseModel):
340
332
 
341
333
  """
342
334
  # get the API client instance
343
- api = cls._get_api(data.get("api"))
335
+ api: ProtectApiClient | None = data.get("api") or (
336
+ cls._api if isinstance(cls, ProtectBaseObject) else None
337
+ )
344
338
 
345
339
  # remap keys that will not be converted correctly by snake_case convert
346
340
  remaps = cls._get_unifi_remaps()
@@ -7,7 +7,7 @@ import logging
7
7
  from copy import deepcopy
8
8
  from dataclasses import dataclass
9
9
  from datetime import datetime
10
- from typing import Any, cast
10
+ from typing import TYPE_CHECKING, Any, cast
11
11
 
12
12
  from aiohttp.client_exceptions import ServerDisconnectedError
13
13
 
@@ -16,14 +16,16 @@ try:
16
16
  except ImportError:
17
17
  from pydantic import PrivateAttr, ValidationError # type: ignore[assignment]
18
18
 
19
- from uiprotect.data.base import (
19
+ from ..exceptions import ClientError
20
+ from ..utils import utc_now
21
+ from .base import (
20
22
  RECENT_EVENT_MAX,
21
23
  ProtectBaseObject,
22
24
  ProtectModel,
23
25
  ProtectModelWithId,
24
26
  )
25
- from uiprotect.data.convert import create_from_unifi_dict
26
- from uiprotect.data.devices import (
27
+ from .convert import create_from_unifi_dict
28
+ from .devices import (
27
29
  Bridge,
28
30
  Camera,
29
31
  Chime,
@@ -33,17 +35,19 @@ from uiprotect.data.devices import (
33
35
  Sensor,
34
36
  Viewer,
35
37
  )
36
- from uiprotect.data.nvr import NVR, Event, Liveview
37
- from uiprotect.data.types import EventType, FixSizeOrderedDict, ModelType
38
- from uiprotect.data.user import Group, User
39
- from uiprotect.data.websocket import (
38
+ from .nvr import NVR, Event, Liveview
39
+ from .types import EventType, FixSizeOrderedDict, ModelType
40
+ from .user import Group, User
41
+ from .websocket import (
40
42
  WSAction,
41
43
  WSJSONPacketFrame,
42
44
  WSPacket,
43
45
  WSSubscriptionMessage,
44
46
  )
45
- from uiprotect.exceptions import ClientError
46
- from uiprotect.utils import utc_now
47
+
48
+ if TYPE_CHECKING:
49
+ from ..api import ProtectApiClient
50
+
47
51
 
48
52
  _LOGGER = logging.getLogger(__name__)
49
53
 
@@ -198,7 +202,9 @@ class Bootstrap(ProtectBaseObject):
198
202
 
199
203
  @classmethod
200
204
  def unifi_dict_to_dict(cls, data: dict[str, Any]) -> dict[str, Any]:
201
- api = cls._get_api(data.get("api"))
205
+ api: ProtectApiClient | None = data.get("api") or (
206
+ cls._api if isinstance(cls, ProtectBaseObject) else None
207
+ )
202
208
  data["macLookup"] = {}
203
209
  data["idLookup"] = {}
204
210
  for model_type in ModelType.bootstrap_models():
uiprotect/data/convert.py CHANGED
@@ -4,7 +4,8 @@ from __future__ import annotations
4
4
 
5
5
  from typing import TYPE_CHECKING, Any
6
6
 
7
- from uiprotect.data.devices import (
7
+ from ..exceptions import DataDecodeError
8
+ from .devices import (
8
9
  Bridge,
9
10
  Camera,
10
11
  Chime,
@@ -13,14 +14,13 @@ from uiprotect.data.devices import (
13
14
  Sensor,
14
15
  Viewer,
15
16
  )
16
- from uiprotect.data.nvr import NVR, Event, Liveview
17
- from uiprotect.data.types import ModelType
18
- from uiprotect.data.user import CloudAccount, Group, User, UserLocation
19
- from uiprotect.exceptions import DataDecodeError
17
+ from .nvr import NVR, Event, Liveview
18
+ from .types import ModelType
19
+ from .user import CloudAccount, Group, User, UserLocation
20
20
 
21
21
  if TYPE_CHECKING:
22
- from uiprotect.api import ProtectApiClient
23
- from uiprotect.data.base import ProtectModel
22
+ from ..api import ProtectApiClient
23
+ from ..data.base import ProtectModel
24
24
 
25
25
 
26
26
  MODEL_TO_CLASS: dict[str, type[ProtectModel]] = {
uiprotect/data/devices.py CHANGED
@@ -17,13 +17,26 @@ try:
17
17
  except ImportError:
18
18
  from pydantic.fields import PrivateAttr
19
19
 
20
- from uiprotect.data.base import (
20
+ from ..exceptions import BadRequest, NotAuthorized, StreamError
21
+ from ..stream import TalkbackStream
22
+ from ..utils import (
23
+ clamp_value,
24
+ convert_smart_audio_types,
25
+ convert_smart_types,
26
+ convert_video_modes,
27
+ from_js_time,
28
+ process_datetime,
29
+ serialize_point,
30
+ to_js_time,
31
+ utc_now,
32
+ )
33
+ from .base import (
21
34
  EVENT_PING_INTERVAL,
22
35
  ProtectAdoptableDeviceModel,
23
36
  ProtectBaseObject,
24
37
  ProtectMotionDeviceModel,
25
38
  )
26
- from uiprotect.data.types import (
39
+ from .types import (
27
40
  DEFAULT,
28
41
  DEFAULT_TYPE,
29
42
  AudioCodecs,
@@ -65,23 +78,10 @@ from uiprotect.data.types import (
65
78
  VideoMode,
66
79
  WDRLevel,
67
80
  )
68
- from uiprotect.data.user import User
69
- from uiprotect.exceptions import BadRequest, NotAuthorized, StreamError
70
- from uiprotect.stream import TalkbackStream
71
- from uiprotect.utils import (
72
- clamp_value,
73
- convert_smart_audio_types,
74
- convert_smart_types,
75
- convert_video_modes,
76
- from_js_time,
77
- process_datetime,
78
- serialize_point,
79
- to_js_time,
80
- utc_now,
81
- )
81
+ from .user import User
82
82
 
83
83
  if TYPE_CHECKING:
84
- from uiprotect.data.nvr import Event, Liveview
84
+ from .nvr import Event, Liveview
85
85
 
86
86
  PRIVACY_ZONE_NAME = "pyufp_privacy_zone"
87
87
  LUX_MAPPING_VALUES = [
uiprotect/data/nvr.py CHANGED
@@ -16,12 +16,14 @@ import aiofiles
16
16
  import orjson
17
17
  from aiofiles import os as aos
18
18
 
19
- from uiprotect.data.base import (
19
+ from ..exceptions import BadRequest, NotAuthorized
20
+ from ..utils import RELEASE_CACHE, process_datetime
21
+ from .base import (
20
22
  ProtectBaseObject,
21
23
  ProtectDeviceModel,
22
24
  ProtectModelWithId,
23
25
  )
24
- from uiprotect.data.devices import (
26
+ from .devices import (
25
27
  Camera,
26
28
  CameraZone,
27
29
  Light,
@@ -30,7 +32,7 @@ from uiprotect.data.devices import (
30
32
  Sensor,
31
33
  SmartDetectSettings,
32
34
  )
33
- from uiprotect.data.types import (
35
+ from .types import (
34
36
  AnalyticsOption,
35
37
  DoorbellMessageType,
36
38
  DoorbellText,
@@ -53,9 +55,7 @@ from uiprotect.data.types import (
53
55
  StorageType,
54
56
  Version,
55
57
  )
56
- from uiprotect.data.user import User, UserLocation
57
- from uiprotect.exceptions import BadRequest, NotAuthorized
58
- from uiprotect.utils import RELEASE_CACHE, process_datetime
58
+ from .user import User, UserLocation
59
59
 
60
60
  try:
61
61
  from pydantic.v1.fields import PrivateAttr
uiprotect/data/user.py CHANGED
@@ -11,8 +11,8 @@ try:
11
11
  except ImportError:
12
12
  from pydantic.fields import PrivateAttr
13
13
 
14
- from uiprotect.data.base import ProtectBaseObject, ProtectModel, ProtectModelWithId
15
- from uiprotect.data.types import ModelType, PermissionNode
14
+ from .base import ProtectBaseObject, ProtectModel, ProtectModelWithId
15
+ from .types import ModelType, PermissionNode
16
16
 
17
17
 
18
18
  class Permission(ProtectBaseObject):
@@ -11,11 +11,11 @@ from typing import TYPE_CHECKING, Any
11
11
 
12
12
  import orjson
13
13
 
14
- from uiprotect.data.types import ProtectWSPayloadFormat
15
- from uiprotect.exceptions import WSDecodeError, WSEncodeError
14
+ from ..exceptions import WSDecodeError, WSEncodeError
15
+ from .types import ProtectWSPayloadFormat
16
16
 
17
17
  if TYPE_CHECKING:
18
- from uiprotect.data.base import ProtectModelWithId
18
+ from .base import ProtectModelWithId
19
19
 
20
20
  WS_HEADER_SIZE = 8
21
21
 
uiprotect/stream.py CHANGED
@@ -11,10 +11,10 @@ from urllib.parse import urlparse
11
11
 
12
12
  from aioshutil import which
13
13
 
14
- from uiprotect.exceptions import BadRequest, StreamError
14
+ from .exceptions import BadRequest, StreamError
15
15
 
16
16
  if TYPE_CHECKING:
17
- from uiprotect.data import Camera
17
+ from .data import Camera
18
18
 
19
19
  _LOGGER = logging.getLogger(__name__)
20
20
 
@@ -15,14 +15,14 @@ from typing import Any, overload
15
15
  import aiohttp
16
16
  from PIL import Image
17
17
 
18
- from uiprotect.api import ProtectApiClient
19
- from uiprotect.data import EventType, WSJSONPacketFrame, WSPacket
20
- from uiprotect.exceptions import BadRequest
21
- from uiprotect.test_util.anonymize import (
18
+ from ..api import ProtectApiClient
19
+ from ..data import EventType, WSJSONPacketFrame, WSPacket
20
+ from ..exceptions import BadRequest
21
+ from ..test_util.anonymize import (
22
22
  anonymize_data,
23
23
  anonymize_prefixed_event_id,
24
24
  )
25
- from uiprotect.utils import from_js_time, is_online, run_async, write_json
25
+ from ..utils import from_js_time, is_online, run_async, write_json
26
26
 
27
27
  BLANK_VIDEO_CMD = "ffmpeg -y -hide_banner -loglevel error -f lavfi -i color=size=1280x720:rate=25:color=black -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 -t {length} {filename}"
28
28
 
@@ -8,7 +8,7 @@ from urllib.parse import urlparse
8
8
 
9
9
  import typer
10
10
 
11
- from uiprotect.data import ModelType
11
+ from ..data import ModelType
12
12
 
13
13
  object_id_mapping: dict[str, str] = {}
14
14
 
uiprotect/utils.py CHANGED
@@ -29,14 +29,14 @@ from uuid import UUID
29
29
  import jwt
30
30
  from aiohttp import ClientResponse
31
31
 
32
- from uiprotect.data.types import (
32
+ from .data.types import (
33
33
  Color,
34
34
  SmartDetectAudioType,
35
35
  SmartDetectObjectType,
36
36
  Version,
37
37
  VideoMode,
38
38
  )
39
- from uiprotect.exceptions import NvrError
39
+ from .exceptions import NvrError
40
40
 
41
41
  try:
42
42
  from pydantic.v1.fields import SHAPE_DICT, SHAPE_LIST, SHAPE_SET, ModelField
@@ -234,11 +234,11 @@ def convert_unifi_data(value: Any, field: ModelField) -> Any:
234
234
  return value
235
235
  if type_ == datetime:
236
236
  return from_js_time(value)
237
- if type_ in _CREATE_TYPES or (isclass(type_) and issubclass(type_, Enum)):
237
+ if type_ in _CREATE_TYPES or _is_enum_type(type_):
238
238
  # cannot do this check too soon because some types cannot be used in isinstance
239
239
  if isinstance(value, type_):
240
240
  return value
241
- # handle edge case for improperly formated UUIDs
241
+ # handle edge case for improperly formatted UUIDs
242
242
  # 00000000-0000-00 0- 000-000000000000
243
243
  if type_ == UUID and value == _BAD_UUID:
244
244
  value = "0" * 32
@@ -247,6 +247,12 @@ def convert_unifi_data(value: Any, field: ModelField) -> Any:
247
247
  return value
248
248
 
249
249
 
250
+ @lru_cache
251
+ def _is_enum_type(type_: Any) -> bool:
252
+ """Checks if type is an Enum."""
253
+ return isclass(type_) and issubclass(type_, Enum)
254
+
255
+
250
256
  def serialize_unifi_obj(value: Any, levels: int = -1) -> Any:
251
257
  """Serializes UFP data"""
252
258
  if unifi_dict := getattr(value, "unifi_dict", None):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: uiprotect
3
- Version: 0.4.1
3
+ Version: 0.6.0
4
4
  Summary: Python API for Unifi Protect (Unofficial)
5
5
  Home-page: https://github.com/uilibs/uiprotect
6
6
  License: MIT
@@ -0,0 +1,37 @@
1
+ uiprotect/__init__.py,sha256=llnQNtiBfwQG8IkQXovvFz4LZeFjrJx7XdmmUhu3a9E,289
2
+ uiprotect/__main__.py,sha256=C_bHCOkv5qj6WMy-6ELoY3Y6HDhLxOa1a30CzmbZhsg,462
3
+ uiprotect/api.py,sha256=1eIAuA4GC32-mpibk-Avd4vU59fT_UgxqjKVP9ISTkY,65943
4
+ uiprotect/cli/__init__.py,sha256=sSLW9keVQOkgFcMW18HTDjRrt9sJ0KWjn9DJDA6f9Pc,8658
5
+ uiprotect/cli/backup.py,sha256=SxUyFFwLHcU60qsI8qBS_Xw7RLJeqUEdMAyjwk30MKw,36715
6
+ uiprotect/cli/base.py,sha256=zpTm2kyJe_GLixnv3Uadke__iRLh64AEwQzp-2hqS7g,7730
7
+ uiprotect/cli/cameras.py,sha256=YvvMccQEYG3Wih0Ix8tan1R1vfaJ6cogg6YKWLzMUV8,16973
8
+ uiprotect/cli/chimes.py,sha256=XANn21bQVkestkKOm9HjxSM8ZGrRrqvUXLouaQ3LTqs,5326
9
+ uiprotect/cli/doorlocks.py,sha256=Go_Tn68bAcmrRAnUIi4kBiR7ciKQsu_R150ubPTjUAs,3523
10
+ uiprotect/cli/events.py,sha256=D5SRejKzsPpKlZ9O2J4wkJRigFRVEymiLyU8VQ43fqI,7186
11
+ uiprotect/cli/lights.py,sha256=RxP1ebYEn2o5812OfrovmJLaNuIDoSNWiX1FvCbcdDw,3314
12
+ uiprotect/cli/liveviews.py,sha256=GU5z-ZLRBXHyspDKiJpiv-kbaBcvxK_-K70rPoqx2Ms,1863
13
+ uiprotect/cli/nvr.py,sha256=TwxEg2XT8jXAbOqv6gc7KFXELKadeItEDYweSL4_-e8,4260
14
+ uiprotect/cli/sensors.py,sha256=fQtcDJCVxs4VbAqcavgBy2ABiVxAW3GXtna6_XFBp2k,8153
15
+ uiprotect/cli/viewers.py,sha256=2cyrp104ffIvgT0wYGIO0G35QMkEbFe7fSVqLwDXQYQ,2171
16
+ uiprotect/data/__init__.py,sha256=OcfuJl2qXfHcj_mdnrHhzZ5tEIZrw8auziX5IE7dn-I,2938
17
+ uiprotect/data/base.py,sha256=esEXOzJt2xKOeYASwCcCotjeZLQEPiT08bnGzNv-k8c,37501
18
+ uiprotect/data/bootstrap.py,sha256=ibfCHqNhH44iw-JsuQs41zBCjb9ksSXz_QQq7qDbLsQ,21876
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
23
+ uiprotect/data/user.py,sha256=yBnUQ3qpHL745hLhR41WjWv_Yx51RlmfHapgvK0KSgM,7067
24
+ uiprotect/data/websocket.py,sha256=lkdobRh5SPu7YzLHyhZVe7qlh5W3L8LKzS63Md-4DOk,6048
25
+ uiprotect/exceptions.py,sha256=kgn0cRM6lTtgLza09SDa3ZiX6ue1QqHCOogQ4qu6KTQ,965
26
+ uiprotect/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
+ uiprotect/release_cache.json,sha256=NamnSFy78hOWY0DPO87J9ELFCAN6NnVquv8gQO75ZG4,386
28
+ uiprotect/stream.py,sha256=McV3XymKyjn-1uV5jdQHcpaDjqLS4zWyMASQ8ubcyb4,4924
29
+ uiprotect/test_util/__init__.py,sha256=d2g7afa0LSdixQ0kjEDYwafDFME_UlW2LzxpamZ2BC0,18556
30
+ uiprotect/test_util/anonymize.py,sha256=f-8ijU-_y9r-uAbhIPn0f0I6hzJpAkvJzc8UpWihObI,8478
31
+ uiprotect/utils.py,sha256=gCLoZBQ94Yi9PqefiqTZK7WrvT3Byue79a4jvDc0k44,18226
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,,
@@ -1,37 +0,0 @@
1
- uiprotect/__init__.py,sha256=tzcxK6cOIIkFEtST4Zjq3bafYTFWtwnaL92DgypjFi8,307
2
- uiprotect/__main__.py,sha256=T69KE5W4zek6qeNEL8_Fq2DEfBc04SqSuIOJpiW4ydE,471
3
- uiprotect/api.py,sha256=G2cvwLuanzvZ7dGfJOlAMvbKSBIsb7t3uOPB-KyT8gk,66006
4
- uiprotect/cli/__init__.py,sha256=tmwtYrhM8rjOw8noKD6NALl_2Nu3xIycDuQyEKD5oMk,8832
5
- uiprotect/cli/backup.py,sha256=Mtjd2f0w7zjIeLkJILKxiBnZJYXypzC9gpyAmBZ8sq0,36746
6
- uiprotect/cli/base.py,sha256=dE6vYb4nLAYbUdHwcKkN7I3iXqTjz84jfHGnsLmk_Ds,7762
7
- uiprotect/cli/cameras.py,sha256=mVLJ5FjZPSbpNXvtd7Yiz17zMDSdLWT0p6Wcaqpt0GQ,16996
8
- uiprotect/cli/chimes.py,sha256=92kNiZN7FpuCF7CqK9oLPt2jQ96tNhTjP1JcOdJAKhU,5350
9
- uiprotect/cli/doorlocks.py,sha256=XMftrrK0O0bWZHOuTwg9m4p9U7gC0FzHFb72bSnlUEg,3547
10
- uiprotect/cli/events.py,sha256=Ni_igTOdOf11pklpNEocBdwd3EW6O0wD8Iz-lN2zMJA,7225
11
- uiprotect/cli/lights.py,sha256=EgJsQ37c3QzSKoYf6h-rCaQoiftNh2igY1bTB_tQz14,3338
12
- uiprotect/cli/liveviews.py,sha256=TrLAqG2_GpNoWyw9IRY-4mJmlFwxGZxUuIdi-YU_NuM,1887
13
- uiprotect/cli/nvr.py,sha256=PVpUitWzP9HLy2yoj0HP-b-4Te5AFCrahUAmrQJ4z-w,4276
14
- uiprotect/cli/sensors.py,sha256=CE77weDkYepo9eEs1J0ModIs3pWNWmesjAq3rlmiez0,8177
15
- uiprotect/cli/viewers.py,sha256=SZlolZH3kkcWKjATrA37TCVZYRpF0t4cCccrC8vIv-M,2195
16
- uiprotect/data/__init__.py,sha256=38Kb1DVi4kv9FTTwugatPNSWLiIp6uvUlTMZRQp2jTY,3050
17
- uiprotect/data/base.py,sha256=YJ0iofoy1K3EG55npokU3T2CLRC8kctutfIy0Sq_6Sg,37850
18
- uiprotect/data/bootstrap.py,sha256=fyC6CoYnm90r1VAWSuOe8FFh8ULaGSv6jNMQcpKPBZA,21821
19
- uiprotect/data/convert.py,sha256=f8QkwZnlNbV_W-YognlDvZ1gQKp5yFuC50396hcu6DU,2127
20
- uiprotect/data/devices.py,sha256=3UOOzFXgJP7AOPKTE1SgPcLy37W4DmSNflIFiyi8tSE,111792
21
- uiprotect/data/nvr.py,sha256=JZja0QiT91Eu8-lw_M0Ora1KGNXhbG5dVNLN8YdeSw0,47677
22
- uiprotect/data/types.py,sha256=MTi9dVzKTp_8XtAmWKtbZujwE5plKGHdjglFGcJ4Yxs,15789
23
- uiprotect/data/user.py,sha256=HZJh9IOXS23kM-szTn7dGGsRZz9w2_9DqltL90gcMoE,7095
24
- uiprotect/data/websocket.py,sha256=3iU8hcH5GsVrGLoDjhXcv7zOKmXrMuQUqUud_ZsF6vw,6084
25
- uiprotect/exceptions.py,sha256=kgn0cRM6lTtgLza09SDa3ZiX6ue1QqHCOogQ4qu6KTQ,965
26
- uiprotect/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
- uiprotect/release_cache.json,sha256=NamnSFy78hOWY0DPO87J9ELFCAN6NnVquv8gQO75ZG4,386
28
- uiprotect/stream.py,sha256=V4aJfVWpSUsWE1PQrXH8F7obQQi1ukPAZ7PzwABjt0I,4942
29
- uiprotect/test_util/__init__.py,sha256=sSEXu6_pwdYNQSCYtftpX1Dy1S8XYOvhrpECYRxeKJE,18596
30
- uiprotect/test_util/anonymize.py,sha256=AGYELhDC4BrdK0deI6zh5jFp3SuM_HvAWLeoxFHSiwg,8486
31
- uiprotect/utils.py,sha256=xP8t0wEBIGS___LUYRNnQuXvUbjKDbsOnnSwWDzphSw,18124
32
- uiprotect/websocket.py,sha256=iMTdchymaCgVHsmY1bRbxkcymqt6WQircIHYNxCu178,7289
33
- uiprotect-0.4.1.dist-info/LICENSE,sha256=INx18jhdbVXMEiiBANeKEbrbz57ckgzxk5uutmmcxGk,1111
34
- uiprotect-0.4.1.dist-info/METADATA,sha256=EOocaNozRAuUHiD47vXbmqj_HzZfd5jK8zB6GhmP-Ew,10984
35
- uiprotect-0.4.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
36
- uiprotect-0.4.1.dist-info/entry_points.txt,sha256=J78AUTPrTTxgI3s7SVgrmGqDP7piX2wuuEORzhDdVRA,47
37
- uiprotect-0.4.1.dist-info/RECORD,,