splight-lib 5.9.6.dev2__tar.gz → 5.10.0__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 (112) hide show
  1. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/PKG-INFO +1 -1
  2. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/pyproject.toml +49 -1
  3. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/client/database/classmap.py +0 -3
  4. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/client/database/remote_client.py +2 -6
  5. splight_lib-5.10.0/splight_lib/client/datalake/abstract.py +36 -0
  6. splight_lib-5.10.0/splight_lib/client/datalake/constants.py +31 -0
  7. splight_lib-5.10.0/splight_lib/client/datalake/exceptions.py +12 -0
  8. splight_lib-5.10.0/splight_lib/client/datalake/remote_client.py +252 -0
  9. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/client/exceptions.py +2 -1
  10. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/client/tests/test_datalake.py +2 -1
  11. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/component/spec.py +1 -1
  12. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/execution/task.py +2 -1
  13. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/logging/_internal.py +0 -1
  14. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/models/__init__.py +4 -4
  15. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/models/actions.py +4 -1
  16. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/models/alert.py +1 -1
  17. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/models/asset.py +4 -1
  18. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/models/attribute.py +1 -1
  19. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/models/component.py +2 -4
  20. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/models/dashboard.py +2 -4
  21. splight_lib-5.10.0/splight_lib/models/database_base.py +79 -0
  22. splight_lib-5.10.0/splight_lib/models/datalake.py +155 -0
  23. splight_lib-5.10.0/splight_lib/models/datalake_base.py +130 -0
  24. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/models/exceptions.py +5 -7
  25. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/models/file.py +1 -1
  26. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/models/function.py +1 -1
  27. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/models/hub_solution.py +2 -2
  28. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/models/metadata.py +1 -1
  29. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/models/native.py +19 -13
  30. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/models/secret.py +1 -1
  31. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/models/solution.py +1 -1
  32. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/models/tag.py +1 -1
  33. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/models/tests/test_database_model.py +3 -1
  34. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/solution/solution.py +1 -1
  35. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/tests/test_api_contracts.py +2 -1
  36. splight_lib-5.9.6.dev2/splight_lib/client/datalake/abstract.py +0 -71
  37. splight_lib-5.9.6.dev2/splight_lib/client/datalake/exceptions.py +0 -6
  38. splight_lib-5.9.6.dev2/splight_lib/client/datalake/remote_client.py +0 -405
  39. splight_lib-5.9.6.dev2/splight_lib/client/datalake/schemas.py +0 -56
  40. splight_lib-5.9.6.dev2/splight_lib/models/base.py +0 -203
  41. splight_lib-5.9.6.dev2/splight_lib/models/hub_server.py +0 -116
  42. splight_lib-5.9.6.dev2/splight_lib/models/pipeline.py +0 -80
  43. splight_lib-5.9.6.dev2/splight_lib/models/server.py +0 -196
  44. splight_lib-5.9.6.dev2/splight_lib/server/__init__.py +0 -5
  45. splight_lib-5.9.6.dev2/splight_lib/server/exceptions.py +0 -3
  46. splight_lib-5.9.6.dev2/splight_lib/server/server.py +0 -18
  47. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/LICENSE.txt +0 -0
  48. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/README.md +0 -0
  49. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/__init__.py +0 -0
  50. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/abstract/__init__.py +0 -0
  51. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/abstract/client.py +0 -0
  52. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/auth/__init__.py +0 -0
  53. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/auth/exceptions.py +0 -0
  54. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/auth/mac_auth.py +0 -0
  55. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/auth/token.py +0 -0
  56. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/client/__init__.py +0 -0
  57. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/client/database/__init__.py +0 -0
  58. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/client/database/abstract.py +0 -0
  59. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/client/database/builder.py +0 -0
  60. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/client/datalake/__init__.py +0 -0
  61. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/client/datalake/buffer.py +0 -0
  62. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/client/datalake/builder.py +0 -0
  63. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/client/file_handler.py +0 -0
  64. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/client/filter.py +0 -0
  65. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/client/hub/__init__.py +0 -0
  66. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/client/hub/abstract.py +0 -0
  67. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/client/hub/client.py +0 -0
  68. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/client/tests/test_database.py +0 -0
  69. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/component/__init__.py +0 -0
  70. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/component/abstract.py +0 -0
  71. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/component/exceptions.py +0 -0
  72. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/component/tests/test_abstract.py +0 -0
  73. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/component/tests/test_spec.py +0 -0
  74. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/conftest.py +0 -0
  75. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/constants.py +0 -0
  76. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/encryption.py +0 -0
  77. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/execution/__init__.py +0 -0
  78. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/execution/engine.py +0 -0
  79. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/execution/exceptions.py +0 -0
  80. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/execution/scheduling.py +0 -0
  81. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/execution/tests/test_execution.py +0 -0
  82. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/execution/tests/test_scheduling.py +0 -0
  83. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/execution/trigger.py +0 -0
  84. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/logging/__init__.py +0 -0
  85. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/logging/component.py +0 -0
  86. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/logging/constants.py +0 -0
  87. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/logging/logging.py +0 -0
  88. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/logging/tests/test_logging.py +0 -0
  89. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/models/data_address.py +0 -0
  90. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/models/generic.py +0 -0
  91. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/models/hub.py +0 -0
  92. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/models/tests/models.json +0 -0
  93. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/models/tests/test_component_object_instance.py +0 -0
  94. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/models/tests/test_metadata.py +0 -0
  95. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/models/tests/test_models.py +0 -0
  96. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/restclient/__init__.py +0 -0
  97. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/restclient/client.py +0 -0
  98. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/restclient/exceptions.py +0 -0
  99. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/restclient/tests/test_restclient.py +0 -0
  100. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/restclient/types.py +0 -0
  101. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/settings.py +0 -0
  102. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/solution/__init__.py +0 -0
  103. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/solution/exceptions.py +0 -0
  104. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/stringcase.py +0 -0
  105. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/testing/__init__.py +0 -0
  106. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/tests/FakeProc.py +0 -0
  107. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/tests/asset_geometries.json +0 -0
  108. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/tests/test_encryption.py +0 -0
  109. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/utils/__init__.py +0 -0
  110. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/utils/custom_model.py +0 -0
  111. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/utils/hub.py +0 -0
  112. {splight_lib-5.9.6.dev2 → splight_lib-5.10.0}/splight_lib/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: splight-lib
3
- Version: 5.9.6.dev2
3
+ Version: 5.10.0
4
4
  Summary: Splight Library
5
5
  Author: Splight Dev
6
6
  Author-email: dev@splight-ae.com
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "splight-lib"
3
- version = "5.9.6.dev2"
3
+ version = "5.10.0"
4
4
  description = "Splight Library"
5
5
  authors = ["Splight Dev <dev@splight-ae.com>"]
6
6
  readme = "README.md"
@@ -71,4 +71,52 @@ filterwarnings = [
71
71
  ]
72
72
 
73
73
  [tool.ruff]
74
+ # Exclude a variety of commonly ignored directories.
75
+ exclude = [
76
+ ".bzr",
77
+ ".direnv",
78
+ ".eggs",
79
+ ".git",
80
+ ".git-rewrite",
81
+ ".hg",
82
+ ".ipynb_checkpoints",
83
+ ".mypy_cache",
84
+ ".nox",
85
+ ".pants.d",
86
+ ".pyenv",
87
+ ".pytest_cache",
88
+ ".pytype",
89
+ ".ruff_cache",
90
+ ".svn",
91
+ ".tox",
92
+ ".venv",
93
+ ".vscode",
94
+ "__pypackages__",
95
+ "_build",
96
+ "buck-out",
97
+ "build",
98
+ "dist",
99
+ "node_modules",
100
+ "site-packages",
101
+ "venv",
102
+ ]
103
+
104
+ # Same as Black.
74
105
  line-length = 79
106
+ indent-width = 4
107
+
108
+ # Assume Python 3.8
109
+ target-version = "py38"
110
+
111
+ [tool.ruff.format]
112
+ # Like Black, use double quotes for strings.
113
+ quote-style = "double"
114
+
115
+ # Like Black, indent with spaces, rather than tabs.
116
+ indent-style = "space"
117
+
118
+ # Like Black, respect magic trailing commas.
119
+ skip-magic-trailing-comma = false
120
+
121
+ # Like Black, automatically detect the appropriate line ending.
122
+ line-ending = "auto"
@@ -23,12 +23,9 @@ MODEL_NAME_MAP = {
23
23
  "secret": f"{ENGINE_PREFIX}/secrets/",
24
24
  "setpoint": f"{ENGINE_PREFIX}/setpoints/",
25
25
  "solution": f"{ENGINE_PREFIX}/solution/solutions/",
26
- "server": f"{ENGINE_PREFIX}/server/servers/",
27
26
  "tab": f"{ENGINE_PREFIX}/dashboard/tabs/",
28
27
  "hubsolution": f"{HUB_PREFIX}/solution/solutions/",
29
28
  "hubsolutionversion": f"{HUB_PREFIX}/solution/versions/",
30
- "hubserver": f"{HUB_PREFIX}/server/servers/",
31
- "hubserverversion": f"{HUB_PREFIX}/server/versions/",
32
29
  }
33
30
 
34
31
  CUSTOM_PATHS_MAP = {
@@ -211,13 +211,9 @@ class RemoteDatabaseClient(AbstractDatabaseClient, AbstractRemoteClient):
211
211
  ------
212
212
  InvalidModelName thrown when the model name is not correct.
213
213
  """
214
- if resource_name.lower() not in [
215
- "file",
216
- "hubsolutionversion",
217
- "hubserverversion",
218
- ]:
214
+ if resource_name.lower() not in ["file", "hubsolutionversion"]:
219
215
  raise InvalidModel(
220
- "Only files, hub solution and hub servers can be downloaded."
216
+ "Only files and hub solution can be downloaded."
221
217
  )
222
218
  api_path = self._get_api_path(resource_name)
223
219
  resource_id = instance.get("id")
@@ -0,0 +1,36 @@
1
+ from abc import abstractmethod
2
+ from typing import Any, TypedDict
3
+
4
+ from splight_lib.abstract.client import AbstractRemoteClient, QuerySet
5
+
6
+
7
+ class Records(TypedDict):
8
+ collection: str
9
+ records: list[dict[str, Any]]
10
+
11
+
12
+ class AbstractDatalakeClient(AbstractRemoteClient):
13
+ def get(self, *args, **kwargs) -> QuerySet:
14
+ kwargs["get_func"] = "_get"
15
+ kwargs["count_func"] = "None"
16
+ return QuerySet(self, *args, **kwargs)
17
+
18
+ async def async_get(self, *args, **kwargs):
19
+ # TODO: consider using an async QuerySet
20
+ return await self._async_get(*args, **kwargs)
21
+
22
+ @abstractmethod
23
+ def save(self, records: Records) -> list[dict]:
24
+ pass
25
+
26
+ @abstractmethod
27
+ async def async_save(self, records: Records) -> list[dict]:
28
+ pass
29
+
30
+ @abstractmethod
31
+ def _get(self, request: dict) -> list[dict]:
32
+ pass
33
+
34
+ @abstractmethod
35
+ async def _async_get(self, request: dict) -> list[dict]:
36
+ pass
@@ -0,0 +1,31 @@
1
+ from enum import Enum
2
+
3
+
4
+ class StepName(str, Enum):
5
+ ADD_FIELDS = "addFields"
6
+ ADD_TO_SET = "addToSet"
7
+ BUCKET = "bucket"
8
+ BUCKET_AUTO = "bucketAuto"
9
+ BUCKET_GROUP = "bucketGroup"
10
+ COUNT = "count"
11
+ FACET = "facet"
12
+ GRAPH_LOOKUP = "graphLookup"
13
+ GROUP = "group"
14
+ INDEX_STATS = "indexStats"
15
+ LIMIT = "limit"
16
+ LIST_SESSIONS = "listSessions"
17
+ LOOKUP = "lookup"
18
+ MATCH = "match"
19
+ MERGE = "merge"
20
+ OUT = "out"
21
+ PLAN_CACHE_STATS = "planCacheStats"
22
+ PROJECT = "project"
23
+ REDACT = "redact"
24
+ REPLACE_ROOT = "replaceRoot"
25
+ REPLACE_WITH = "replaceWith"
26
+ SAMPLE = "sample"
27
+ SET = "set"
28
+ SKIP = "skip"
29
+ SORT = "sort"
30
+ UNSET = "unset"
31
+ UNWIND = "unwind"
@@ -0,0 +1,12 @@
1
+ class DatalakeRequestError(Exception):
2
+ def __init__(self, status_code: int, message: str):
3
+ self._msg = f"Request failed with status code {status_code}: {message}"
4
+ super().__init__(self._msg)
5
+
6
+
7
+ class InvalidCollectionName(Exception):
8
+ def __init__(self, collection: str):
9
+ self._msg = f"Collection {collection} is not a valid collection"
10
+
11
+ def __str__(self) -> str:
12
+ return self._msg
@@ -0,0 +1,252 @@
1
+ from threading import Lock, Thread
2
+ from time import sleep
3
+
4
+ from furl import furl
5
+ from retry import retry
6
+
7
+ from splight_lib.auth import SplightAuthToken
8
+ from splight_lib.client.datalake.abstract import (
9
+ AbstractDatalakeClient,
10
+ Records,
11
+ )
12
+ from splight_lib.client.datalake.buffer import DatalakeDocumentBuffer
13
+ from splight_lib.client.datalake.exceptions import DatalakeRequestError
14
+ from splight_lib.client.exceptions import SPLIGHT_REQUEST_EXCEPTIONS
15
+ from splight_lib.constants import DL_BUFFER_SIZE, DL_BUFFER_TIMEOUT
16
+ from splight_lib.logging._internal import LogTags, get_splight_logger
17
+ from splight_lib.restclient import SplightRestClient
18
+
19
+ logger = get_splight_logger()
20
+
21
+ EXCEPTIONS = (*SPLIGHT_REQUEST_EXCEPTIONS, DatalakeRequestError)
22
+
23
+
24
+ class SyncRemoteDatalakeClient(AbstractDatalakeClient):
25
+ _PREFIX = "/data"
26
+
27
+ def __init__(
28
+ self, base_url: str, access_id: str, secret_key: str, *args, **kwargs
29
+ ):
30
+ super().__init__()
31
+ self._base_url = furl(base_url)
32
+ token = SplightAuthToken(
33
+ access_key=access_id,
34
+ secret_key=secret_key,
35
+ )
36
+ self._restclient = SplightRestClient()
37
+ self._restclient.update_headers(token.header)
38
+ logger.debug(
39
+ "Remote datalake client initialized.", tags=LogTags.DATALAKE
40
+ )
41
+
42
+ @retry(EXCEPTIONS, tries=3, delay=2, jitter=1)
43
+ def save(self, records: Records) -> list[dict]:
44
+ url = self._base_url / f"{self._PREFIX}/write"
45
+ response = self._restclient.post(url, json=records)
46
+ if response.is_error:
47
+ raise DatalakeRequestError(response.status_code, response.text)
48
+ return records["records"]
49
+
50
+ @retry(EXCEPTIONS, tries=3, delay=2, jitter=1)
51
+ async def async_save(
52
+ self,
53
+ records: Records,
54
+ ) -> list[dict]:
55
+ # POST /data/write
56
+ url = self._base_url / f"{self._PREFIX}/write"
57
+ response = await self._restclient.async_post(url, json=records)
58
+ if response.is_error:
59
+ raise DatalakeRequestError(response.status_code, response.text)
60
+ return records["records"]
61
+
62
+ @retry(EXCEPTIONS, tries=3, delay=2, jitter=1)
63
+ def _get(self, request: dict) -> list[dict]:
64
+ url = self._base_url / f"{self._PREFIX}/read"
65
+ response = self._restclient.post(url, json=request)
66
+ if response.is_error:
67
+ raise DatalakeRequestError(response.status_code, response.text)
68
+ return response.json()
69
+
70
+ @retry(EXCEPTIONS, tries=3, delay=2, jitter=1)
71
+ async def _async_get(self, request: dict) -> list[dict]:
72
+ url = self._base_url / f"{self._PREFIX}/read"
73
+ response = await self._restclient.async_post(url, json=request)
74
+ if response.is_error:
75
+ raise DatalakeRequestError(response.status_code, response.text)
76
+ return response.json()
77
+
78
+
79
+ class BufferedAsyncRemoteDatalakeClient(SyncRemoteDatalakeClient):
80
+ _PREFIX = "data"
81
+
82
+ def __init__(
83
+ self,
84
+ base_url: str,
85
+ access_id: str,
86
+ secret_key: str,
87
+ buffer_size: int = DL_BUFFER_SIZE,
88
+ buffer_timeout: float = DL_BUFFER_TIMEOUT,
89
+ *args,
90
+ **kwargs,
91
+ ):
92
+ super().__init__(
93
+ base_url,
94
+ access_id,
95
+ secret_key,
96
+ buffer_size,
97
+ buffer_timeout,
98
+ *args,
99
+ **kwargs,
100
+ )
101
+ self._base_url = furl(base_url)
102
+ token = SplightAuthToken(
103
+ access_key=access_id,
104
+ secret_key=secret_key,
105
+ )
106
+ self._restclient = SplightRestClient()
107
+ self._restclient.update_headers(token.header)
108
+
109
+ logger.debug(
110
+ "Initializing buffer with size %s and timeout %s",
111
+ buffer_size,
112
+ buffer_timeout,
113
+ )
114
+ self._data_buffers = {
115
+ "default": DatalakeDocumentBuffer(buffer_size, buffer_timeout),
116
+ "routine_evaluations": DatalakeDocumentBuffer(
117
+ buffer_size, buffer_timeout
118
+ ),
119
+ }
120
+ self._lock = Lock()
121
+ self._flush_thread = Thread(target=self._flusher, daemon=True)
122
+ self._flush_thread.start()
123
+ logger.debug(
124
+ "Buffered Remote datalake client initialized.",
125
+ tags=LogTags.DATALAKE,
126
+ )
127
+
128
+ def save(self, records: Records) -> list[dict]:
129
+ logger.debug("Saving documents in datalake", tags=LogTags.DATALAKE)
130
+ collection = records["collection"]
131
+ instances = records["records"]
132
+ buffer = self._data_buffers[collection]
133
+ with self._lock:
134
+ if buffer.should_flush():
135
+ logger.debug(
136
+ "Flushing datalake buffer with %s elements",
137
+ len(buffer.data),
138
+ )
139
+ self._send_documents(collection, buffer.data)
140
+ buffer.reset()
141
+ buffer.add_documents(instances)
142
+ return instances
143
+
144
+ def _flusher(self):
145
+ while True:
146
+ for collection, buffer in self._data_buffers.items():
147
+ self._flush_buffer(collection, buffer)
148
+ sleep(0.5)
149
+
150
+ def _flush_buffer(
151
+ self, collection: str, buffer: DatalakeDocumentBuffer
152
+ ) -> None:
153
+ with self._lock:
154
+ if buffer.should_flush():
155
+ try:
156
+ logger.debug(
157
+ "Flushing datalake buffer with %s elements",
158
+ len(buffer.data),
159
+ )
160
+ self._send_documents(collection, buffer.data)
161
+ buffer.reset()
162
+ except Exception:
163
+ logger.error("Unable to save documents", exc_info=True)
164
+
165
+ @retry(EXCEPTIONS, tries=3, delay=2, jitter=1)
166
+ def _send_documents(self, collection: str, docs: list[dict]) -> list[dict]:
167
+ url = self._base_url / f"{self._PREFIX}/write"
168
+ data = {
169
+ "collection": collection,
170
+ "records": docs,
171
+ }
172
+ response = self._restclient.post(url, json=data)
173
+ if response.is_error:
174
+ raise DatalakeRequestError(response.status_code, response.text)
175
+ return docs
176
+
177
+
178
+ class BufferedSyncRemoteDataClient(SyncRemoteDatalakeClient):
179
+ _PREFIX = "data"
180
+
181
+ def __init__(
182
+ self,
183
+ base_url: str,
184
+ access_id: str,
185
+ secret_key: str,
186
+ buffer_size: int = DL_BUFFER_SIZE,
187
+ buffer_timeout: float = DL_BUFFER_TIMEOUT,
188
+ *args,
189
+ **kwargs,
190
+ ):
191
+ super().__init__(
192
+ base_url,
193
+ access_id,
194
+ secret_key,
195
+ buffer_size,
196
+ buffer_timeout,
197
+ *args,
198
+ **kwargs,
199
+ )
200
+ self._base_url = furl(base_url)
201
+ token = SplightAuthToken(
202
+ access_key=access_id,
203
+ secret_key=secret_key,
204
+ )
205
+ self._restclient = SplightRestClient()
206
+ self._restclient.update_headers(token.header)
207
+
208
+ logger.debug(
209
+ "Initializing buffer with size %s and timeout %s",
210
+ buffer_size,
211
+ buffer_timeout,
212
+ tags=LogTags.DATALAKE,
213
+ )
214
+ self._data_buffers = {
215
+ "default": DatalakeDocumentBuffer(buffer_size, buffer_timeout),
216
+ "routine_evaluations": DatalakeDocumentBuffer(
217
+ buffer_size, buffer_timeout
218
+ ),
219
+ }
220
+ self._lock = Lock()
221
+ logger.debug(
222
+ "Synchronous Buffered Remote datalake client initialized.",
223
+ tags=LogTags.DATALAKE,
224
+ )
225
+
226
+ def save(self, records: Records) -> list[dict]:
227
+ logger.debug("Saving documents in datalake", tag=LogTags.DATALAKE)
228
+ collection = records["collection"]
229
+ buffer = self._data_buffers[collection]
230
+ with self._lock:
231
+ buffer.add_documents(records["records"])
232
+ if buffer.should_flush():
233
+ logger.debug(
234
+ "Flushing datalake buffer with %s elements",
235
+ len(buffer.data),
236
+ tags=LogTags.DATALAKE,
237
+ )
238
+ self._send_documents(collection, buffer.data)
239
+ buffer.reset()
240
+ return records["records"]
241
+
242
+ @retry(EXCEPTIONS, tries=3, delay=2, jitter=1)
243
+ def _send_documents(self, collection: str, docs: list[dict]) -> list[dict]:
244
+ url = self._base_url / f"{self._PREFIX}/write"
245
+ data = {
246
+ "collection": collection,
247
+ "records": docs,
248
+ }
249
+ response = self._restclient.post(url, json=data)
250
+ if response.is_error:
251
+ raise DatalakeRequestError(response.status_code, response.text)
252
+ return docs
@@ -40,4 +40,5 @@ class InstanceNotFound(Exception):
40
40
  return self._msg
41
41
 
42
42
 
43
- class InvalidModel(Exception): ...
43
+ class InvalidModel(Exception):
44
+ pass
@@ -65,6 +65,7 @@ def test_save(mocker: MockerFixture):
65
65
  )
66
66
  collection = "collection_name"
67
67
  instances = [{"key": "value"}]
68
- result = client.save(collection=collection, instances=instances)
68
+ records = {"collection": collection, "records": instances}
69
+ result = client.save(records)
69
70
  mock_post.assert_called_once()
70
71
  assert result == instances
@@ -9,7 +9,6 @@ from splight_lib.component.exceptions import (
9
9
  ParameterDependencyError,
10
10
  )
11
11
  from splight_lib.constants import DESCRIPTION_MAX_LENGTH
12
- from splight_lib.models.base import SplightDatalakeBaseModel
13
12
  from splight_lib.models.component import (
14
13
  Component,
15
14
  ComponentObjectInstance,
@@ -22,6 +21,7 @@ from splight_lib.models.component import (
22
21
  Routine,
23
22
  get_field_value,
24
23
  )
24
+ from splight_lib.models.datalake_base import SplightDatalakeBaseModel
25
25
  from splight_lib.utils.custom_model import create_custom_model
26
26
 
27
27
  VALID_PARAMETER_VALUES = {
@@ -10,7 +10,8 @@ from splight_lib.execution.trigger import IntervalTrigger
10
10
 
11
11
  class BaseTask(ABC):
12
12
  @abstractmethod
13
- def as_job(self) -> Dict: ...
13
+ def as_job(self) -> Dict:
14
+ pass
14
15
 
15
16
 
16
17
  class PeriodicTask(BaseTask):
@@ -24,7 +24,6 @@ class LogTags(UppercaseStrEnum):
24
24
  DATABASE = auto()
25
25
  DATALAKE = auto()
26
26
  CACHE = auto()
27
- SERVER = auto()
28
27
 
29
28
 
30
29
  # don't used now
@@ -18,15 +18,14 @@ from splight_lib.models.dashboard import (
18
18
  Filter,
19
19
  Tab,
20
20
  )
21
+ from splight_lib.models.datalake import DataRequest, PipelineStep, Trace
21
22
  from splight_lib.models.file import File
22
23
  from splight_lib.models.function import Function, FunctionItem, QueryFilter
23
24
  from splight_lib.models.hub import HubComponent
24
- from splight_lib.models.hub_server import HubServer
25
25
  from splight_lib.models.hub_solution import HubSolution
26
26
  from splight_lib.models.metadata import Metadata
27
27
  from splight_lib.models.native import Boolean, Number, String
28
28
  from splight_lib.models.secret import Secret
29
- from splight_lib.models.server import Server
30
29
  from splight_lib.models.solution import Solution
31
30
  from splight_lib.models.tag import Tag
32
31
 
@@ -46,23 +45,24 @@ __all__ = [
46
45
  ComponentObject,
47
46
  ComponentObjectInstance,
48
47
  Dashboard,
48
+ DataRequest,
49
49
  File,
50
50
  Filter,
51
51
  Function,
52
52
  FunctionItem,
53
53
  HubSolution,
54
54
  HubComponent,
55
- HubServer,
56
55
  QueryFilter,
57
56
  Metadata,
58
57
  Number,
58
+ PipelineStep,
59
59
  RoutineEvaluation,
60
60
  Secret,
61
- Server,
62
61
  SetPoint,
63
62
  Solution,
64
63
  String,
65
64
  RoutineObject,
66
65
  RoutineObjectInstance,
67
66
  Tab,
67
+ Trace,
68
68
  ]
@@ -1,6 +1,9 @@
1
1
  from datetime import datetime
2
2
 
3
- from splight_lib.models.base import ResourceSummary, SplightDatabaseBaseModel
3
+ from splight_lib.models.database_base import (
4
+ ResourceSummary,
5
+ SplightDatabaseBaseModel,
6
+ )
4
7
 
5
8
 
6
9
  class SetPoint(SplightDatabaseBaseModel):
@@ -14,7 +14,7 @@ from strenum import LowercaseStrEnum, UppercaseStrEnum
14
14
  from typing_extensions import TypedDict
15
15
 
16
16
  from splight_lib.constants import DESCRIPTION_MAX_LENGTH
17
- from splight_lib.models.base import SplightDatabaseBaseModel
17
+ from splight_lib.models.database_base import SplightDatabaseBaseModel
18
18
  from splight_lib.models.exceptions import (
19
19
  InvalidAlertConfiguration,
20
20
  MissingAlertItemExpression,
@@ -6,7 +6,10 @@ from pydantic import BaseModel, Field
6
6
 
7
7
  from splight_lib.constants import DESCRIPTION_MAX_LENGTH
8
8
  from splight_lib.models.attribute import Attribute
9
- from splight_lib.models.base import ResourceSummary, SplightDatabaseBaseModel
9
+ from splight_lib.models.database_base import (
10
+ ResourceSummary,
11
+ SplightDatabaseBaseModel,
12
+ )
10
13
  from splight_lib.models.exceptions import MethodNotAllowed
11
14
  from splight_lib.models.metadata import Metadata
12
15
  from splight_lib.models.tag import Tag
@@ -3,7 +3,7 @@ from typing import Optional
3
3
 
4
4
  from strenum import PascalCaseStrEnum
5
5
 
6
- from splight_lib.models.base import SplightDatabaseBaseModel
6
+ from splight_lib.models.database_base import SplightDatabaseBaseModel
7
7
 
8
8
 
9
9
  class AttributeType(PascalCaseStrEnum):
@@ -20,11 +20,9 @@ from splight_lib.constants import DESCRIPTION_MAX_LENGTH
20
20
  from splight_lib.execution.scheduling import Crontab
21
21
  from splight_lib.models.asset import Asset
22
22
  from splight_lib.models.attribute import Attribute
23
- from splight_lib.models.base import (
24
- SplightDatabaseBaseModel,
25
- SplightDatalakeBaseModel,
26
- )
27
23
  from splight_lib.models.data_address import DataAddresses as DLDataAddress
24
+ from splight_lib.models.database_base import SplightDatabaseBaseModel
25
+ from splight_lib.models.datalake_base import SplightDatalakeBaseModel
28
26
  from splight_lib.models.exceptions import InvalidObjectInstance
29
27
  from splight_lib.models.file import File
30
28
  from splight_lib.models.secret import Secret
@@ -3,7 +3,7 @@ from typing import Any, Dict, List, Optional
3
3
  from pydantic import Field
4
4
 
5
5
  from splight_lib.constants import DESCRIPTION_MAX_LENGTH
6
- from splight_lib.models.base import SplightDatabaseBaseModel
6
+ from splight_lib.models.database_base import SplightDatabaseBaseModel
7
7
 
8
8
 
9
9
  class Filter(SplightDatabaseBaseModel):
@@ -39,9 +39,7 @@ class ChartItem(SplightDatabaseBaseModel):
39
39
  aggregate_period: Optional[str] = None
40
40
  source: Optional[str] = None
41
41
  source_label: Optional[str] = None
42
- source_type: Optional[str] = (
43
- None # TODO: define options (component, native)
44
- )
42
+ source_type: Optional[str] = None
45
43
  source_component_label: Optional[str] = None
46
44
  source_component_id: Optional[str] = None
47
45
  output_format: Optional[str] = None