splight-lib 2.3.20__tar.gz → 3.0.0.dev0__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.
- {splight-lib-2.3.20/splight_lib.egg-info → splight-lib-3.0.0.dev0}/PKG-INFO +1 -1
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/setup.py +1 -1
- splight-lib-3.0.0.dev0/splight_lib/abstract/__init__.py +0 -0
- splight-lib-2.3.20/splight_abstract/client/abstract.py → splight-lib-3.0.0.dev0/splight_lib/abstract/client.py +12 -41
- splight-lib-3.0.0.dev0/splight_lib/client/__init__.py +0 -0
- {splight-lib-2.3.20/splight_abstract → splight-lib-3.0.0.dev0/splight_lib/client}/communication/abstract.py +3 -10
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/client/communication/classmap.py +2 -1
- splight-lib-3.0.0.dev0/splight_lib/client/communication/local_client.py +7 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/client/communication/remote_client.py +36 -16
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/client/database/__init__.py +2 -0
- splight-lib-3.0.0.dev0/splight_lib/client/database/abstract.py +28 -0
- splight-lib-3.0.0.dev0/splight_lib/client/database/builder.py +17 -0
- splight-lib-3.0.0.dev0/splight_lib/client/database/classmap.py +18 -0
- splight-lib-3.0.0.dev0/splight_lib/client/database/local_client.py +185 -0
- splight-lib-3.0.0.dev0/splight_lib/client/database/remote_client.py +267 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/client/datalake/__init__.py +2 -0
- splight-lib-3.0.0.dev0/splight_lib/client/datalake/abstract.py +65 -0
- splight-lib-3.0.0.dev0/splight_lib/client/datalake/builder.py +17 -0
- splight-lib-3.0.0.dev0/splight_lib/client/datalake/local_client.py +162 -0
- splight-lib-3.0.0.dev0/splight_lib/client/datalake/remote_client.py +179 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/client/exceptions.py +1 -1
- {splight-lib-2.3.20/splight_abstract → splight-lib-3.0.0.dev0/splight_lib/client}/hub/abstract.py +16 -7
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/client/hub/client.py +8 -15
- splight-lib-3.0.0.dev0/splight_lib/communication/__init__.py +0 -0
- splight-lib-3.0.0.dev0/splight_lib/communication/event_handler.py +171 -0
- splight-lib-3.0.0.dev0/splight_lib/component/__init__.py +5 -0
- splight-lib-3.0.0.dev0/splight_lib/component/abstract.py +260 -0
- splight-lib-3.0.0.dev0/splight_lib/component/exceptions.py +36 -0
- splight-lib-3.0.0.dev0/splight_lib/component/spec.py +232 -0
- splight-lib-3.0.0.dev0/splight_lib/constants.py +1 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/execution.py +1 -1
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/logging/_internal.py +0 -1
- splight-lib-3.0.0.dev0/splight_lib/models/__init__.py +33 -0
- splight-lib-3.0.0.dev0/splight_lib/models/alert.py +55 -0
- splight-lib-3.0.0.dev0/splight_lib/models/asset.py +41 -0
- splight-lib-3.0.0.dev0/splight_lib/models/attribute.py +8 -0
- splight-lib-3.0.0.dev0/splight_lib/models/base.py +160 -0
- splight-lib-2.3.20/splight_models/communication/context.py → splight-lib-3.0.0.dev0/splight_lib/models/communication.py +9 -10
- splight-lib-3.0.0.dev0/splight_lib/models/component.py +327 -0
- splight-lib-3.0.0.dev0/splight_lib/models/event.py +119 -0
- splight-lib-3.0.0.dev0/splight_lib/models/exceptions.py +14 -0
- {splight-lib-2.3.20/splight_models → splight-lib-3.0.0.dev0/splight_lib/models}/file.py +16 -4
- {splight-lib-2.3.20/splight_models → splight-lib-3.0.0.dev0/splight_lib/models}/hub.py +2 -3
- splight-lib-2.3.20/splight_models/variable.py → splight-lib-3.0.0.dev0/splight_lib/models/native.py +6 -10
- {splight-lib-2.3.20/splight_models → splight-lib-3.0.0.dev0/splight_lib/models}/query.py +3 -3
- {splight-lib-2.3.20/splight_models → splight-lib-3.0.0.dev0/splight_lib/models}/secret.py +2 -4
- splight-lib-3.0.0.dev0/splight_lib/models/setpoint.py +67 -0
- splight-lib-3.0.0.dev0/splight_lib/settings.py +63 -0
- splight-lib-3.0.0.dev0/splight_lib/utils/__init__.py +0 -0
- splight-lib-3.0.0.dev0/splight_lib/utils/custom_model.py +75 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0/splight_lib.egg-info}/PKG-INFO +1 -1
- splight-lib-3.0.0.dev0/splight_lib.egg-info/SOURCES.txt +76 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib.egg-info/requires.txt +1 -0
- splight-lib-3.0.0.dev0/splight_lib.egg-info/top_level.txt +1 -0
- splight-lib-2.3.20/splight_abstract/__init__.py +0 -11
- splight-lib-2.3.20/splight_abstract/auth/__init__.py +0 -2
- splight-lib-2.3.20/splight_abstract/auth/abstract.py +0 -41
- splight-lib-2.3.20/splight_abstract/auth/exceptions.py +0 -20
- splight-lib-2.3.20/splight_abstract/cache/__init__.py +0 -1
- splight-lib-2.3.20/splight_abstract/cache/abstract.py +0 -130
- splight-lib-2.3.20/splight_abstract/client/__init__.py +0 -3
- splight-lib-2.3.20/splight_abstract/client/filter.py +0 -98
- splight-lib-2.3.20/splight_abstract/client/hooks.py +0 -70
- splight-lib-2.3.20/splight_abstract/communication/__init__.py +0 -2
- splight-lib-2.3.20/splight_abstract/database/__init__.py +0 -1
- splight-lib-2.3.20/splight_abstract/database/abstract.py +0 -39
- splight-lib-2.3.20/splight_abstract/datalake/__init__.py +0 -1
- splight-lib-2.3.20/splight_abstract/datalake/abstract.py +0 -103
- splight-lib-2.3.20/splight_abstract/deployment/__init__.py +0 -1
- splight-lib-2.3.20/splight_abstract/deployment/abstract.py +0 -39
- splight-lib-2.3.20/splight_abstract/endpoints/__init__.py +0 -76
- splight-lib-2.3.20/splight_abstract/hub/__init__.py +0 -1
- splight-lib-2.3.20/splight_abstract/notification/__init__.py +0 -2
- splight-lib-2.3.20/splight_abstract/notification/abstract.py +0 -10
- splight-lib-2.3.20/splight_abstract/remote/__init__.py +0 -1
- splight-lib-2.3.20/splight_abstract/remote/abstract.py +0 -13
- splight-lib-2.3.20/splight_abstract/storage/__init__.py +0 -1
- splight-lib-2.3.20/splight_abstract/storage/abstract.py +0 -44
- splight-lib-2.3.20/splight_lib/__init__.py +0 -3
- splight-lib-2.3.20/splight_lib/client/communication/local_client.py +0 -6
- splight-lib-2.3.20/splight_lib/client/database/classmap.py +0 -33
- splight-lib-2.3.20/splight_lib/client/database/local_client.py +0 -175
- splight-lib-2.3.20/splight_lib/client/database/remote_client.py +0 -224
- splight-lib-2.3.20/splight_lib/client/datalake/local_client.py +0 -194
- splight-lib-2.3.20/splight_lib/client/datalake/remote_client.py +0 -261
- splight-lib-2.3.20/splight_lib/client/settings.py +0 -18
- splight-lib-2.3.20/splight_lib/component/__init__.py +0 -5
- splight-lib-2.3.20/splight_lib/component/abstract.py +0 -766
- splight-lib-2.3.20/splight_lib/settings.py +0 -179
- splight-lib-2.3.20/splight_lib.egg-info/SOURCES.txt +0 -101
- splight-lib-2.3.20/splight_lib.egg-info/top_level.txt +0 -3
- splight-lib-2.3.20/splight_models/__init__.py +0 -20
- splight-lib-2.3.20/splight_models/alert.py +0 -84
- splight-lib-2.3.20/splight_models/asset.py +0 -20
- splight-lib-2.3.20/splight_models/attribute.py +0 -8
- splight-lib-2.3.20/splight_models/base.py +0 -19
- splight-lib-2.3.20/splight_models/blockchain.py +0 -58
- splight-lib-2.3.20/splight_models/channel.py +0 -7
- splight-lib-2.3.20/splight_models/communication/__init__.py +0 -11
- splight-lib-2.3.20/splight_models/communication/events.py +0 -41
- splight-lib-2.3.20/splight_models/component.py +0 -345
- splight-lib-2.3.20/splight_models/constants.py +0 -120
- splight-lib-2.3.20/splight_models/credential.py +0 -13
- splight-lib-2.3.20/splight_models/datalake.py +0 -47
- splight-lib-2.3.20/splight_models/deployment.py +0 -50
- splight-lib-2.3.20/splight_models/exception.py +0 -26
- splight-lib-2.3.20/splight_models/namespace.py +0 -20
- splight-lib-2.3.20/splight_models/notification.py +0 -42
- splight-lib-2.3.20/splight_models/setpoint.py +0 -73
- splight-lib-2.3.20/splight_models/severity.py +0 -10
- splight-lib-2.3.20/splight_models/user.py +0 -95
- splight-lib-2.3.20/splight_models/webhook.py +0 -26
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/LICENSE.txt +0 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/README.md +0 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/setup.cfg +0 -0
- {splight-lib-2.3.20/splight_lib/client → splight-lib-3.0.0.dev0/splight_lib}/__init__.py +0 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/auth/__init__.py +0 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/auth/exceptions.py +0 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/auth/mac_auth.py +0 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/auth/token.py +0 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/client/communication/__init__.py +0 -0
- {splight-lib-2.3.20/splight_abstract → splight-lib-3.0.0.dev0/splight_lib/client}/communication/exceptions.py +0 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/client/file_handler.py +0 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/client/filter.py +0 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/client/hub/__init__.py +0 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/encryption.py +0 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/logging/__init__.py +0 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/logging/component.py +0 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/logging/logging.py +0 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/restclient/__init__.py +0 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/restclient/client.py +0 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/restclient/exceptions.py +0 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/restclient/types.py +0 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/webhook.py +0 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib.egg-info/dependency_links.txt +0 -0
- {splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib.egg-info/not-zip-safe +0 -0
|
File without changes
|
|
@@ -1,54 +1,25 @@
|
|
|
1
1
|
from abc import ABC
|
|
2
2
|
from collections import UserList
|
|
3
|
-
from functools import wraps
|
|
4
|
-
from typing import Callable, List, Type
|
|
5
|
-
|
|
6
|
-
from pydantic import BaseModel
|
|
7
|
-
|
|
8
|
-
from .filter import FilterMixin
|
|
9
|
-
from .hooks import HooksMixin
|
|
10
3
|
|
|
11
4
|
|
|
12
5
|
class empty:
|
|
13
6
|
pass
|
|
14
7
|
|
|
15
8
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def wrapper(self, resource_type: Type, *args, **kwargs):
|
|
19
|
-
if resource_type not in self.valid_classes:
|
|
20
|
-
raise NotImplementedError(
|
|
21
|
-
f"Not a valid resource_type: {resource_type.__name__}"
|
|
22
|
-
)
|
|
23
|
-
return func(self, resource_type, *args, **kwargs)
|
|
24
|
-
|
|
25
|
-
return wrapper
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
def validate_client_instance_type(func: Callable) -> Callable:
|
|
29
|
-
@wraps(func)
|
|
30
|
-
def wrapper(self, instance: BaseModel, *args, **kwargs):
|
|
31
|
-
if type(instance) not in self.valid_classes:
|
|
32
|
-
raise NotImplementedError(
|
|
33
|
-
f"Not a valid instance type: {type(instance).__name__}"
|
|
34
|
-
)
|
|
35
|
-
return func(self, instance, *args, **kwargs)
|
|
36
|
-
|
|
37
|
-
return wrapper
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
class AbstractClient(ABC, HooksMixin, FilterMixin):
|
|
41
|
-
valid_classes: List[Type] = []
|
|
9
|
+
class AbstractClient(ABC):
|
|
10
|
+
pass
|
|
42
11
|
|
|
43
|
-
def __init__(self, namespace: str = "default", *args, **kwargs):
|
|
44
|
-
self.namespace = namespace.lower().replace("_", "")
|
|
45
12
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
13
|
+
class AbstractRemoteClient(AbstractClient):
|
|
14
|
+
def _parse_params(self, **kwargs):
|
|
15
|
+
params = {}
|
|
16
|
+
for key, value in kwargs.items():
|
|
17
|
+
if value is None:
|
|
18
|
+
continue
|
|
19
|
+
params[key] = value
|
|
20
|
+
if isinstance(value, list):
|
|
21
|
+
params[key] = ",".join(value)
|
|
22
|
+
return params
|
|
52
23
|
|
|
53
24
|
|
|
54
25
|
class QuerySet(UserList):
|
|
File without changes
|
|
@@ -1,16 +1,9 @@
|
|
|
1
1
|
from abc import abstractmethod, abstractproperty
|
|
2
|
-
from enum import Enum
|
|
3
2
|
from typing import Callable, Dict
|
|
4
3
|
|
|
5
|
-
from
|
|
6
|
-
from
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class CommunicationClientStatus(str, Enum):
|
|
10
|
-
STARTING = "starting"
|
|
11
|
-
READY = "ready"
|
|
12
|
-
FAILED = "failed"
|
|
13
|
-
ERROR = "error"
|
|
4
|
+
from splight_lib.abstract.client import AbstractClient
|
|
5
|
+
from splight_lib.models.communication import CommunicationContext
|
|
6
|
+
from splight_lib.models.event import CommunicationEvent
|
|
14
7
|
|
|
15
8
|
|
|
16
9
|
class AbstractCommunicationClient(AbstractClient):
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from
|
|
1
|
+
from splight_lib.models.communication import CommunicationContext
|
|
2
|
+
from splight_lib.models.event import CommunicationEvent
|
|
2
3
|
|
|
3
4
|
CLASSMAP = {
|
|
4
5
|
CommunicationContext: "v2/engine/communication/context/",
|
{splight-lib-2.3.20 → splight-lib-3.0.0.dev0}/splight_lib/client/communication/remote_client.py
RENAMED
|
@@ -5,35 +5,36 @@ import pysher
|
|
|
5
5
|
import requests
|
|
6
6
|
from furl import furl
|
|
7
7
|
from retry import retry
|
|
8
|
-
from
|
|
8
|
+
from splight_lib.auth import SplightAuthToken
|
|
9
|
+
from splight_lib.client.communication.abstract import (
|
|
9
10
|
AbstractCommunicationClient,
|
|
10
|
-
ClientNotReady,
|
|
11
11
|
)
|
|
12
|
-
from splight_lib.auth import SplightAuthToken
|
|
13
12
|
from splight_lib.client.communication.classmap import CLASSMAP
|
|
14
|
-
from splight_lib.client.
|
|
13
|
+
from splight_lib.client.communication.exceptions import ClientNotReady
|
|
15
14
|
from splight_lib.logging._internal import LogTags, get_splight_logger
|
|
16
|
-
from
|
|
15
|
+
from splight_lib.models.communication import (
|
|
17
16
|
CommunicationClientStatus,
|
|
18
17
|
CommunicationContext,
|
|
19
|
-
CommunicationEvent,
|
|
20
18
|
)
|
|
19
|
+
from splight_lib.models.event import CommunicationEvent
|
|
21
20
|
|
|
22
21
|
logger = get_splight_logger()
|
|
23
22
|
|
|
24
23
|
|
|
25
24
|
class CommunicationFactory:
|
|
26
|
-
def __init__(self, model):
|
|
25
|
+
def __init__(self, model, base_url, access_id: str, secret_key: str):
|
|
27
26
|
self._model = model
|
|
27
|
+
self._base_url = furl(base_url)
|
|
28
|
+
self._access_id = access_id
|
|
29
|
+
self._secret_key = secret_key
|
|
28
30
|
|
|
29
31
|
def get_url(self):
|
|
30
|
-
|
|
31
|
-
return base_url / CLASSMAP.get(self._model)
|
|
32
|
+
return self._base_url / CLASSMAP.get(self._model)
|
|
32
33
|
|
|
33
34
|
def get_headers(self):
|
|
34
35
|
auth_token = SplightAuthToken(
|
|
35
|
-
access_key=
|
|
36
|
-
secret_key=
|
|
36
|
+
access_key=self._access_id,
|
|
37
|
+
secret_key=self._secret_key,
|
|
37
38
|
)
|
|
38
39
|
return auth_token.header
|
|
39
40
|
|
|
@@ -58,8 +59,19 @@ class CommunicationFactory:
|
|
|
58
59
|
|
|
59
60
|
|
|
60
61
|
class RemoteCommunicationClient(AbstractCommunicationClient):
|
|
61
|
-
def __init__(
|
|
62
|
+
def __init__(
|
|
63
|
+
self,
|
|
64
|
+
url: str,
|
|
65
|
+
access_id: str,
|
|
66
|
+
secret_key: str,
|
|
67
|
+
daemon: bool = True,
|
|
68
|
+
*args,
|
|
69
|
+
**kwargs,
|
|
70
|
+
):
|
|
62
71
|
super().__init__(*args, **kwargs)
|
|
72
|
+
self._base_url = url
|
|
73
|
+
self._access_id = access_id
|
|
74
|
+
self._secret_key = secret_key
|
|
63
75
|
self._status = CommunicationClientStatus.STOPPED
|
|
64
76
|
self._channel_bindings = []
|
|
65
77
|
self._client, self._context = None, None
|
|
@@ -105,7 +117,12 @@ class RemoteCommunicationClient(AbstractCommunicationClient):
|
|
|
105
117
|
@retry(Exception, tries=3, delay=2, jitter=1)
|
|
106
118
|
def __load_context(self):
|
|
107
119
|
params = {"instance_id": self.instance_id}
|
|
108
|
-
self._context = CommunicationFactory(
|
|
120
|
+
self._context = CommunicationFactory(
|
|
121
|
+
CommunicationContext,
|
|
122
|
+
base_url=self._base_url,
|
|
123
|
+
access_id=self._access_id,
|
|
124
|
+
secret_key=self._secret_key,
|
|
125
|
+
).get(params)
|
|
109
126
|
|
|
110
127
|
@retry(Exception, tries=3, delay=2, jitter=1)
|
|
111
128
|
def __load_client(self):
|
|
@@ -162,9 +179,12 @@ class RemoteCommunicationClient(AbstractCommunicationClient):
|
|
|
162
179
|
raise NotImplementedError
|
|
163
180
|
|
|
164
181
|
def trigger(self, event: CommunicationEvent):
|
|
165
|
-
return CommunicationFactory(
|
|
166
|
-
|
|
167
|
-
|
|
182
|
+
return CommunicationFactory(
|
|
183
|
+
CommunicationEvent,
|
|
184
|
+
base_url=self._base_url,
|
|
185
|
+
access_id=self._access_id,
|
|
186
|
+
secret_key=self._secret_key,
|
|
187
|
+
).create(data=event.dict())
|
|
168
188
|
|
|
169
189
|
def authenticate(
|
|
170
190
|
self, channel_name: str, socket_id: str, custom_data: Dict = None
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
from splight_lib.client.database.builder import DatabaseClientBuilder
|
|
1
2
|
from splight_lib.client.database.local_client import LocalDatabaseClient
|
|
2
3
|
from splight_lib.client.database.remote_client import RemoteDatabaseClient
|
|
3
4
|
|
|
4
5
|
__all__ = [
|
|
5
6
|
LocalDatabaseClient,
|
|
7
|
+
DatabaseClientBuilder,
|
|
6
8
|
RemoteDatabaseClient,
|
|
7
9
|
]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from abc import abstractmethod
|
|
2
|
+
from tempfile import NamedTemporaryFile
|
|
3
|
+
from typing import Dict, List, Union
|
|
4
|
+
|
|
5
|
+
from splight_lib.abstract.client import AbstractClient, QuerySet
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AbstractDatabaseClient(AbstractClient):
|
|
9
|
+
@abstractmethod
|
|
10
|
+
def save(self, resource_name: str, instance: Dict) -> Dict:
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
@abstractmethod
|
|
14
|
+
def _get(
|
|
15
|
+
self, resource_name: str, first: bool = False, **kwargs
|
|
16
|
+
) -> Union[Dict, List[Dict]]:
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
def get(self, resource_name: str, *args, **kwargs) -> QuerySet:
|
|
20
|
+
return QuerySet(self, resource_name, *args, **kwargs)
|
|
21
|
+
|
|
22
|
+
@abstractmethod
|
|
23
|
+
def delete(self, resource_name: str, id: str) -> None:
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
@abstractmethod
|
|
27
|
+
def download(self, instance: Dict) -> NamedTemporaryFile:
|
|
28
|
+
pass
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from typing import Any, Dict
|
|
2
|
+
|
|
3
|
+
from splight_lib.client.database.abstract import AbstractDatabaseClient
|
|
4
|
+
from splight_lib.client.database.local_client import LocalDatabaseClient
|
|
5
|
+
from splight_lib.client.database.remote_client import RemoteDatabaseClient
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class DatabaseClientBuilder:
|
|
9
|
+
@staticmethod
|
|
10
|
+
def build(
|
|
11
|
+
local: bool = False, parameters: Dict[str, Any] = {}
|
|
12
|
+
) -> AbstractDatabaseClient:
|
|
13
|
+
if local:
|
|
14
|
+
db_client = LocalDatabaseClient(**parameters)
|
|
15
|
+
else:
|
|
16
|
+
db_client = RemoteDatabaseClient(**parameters)
|
|
17
|
+
return db_client
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from splight_lib.constants import ENGINE_PREFIX
|
|
2
|
+
|
|
3
|
+
MODEL_NAME_MAP = {
|
|
4
|
+
"alert": f"{ENGINE_PREFIX}/alert/alerts/",
|
|
5
|
+
"asset": f"{ENGINE_PREFIX}/assets/",
|
|
6
|
+
"attribute": f"{ENGINE_PREFIX}/attributes/",
|
|
7
|
+
"component": f"{ENGINE_PREFIX}/component/components/",
|
|
8
|
+
"componentobject": f"{ENGINE_PREFIX}/component/objects/",
|
|
9
|
+
"file": f"{ENGINE_PREFIX}/files/",
|
|
10
|
+
"query": f"{ENGINE_PREFIX}/queries/",
|
|
11
|
+
"secret": f"{ENGINE_PREFIX}/secrets/",
|
|
12
|
+
"setpoint": f"{ENGINE_PREFIX}/setpoints/",
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
CUSTOM_PATHS_MAP = {
|
|
16
|
+
"set-asset-attribute": "{prefix}/assets/{asset}/set-attribute/",
|
|
17
|
+
"get-asset-attribute": "{prefix}/assets/{asset}/get-attribute/",
|
|
18
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from functools import partial
|
|
4
|
+
from tempfile import NamedTemporaryFile
|
|
5
|
+
from typing import Dict, List, Union
|
|
6
|
+
from uuid import uuid4
|
|
7
|
+
|
|
8
|
+
from splight_lib.client.database.abstract import AbstractDatabaseClient
|
|
9
|
+
from splight_lib.client.exceptions import InstanceNotFound
|
|
10
|
+
from splight_lib.client.filter import value_filter_on_tuple
|
|
11
|
+
from splight_lib.logging._internal import LogTags, get_splight_logger
|
|
12
|
+
|
|
13
|
+
logger = get_splight_logger()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class LocalDatabaseClient(AbstractDatabaseClient):
|
|
17
|
+
"""Database Client implementation for a local database that uses a
|
|
18
|
+
JSON file.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(self, path: str, *args, **kwargs):
|
|
22
|
+
super().__init__()
|
|
23
|
+
self._db_file = os.path.join(path, "splight-db.json")
|
|
24
|
+
|
|
25
|
+
if not os.path.exists(self._db_file):
|
|
26
|
+
self._save_db(self._db_file, {})
|
|
27
|
+
logger.debug(
|
|
28
|
+
"Local database client initialized.", tags=LogTags.DATABASE
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
def save(self, resource_name: str, instance: Dict) -> Dict:
|
|
32
|
+
"""Creates or updates a resource depending on the name if
|
|
33
|
+
it contains the id or not.
|
|
34
|
+
|
|
35
|
+
Parameters
|
|
36
|
+
----------
|
|
37
|
+
resource_name: str
|
|
38
|
+
The name of the resource to be created or updated.
|
|
39
|
+
instance : Dict
|
|
40
|
+
A dictionary with resource to be created or updated
|
|
41
|
+
|
|
42
|
+
Returns
|
|
43
|
+
-------
|
|
44
|
+
Dict with the created or updated resource.
|
|
45
|
+
|
|
46
|
+
Raises
|
|
47
|
+
------
|
|
48
|
+
InvalidModelName thrown when the model name is not correct.
|
|
49
|
+
"""
|
|
50
|
+
logger.debug("Saving instance", tags=LogTags.DATABASE)
|
|
51
|
+
|
|
52
|
+
model_name = resource_name.lower()
|
|
53
|
+
if instance.get("id"):
|
|
54
|
+
saved_instance = self._update(model_name, instance)
|
|
55
|
+
else:
|
|
56
|
+
saved_instance = self._create(model_name, instance)
|
|
57
|
+
return saved_instance
|
|
58
|
+
|
|
59
|
+
def delete(self, resource_name: str, id: str):
|
|
60
|
+
"""Deletes a resource from the database
|
|
61
|
+
|
|
62
|
+
Parameters
|
|
63
|
+
----------
|
|
64
|
+
resource_name : str
|
|
65
|
+
The resource name
|
|
66
|
+
id : str
|
|
67
|
+
The resource's id.
|
|
68
|
+
|
|
69
|
+
Raises
|
|
70
|
+
------
|
|
71
|
+
InvalidModelName thrown when the model name is not correct.
|
|
72
|
+
"""
|
|
73
|
+
logger.debug("Deleting instance %s.", id, tags=LogTags.DATABASE)
|
|
74
|
+
model_name = resource_name.lower()
|
|
75
|
+
db = self._load_db_file(self._db_file)
|
|
76
|
+
db_instances = db.get(model_name, {})
|
|
77
|
+
|
|
78
|
+
if id not in db_instances:
|
|
79
|
+
raise InstanceNotFound(model_name, id)
|
|
80
|
+
|
|
81
|
+
_ = db_instances.pop(id)
|
|
82
|
+
self._save_db(self._db_file, db)
|
|
83
|
+
|
|
84
|
+
def operate(self, resource_name: str, instance: Dict) -> Dict:
|
|
85
|
+
raise NotImplementedError("Method not allowed for Local Database")
|
|
86
|
+
|
|
87
|
+
def _get(
|
|
88
|
+
self,
|
|
89
|
+
resource_name: str,
|
|
90
|
+
first: bool = False,
|
|
91
|
+
**kwargs,
|
|
92
|
+
) -> Union[Dict, List[Dict]]:
|
|
93
|
+
"""Retrieves one or multiple resources. If the parameter id is passed
|
|
94
|
+
as a kwarg, the instance with that id will be retrieved.
|
|
95
|
+
|
|
96
|
+
Parameters
|
|
97
|
+
----------
|
|
98
|
+
resource_name : str
|
|
99
|
+
The name of the resource.
|
|
100
|
+
first: bool
|
|
101
|
+
Whether to retrieve first element or not.
|
|
102
|
+
|
|
103
|
+
Returns
|
|
104
|
+
-------
|
|
105
|
+
Union[Dict, List[Dict]] list of resource or single resource.
|
|
106
|
+
"""
|
|
107
|
+
resource_id = kwargs.pop("id", None)
|
|
108
|
+
model_name = resource_name.lower()
|
|
109
|
+
if resource_id:
|
|
110
|
+
result = self._retrieve_single(model_name, resource_id)
|
|
111
|
+
else:
|
|
112
|
+
result = self._retrieve_multiple(model_name, first=first, **kwargs)
|
|
113
|
+
return result
|
|
114
|
+
|
|
115
|
+
def _retrieve_single(self, model_name: str, resource_id: str) -> Dict:
|
|
116
|
+
db = self._load_db_file(self._db_file)
|
|
117
|
+
db_instances = db.get(model_name, {})
|
|
118
|
+
if resource_id not in db_instances:
|
|
119
|
+
raise InstanceNotFound(model_name, resource_id)
|
|
120
|
+
return db_instances.get(resource_id)
|
|
121
|
+
|
|
122
|
+
def _retrieve_multiple(
|
|
123
|
+
self, model_name: str, first: bool = False, **kwargs
|
|
124
|
+
) -> List[Dict]:
|
|
125
|
+
db = self._load_db_file(self._db_file)
|
|
126
|
+
db_instances = db.get(model_name, {})
|
|
127
|
+
|
|
128
|
+
filters = self._validate_filters(kwargs)
|
|
129
|
+
filtered = self._filter(db_instances, filters=filters)
|
|
130
|
+
instances = list(filtered.values())
|
|
131
|
+
if first:
|
|
132
|
+
return [instances[0]]
|
|
133
|
+
return instances
|
|
134
|
+
|
|
135
|
+
def download(
|
|
136
|
+
self, instances: Dict, decrtypt: bool = True, **kwargs
|
|
137
|
+
) -> NamedTemporaryFile:
|
|
138
|
+
raise NotImplementedError("Method not implemented for Local Database")
|
|
139
|
+
|
|
140
|
+
def _create(self, resource_name: str, instance: Dict) -> Dict:
|
|
141
|
+
db = self._load_db_file(self._db_file)
|
|
142
|
+
db_instances = db.get(resource_name, {})
|
|
143
|
+
instance["id"] = str(uuid4())
|
|
144
|
+
db_instances.update({instance["id"]: instance})
|
|
145
|
+
db[resource_name] = db_instances
|
|
146
|
+
self._save_db(self._db_file, db)
|
|
147
|
+
return instance
|
|
148
|
+
|
|
149
|
+
def _update(self, resource_name: str, instance: Dict) -> Dict:
|
|
150
|
+
db = self._load_db_file(self._db_file)
|
|
151
|
+
db_instances = db.get(resource_name, {})
|
|
152
|
+
|
|
153
|
+
if instance["id"] not in db_instances:
|
|
154
|
+
raise InstanceNotFound(resource_name, instance["id"])
|
|
155
|
+
db_instances[instance["id"]] = instance
|
|
156
|
+
self._save_db(self._db_file, db)
|
|
157
|
+
return instance
|
|
158
|
+
|
|
159
|
+
def _filter(
|
|
160
|
+
self, instances: Dict[str, Dict], filters: Dict
|
|
161
|
+
) -> Dict[str, Dict]:
|
|
162
|
+
filtered = instances
|
|
163
|
+
for key, value in filters.items():
|
|
164
|
+
filtered = filter(
|
|
165
|
+
partial(value_filter_on_tuple, key, value), filtered.items()
|
|
166
|
+
)
|
|
167
|
+
filtered = {item[0]: item[1] for item in filtered}
|
|
168
|
+
return filtered
|
|
169
|
+
|
|
170
|
+
def _load_db_file(self, file_path: str) -> Dict:
|
|
171
|
+
with open(file_path, "r") as fid:
|
|
172
|
+
data = json.load(fid)
|
|
173
|
+
return data
|
|
174
|
+
|
|
175
|
+
def _save_db(self, file_path: str, db: Dict):
|
|
176
|
+
with open(file_path, "w") as fid:
|
|
177
|
+
json.dump(db, fid, indent=2)
|
|
178
|
+
|
|
179
|
+
def _validate_filters(self, filters_raw: Dict):
|
|
180
|
+
invalid_filters = ["ignore_hook"]
|
|
181
|
+
return {
|
|
182
|
+
key: value
|
|
183
|
+
for key, value in filters_raw.items()
|
|
184
|
+
if key not in invalid_filters
|
|
185
|
+
}
|