splight-lib 2.3.19__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.
Files changed (136) hide show
  1. {splight-lib-2.3.19/splight_lib.egg-info → splight-lib-3.0.0.dev0}/PKG-INFO +1 -1
  2. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/setup.py +1 -1
  3. splight-lib-3.0.0.dev0/splight_lib/abstract/__init__.py +0 -0
  4. splight-lib-2.3.19/splight_abstract/client/abstract.py → splight-lib-3.0.0.dev0/splight_lib/abstract/client.py +12 -41
  5. splight-lib-3.0.0.dev0/splight_lib/client/__init__.py +0 -0
  6. {splight-lib-2.3.19/splight_abstract → splight-lib-3.0.0.dev0/splight_lib/client}/communication/abstract.py +3 -10
  7. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/client/communication/classmap.py +2 -1
  8. splight-lib-3.0.0.dev0/splight_lib/client/communication/local_client.py +7 -0
  9. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/client/communication/remote_client.py +36 -16
  10. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/client/database/__init__.py +2 -0
  11. splight-lib-3.0.0.dev0/splight_lib/client/database/abstract.py +28 -0
  12. splight-lib-3.0.0.dev0/splight_lib/client/database/builder.py +17 -0
  13. splight-lib-3.0.0.dev0/splight_lib/client/database/classmap.py +18 -0
  14. splight-lib-3.0.0.dev0/splight_lib/client/database/local_client.py +185 -0
  15. splight-lib-3.0.0.dev0/splight_lib/client/database/remote_client.py +267 -0
  16. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/client/datalake/__init__.py +2 -0
  17. splight-lib-3.0.0.dev0/splight_lib/client/datalake/abstract.py +65 -0
  18. splight-lib-3.0.0.dev0/splight_lib/client/datalake/builder.py +17 -0
  19. splight-lib-3.0.0.dev0/splight_lib/client/datalake/local_client.py +162 -0
  20. splight-lib-3.0.0.dev0/splight_lib/client/datalake/remote_client.py +179 -0
  21. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/client/exceptions.py +1 -1
  22. {splight-lib-2.3.19/splight_abstract → splight-lib-3.0.0.dev0/splight_lib/client}/hub/abstract.py +16 -7
  23. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/client/hub/client.py +8 -15
  24. splight-lib-3.0.0.dev0/splight_lib/communication/__init__.py +0 -0
  25. splight-lib-3.0.0.dev0/splight_lib/communication/event_handler.py +171 -0
  26. splight-lib-3.0.0.dev0/splight_lib/component/__init__.py +5 -0
  27. splight-lib-3.0.0.dev0/splight_lib/component/abstract.py +260 -0
  28. splight-lib-3.0.0.dev0/splight_lib/component/exceptions.py +36 -0
  29. splight-lib-3.0.0.dev0/splight_lib/component/spec.py +232 -0
  30. splight-lib-3.0.0.dev0/splight_lib/constants.py +1 -0
  31. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/execution.py +1 -1
  32. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/logging/_internal.py +0 -1
  33. splight-lib-3.0.0.dev0/splight_lib/models/__init__.py +33 -0
  34. splight-lib-3.0.0.dev0/splight_lib/models/alert.py +55 -0
  35. splight-lib-3.0.0.dev0/splight_lib/models/asset.py +41 -0
  36. splight-lib-3.0.0.dev0/splight_lib/models/attribute.py +8 -0
  37. splight-lib-3.0.0.dev0/splight_lib/models/base.py +160 -0
  38. splight-lib-2.3.19/splight_models/communication/context.py → splight-lib-3.0.0.dev0/splight_lib/models/communication.py +9 -10
  39. splight-lib-3.0.0.dev0/splight_lib/models/component.py +327 -0
  40. splight-lib-3.0.0.dev0/splight_lib/models/event.py +119 -0
  41. splight-lib-3.0.0.dev0/splight_lib/models/exceptions.py +14 -0
  42. {splight-lib-2.3.19/splight_models → splight-lib-3.0.0.dev0/splight_lib/models}/file.py +16 -4
  43. {splight-lib-2.3.19/splight_models → splight-lib-3.0.0.dev0/splight_lib/models}/hub.py +2 -3
  44. splight-lib-2.3.19/splight_models/variable.py → splight-lib-3.0.0.dev0/splight_lib/models/native.py +6 -10
  45. {splight-lib-2.3.19/splight_models → splight-lib-3.0.0.dev0/splight_lib/models}/query.py +3 -3
  46. {splight-lib-2.3.19/splight_models → splight-lib-3.0.0.dev0/splight_lib/models}/secret.py +2 -4
  47. splight-lib-3.0.0.dev0/splight_lib/models/setpoint.py +67 -0
  48. splight-lib-3.0.0.dev0/splight_lib/settings.py +63 -0
  49. splight-lib-3.0.0.dev0/splight_lib/utils/__init__.py +0 -0
  50. splight-lib-3.0.0.dev0/splight_lib/utils/custom_model.py +75 -0
  51. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0/splight_lib.egg-info}/PKG-INFO +1 -1
  52. splight-lib-3.0.0.dev0/splight_lib.egg-info/SOURCES.txt +76 -0
  53. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib.egg-info/requires.txt +1 -0
  54. splight-lib-3.0.0.dev0/splight_lib.egg-info/top_level.txt +1 -0
  55. splight-lib-2.3.19/splight_abstract/__init__.py +0 -11
  56. splight-lib-2.3.19/splight_abstract/auth/__init__.py +0 -2
  57. splight-lib-2.3.19/splight_abstract/auth/abstract.py +0 -41
  58. splight-lib-2.3.19/splight_abstract/auth/exceptions.py +0 -20
  59. splight-lib-2.3.19/splight_abstract/cache/__init__.py +0 -1
  60. splight-lib-2.3.19/splight_abstract/cache/abstract.py +0 -130
  61. splight-lib-2.3.19/splight_abstract/client/__init__.py +0 -3
  62. splight-lib-2.3.19/splight_abstract/client/filter.py +0 -98
  63. splight-lib-2.3.19/splight_abstract/client/hooks.py +0 -70
  64. splight-lib-2.3.19/splight_abstract/communication/__init__.py +0 -2
  65. splight-lib-2.3.19/splight_abstract/database/__init__.py +0 -1
  66. splight-lib-2.3.19/splight_abstract/database/abstract.py +0 -39
  67. splight-lib-2.3.19/splight_abstract/datalake/__init__.py +0 -1
  68. splight-lib-2.3.19/splight_abstract/datalake/abstract.py +0 -103
  69. splight-lib-2.3.19/splight_abstract/deployment/__init__.py +0 -1
  70. splight-lib-2.3.19/splight_abstract/deployment/abstract.py +0 -39
  71. splight-lib-2.3.19/splight_abstract/endpoints/__init__.py +0 -76
  72. splight-lib-2.3.19/splight_abstract/hub/__init__.py +0 -1
  73. splight-lib-2.3.19/splight_abstract/notification/__init__.py +0 -2
  74. splight-lib-2.3.19/splight_abstract/notification/abstract.py +0 -10
  75. splight-lib-2.3.19/splight_abstract/remote/__init__.py +0 -1
  76. splight-lib-2.3.19/splight_abstract/remote/abstract.py +0 -13
  77. splight-lib-2.3.19/splight_abstract/storage/__init__.py +0 -1
  78. splight-lib-2.3.19/splight_abstract/storage/abstract.py +0 -44
  79. splight-lib-2.3.19/splight_lib/__init__.py +0 -3
  80. splight-lib-2.3.19/splight_lib/client/communication/local_client.py +0 -6
  81. splight-lib-2.3.19/splight_lib/client/database/classmap.py +0 -33
  82. splight-lib-2.3.19/splight_lib/client/database/local_client.py +0 -175
  83. splight-lib-2.3.19/splight_lib/client/database/remote_client.py +0 -224
  84. splight-lib-2.3.19/splight_lib/client/datalake/local_client.py +0 -194
  85. splight-lib-2.3.19/splight_lib/client/datalake/remote_client.py +0 -261
  86. splight-lib-2.3.19/splight_lib/client/settings.py +0 -18
  87. splight-lib-2.3.19/splight_lib/component/__init__.py +0 -5
  88. splight-lib-2.3.19/splight_lib/component/abstract.py +0 -766
  89. splight-lib-2.3.19/splight_lib/settings.py +0 -179
  90. splight-lib-2.3.19/splight_lib.egg-info/SOURCES.txt +0 -101
  91. splight-lib-2.3.19/splight_lib.egg-info/top_level.txt +0 -3
  92. splight-lib-2.3.19/splight_models/__init__.py +0 -20
  93. splight-lib-2.3.19/splight_models/alert.py +0 -84
  94. splight-lib-2.3.19/splight_models/asset.py +0 -20
  95. splight-lib-2.3.19/splight_models/attribute.py +0 -8
  96. splight-lib-2.3.19/splight_models/base.py +0 -19
  97. splight-lib-2.3.19/splight_models/blockchain.py +0 -58
  98. splight-lib-2.3.19/splight_models/channel.py +0 -7
  99. splight-lib-2.3.19/splight_models/communication/__init__.py +0 -11
  100. splight-lib-2.3.19/splight_models/communication/events.py +0 -41
  101. splight-lib-2.3.19/splight_models/component.py +0 -345
  102. splight-lib-2.3.19/splight_models/constants.py +0 -120
  103. splight-lib-2.3.19/splight_models/credential.py +0 -13
  104. splight-lib-2.3.19/splight_models/datalake.py +0 -47
  105. splight-lib-2.3.19/splight_models/deployment.py +0 -50
  106. splight-lib-2.3.19/splight_models/exception.py +0 -26
  107. splight-lib-2.3.19/splight_models/namespace.py +0 -20
  108. splight-lib-2.3.19/splight_models/notification.py +0 -42
  109. splight-lib-2.3.19/splight_models/setpoint.py +0 -73
  110. splight-lib-2.3.19/splight_models/severity.py +0 -10
  111. splight-lib-2.3.19/splight_models/user.py +0 -95
  112. splight-lib-2.3.19/splight_models/webhook.py +0 -26
  113. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/LICENSE.txt +0 -0
  114. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/README.md +0 -0
  115. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/setup.cfg +0 -0
  116. {splight-lib-2.3.19/splight_lib/client → splight-lib-3.0.0.dev0/splight_lib}/__init__.py +0 -0
  117. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/auth/__init__.py +0 -0
  118. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/auth/exceptions.py +0 -0
  119. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/auth/mac_auth.py +0 -0
  120. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/auth/token.py +0 -0
  121. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/client/communication/__init__.py +0 -0
  122. {splight-lib-2.3.19/splight_abstract → splight-lib-3.0.0.dev0/splight_lib/client}/communication/exceptions.py +0 -0
  123. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/client/file_handler.py +0 -0
  124. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/client/filter.py +0 -0
  125. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/client/hub/__init__.py +0 -0
  126. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/encryption.py +0 -0
  127. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/logging/__init__.py +0 -0
  128. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/logging/component.py +0 -0
  129. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/logging/logging.py +0 -0
  130. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/restclient/__init__.py +0 -0
  131. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/restclient/client.py +0 -0
  132. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/restclient/exceptions.py +0 -0
  133. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/restclient/types.py +0 -0
  134. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib/webhook.py +0 -0
  135. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib.egg-info/dependency_links.txt +0 -0
  136. {splight-lib-2.3.19 → splight-lib-3.0.0.dev0}/splight_lib.egg-info/not-zip-safe +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: splight-lib
3
- Version: 2.3.19
3
+ Version: 3.0.0.dev0
4
4
  Summary: Library for public use. Splight
5
5
  Home-page: UNKNOWN
6
6
  Author: Splight
@@ -14,7 +14,7 @@ test_requires = [
14
14
 
15
15
  setup(
16
16
  name="splight-lib",
17
- version="2.3.19",
17
+ version="3.0.0dev0",
18
18
  author="Splight",
19
19
  author_email="factory@splight-ae.com",
20
20
  packages=find_packages(),
@@ -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
- def validate_client_resource_type(func: Callable) -> Callable:
17
- @wraps(func)
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
- def _validated_kwargs(self, resource_type: Type, **kwargs):
47
- """
48
- Validate the given kwargs.
49
- """
50
- class_fields = list(resource_type.__fields__.keys())
51
- return super()._validated_kwargs(class_fields, **kwargs)
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 splight_abstract.client import AbstractClient
6
- from splight_models import CommunicationContext, CommunicationEvent
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 splight_models import CommunicationContext, CommunicationEvent
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/",
@@ -0,0 +1,7 @@
1
+ from splight_lib.client.communication.abstract import (
2
+ AbstractCommunicationClient,
3
+ )
4
+
5
+
6
+ class LocalCommunicationClient(AbstractCommunicationClient):
7
+ pass
@@ -5,35 +5,36 @@ import pysher
5
5
  import requests
6
6
  from furl import furl
7
7
  from retry import retry
8
- from splight_abstract.communication import (
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.settings import settings_remote as settings
13
+ from splight_lib.client.communication.exceptions import ClientNotReady
15
14
  from splight_lib.logging._internal import LogTags, get_splight_logger
16
- from splight_models.communication import (
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
- base_url = furl(settings.SPLIGHT_PLATFORM_API_HOST)
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=settings.SPLIGHT_ACCESS_ID,
36
- secret_key=settings.SPLIGHT_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__(self, daemon: bool = True, *args, **kwargs):
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(CommunicationContext).get(params)
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(CommunicationEvent).create(
166
- data=event.dict()
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
+ }