splight-lib 5.10.1.dev1__tar.gz → 5.10.2__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 (106) hide show
  1. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/PKG-INFO +1 -1
  2. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/pyproject.toml +1 -1
  3. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/abstract/client.py +4 -3
  4. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/client/database/classmap.py +0 -4
  5. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/client/database/remote_client.py +2 -6
  6. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/client/datalake/abstract.py +5 -3
  7. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/client/datalake/remote_client.py +1 -1
  8. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/logging/_internal.py +0 -1
  9. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/__init__.py +0 -4
  10. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/datalake_base.py +3 -2
  11. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/exceptions.py +0 -9
  12. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/function.py +9 -2
  13. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/solution/solution.py +1 -1
  14. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/tests/test_api_contracts.py +6 -1
  15. splight_lib-5.10.1.dev1/splight_lib/models/hub_server.py +0 -118
  16. splight_lib-5.10.1.dev1/splight_lib/models/server.py +0 -211
  17. splight_lib-5.10.1.dev1/splight_lib/server/__init__.py +0 -5
  18. splight_lib-5.10.1.dev1/splight_lib/server/exceptions.py +0 -3
  19. splight_lib-5.10.1.dev1/splight_lib/server/server.py +0 -16
  20. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/LICENSE.txt +0 -0
  21. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/README.md +0 -0
  22. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/__init__.py +0 -0
  23. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/abstract/__init__.py +0 -0
  24. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/auth/__init__.py +0 -0
  25. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/auth/exceptions.py +0 -0
  26. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/auth/mac_auth.py +0 -0
  27. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/auth/token.py +0 -0
  28. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/client/__init__.py +0 -0
  29. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/client/database/__init__.py +0 -0
  30. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/client/database/abstract.py +0 -0
  31. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/client/database/builder.py +0 -0
  32. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/client/datalake/__init__.py +0 -0
  33. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/client/datalake/buffer.py +0 -0
  34. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/client/datalake/builder.py +0 -0
  35. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/client/datalake/constants.py +0 -0
  36. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/client/datalake/exceptions.py +0 -0
  37. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/client/exceptions.py +0 -0
  38. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/client/file_handler.py +0 -0
  39. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/client/filter.py +0 -0
  40. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/client/hub/__init__.py +0 -0
  41. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/client/hub/abstract.py +0 -0
  42. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/client/hub/client.py +0 -0
  43. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/client/tests/test_database.py +0 -0
  44. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/client/tests/test_datalake.py +0 -0
  45. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/component/__init__.py +0 -0
  46. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/component/abstract.py +0 -0
  47. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/component/exceptions.py +0 -0
  48. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/component/spec.py +0 -0
  49. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/component/tests/test_abstract.py +0 -0
  50. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/component/tests/test_spec.py +0 -0
  51. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/conftest.py +0 -0
  52. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/constants.py +0 -0
  53. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/encryption.py +0 -0
  54. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/execution/__init__.py +0 -0
  55. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/execution/engine.py +0 -0
  56. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/execution/exceptions.py +0 -0
  57. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/execution/scheduling.py +0 -0
  58. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/execution/task.py +0 -0
  59. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/execution/tests/test_execution.py +0 -0
  60. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/execution/tests/test_scheduling.py +0 -0
  61. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/execution/trigger.py +0 -0
  62. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/logging/__init__.py +0 -0
  63. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/logging/component.py +0 -0
  64. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/logging/constants.py +0 -0
  65. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/logging/logging.py +0 -0
  66. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/logging/tests/test_logging.py +0 -0
  67. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/actions.py +0 -0
  68. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/alert.py +0 -0
  69. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/asset.py +0 -0
  70. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/attribute.py +0 -0
  71. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/component.py +0 -0
  72. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/dashboard.py +0 -0
  73. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/data_address.py +0 -0
  74. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/database_base.py +0 -0
  75. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/datalake.py +0 -0
  76. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/file.py +0 -0
  77. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/generic.py +0 -0
  78. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/hub.py +0 -0
  79. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/hub_solution.py +0 -0
  80. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/metadata.py +0 -0
  81. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/native.py +0 -0
  82. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/secret.py +0 -0
  83. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/solution.py +0 -0
  84. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/tag.py +0 -0
  85. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/tests/models.json +0 -0
  86. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/tests/test_component_object_instance.py +0 -0
  87. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/tests/test_database_model.py +0 -0
  88. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/tests/test_metadata.py +0 -0
  89. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/models/tests/test_models.py +0 -0
  90. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/restclient/__init__.py +0 -0
  91. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/restclient/client.py +0 -0
  92. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/restclient/exceptions.py +0 -0
  93. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/restclient/tests/test_restclient.py +0 -0
  94. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/restclient/types.py +0 -0
  95. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/settings.py +0 -0
  96. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/solution/__init__.py +0 -0
  97. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/solution/exceptions.py +0 -0
  98. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/stringcase.py +0 -0
  99. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/testing/__init__.py +0 -0
  100. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/tests/FakeProc.py +0 -0
  101. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/tests/asset_geometries.json +0 -0
  102. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/tests/test_encryption.py +0 -0
  103. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/utils/__init__.py +0 -0
  104. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/utils/custom_model.py +0 -0
  105. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/utils/hub.py +0 -0
  106. {splight_lib-5.10.1.dev1 → splight_lib-5.10.2}/splight_lib/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: splight-lib
3
- Version: 5.10.1.dev1
3
+ Version: 5.10.2
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.10.1.dev1"
3
+ version = "5.10.2"
4
4
  description = "Splight Library"
5
5
  authors = ["Splight Dev <dev@splight-ae.com>"]
6
6
  readme = "README.md"
@@ -32,6 +32,7 @@ class AbstractRemoteClient(AbstractClient):
32
32
  return params
33
33
 
34
34
 
35
+ # TODO: Remove this class
35
36
  class QuerySet(UserList):
36
37
  def __init__(
37
38
  self,
@@ -70,7 +71,7 @@ class QuerySet(UserList):
70
71
  return self._cached_results[i]
71
72
 
72
73
  if isinstance(i, slice):
73
- skip_ = self._kwargs.get("skip_", 0) + i.start
74
+ # skip_ = self._kwargs.get("skip_", 0) + i.start
74
75
 
75
76
  limit_ = i.stop - i.start
76
77
  if "limit_" in self._kwargs:
@@ -78,8 +79,8 @@ class QuerySet(UserList):
78
79
  limit_ = min(limit_, old_limit_)
79
80
 
80
81
  kwargs = {**self._kwargs}
81
- kwargs["skip_"] = skip_
82
- kwargs["limit_"] = limit_
82
+ # kwargs["skip_"] = skip_
83
+ # kwargs["limit_"] = limit_
83
84
  kwargs.pop("get_func", None)
84
85
  kwargs.pop("count_func", None)
85
86
  return QuerySet(
@@ -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 = {
@@ -36,5 +33,4 @@ CUSTOM_PATHS_MAP = {
36
33
  "get-asset-attribute": "{prefix}/assets/{asset}/get-attribute/",
37
34
  "decrypt-secret": "{prefix}/secrets/decrypt/",
38
35
  "routine-status": "{prefix}/component/routines/{routine}/update_status/",
39
- "server-status": "{prefix}/server/servers/{server}/update-status/",
40
36
  }
@@ -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")
@@ -9,11 +9,13 @@ class Records(TypedDict):
9
9
  records: list[dict[str, Any]]
10
10
 
11
11
 
12
+ # TODO: Fix this class after delete QuerySet
12
13
  class AbstractDatalakeClient(AbstractRemoteClient):
13
14
  def get(self, *args, **kwargs) -> QuerySet:
14
- kwargs["get_func"] = "_get"
15
- kwargs["count_func"] = "None"
16
- return QuerySet(self, *args, **kwargs)
15
+ # kwargs["get_func"] = "_get"
16
+ # kwargs["count_func"] = "None"
17
+ # return QuerySet(self, *args, **kwargs)
18
+ return self._get(*args, **kwargs)
17
19
 
18
20
  async def async_get(self, *args, **kwargs):
19
21
  # TODO: consider using an async QuerySet
@@ -224,7 +224,7 @@ class BufferedSyncRemoteDataClient(SyncRemoteDatalakeClient):
224
224
  )
225
225
 
226
226
  def save(self, records: Records) -> list[dict]:
227
- logger.debug("Saving documents in datalake", tag=LogTags.DATALAKE)
227
+ logger.debug("Saving documents in datalake", tags=LogTags.DATALAKE)
228
228
  collection = records["collection"]
229
229
  buffer = self._data_buffers[collection]
230
230
  with self._lock:
@@ -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
@@ -22,12 +22,10 @@ from splight_lib.models.datalake import DataRequest, PipelineStep, Trace
22
22
  from splight_lib.models.file import File
23
23
  from splight_lib.models.function import Function, FunctionItem, QueryFilter
24
24
  from splight_lib.models.hub import HubComponent
25
- from splight_lib.models.hub_server import HubServer
26
25
  from splight_lib.models.hub_solution import HubSolution
27
26
  from splight_lib.models.metadata import Metadata
28
27
  from splight_lib.models.native import Boolean, Number, String
29
28
  from splight_lib.models.secret import Secret
30
- from splight_lib.models.server import Server
31
29
  from splight_lib.models.solution import Solution
32
30
  from splight_lib.models.tag import Tag
33
31
 
@@ -54,14 +52,12 @@ __all__ = [
54
52
  FunctionItem,
55
53
  HubSolution,
56
54
  HubComponent,
57
- HubServer,
58
55
  QueryFilter,
59
56
  Metadata,
60
57
  Number,
61
58
  PipelineStep,
62
59
  RoutineEvaluation,
63
60
  Secret,
64
- Server,
65
61
  SetPoint,
66
62
  Solution,
67
63
  String,
@@ -62,8 +62,9 @@ class SplightDatalakeBaseModel(BaseModel):
62
62
  )
63
63
  instances = request.apply()
64
64
  df = pd.DataFrame([instance.dict() for instance in instances])
65
- df.index = df["timestamp"]
66
- df.drop(columns="timestamp", inplace=True)
65
+ if not df.empty:
66
+ df.index = df["timestamp"]
67
+ df.drop(columns="timestamp", inplace=True)
67
68
  return df
68
69
 
69
70
  def save(self) -> None:
@@ -66,15 +66,6 @@ class InvalidArgument(Exception):
66
66
  pass
67
67
 
68
68
 
69
- class InvalidServerConfigType(Exception):
70
- def __init__(self, name: str, type_: str):
71
- msg = (
72
- f"Config parameter {name} has an invalid type {type_}. The only "
73
- "valid types are native and 'File'"
74
- )
75
- super().__init__(msg)
76
-
77
-
78
69
  class TraceAlreadyExistsError(Exception):
79
70
  def __init__(self, ref_id: str):
80
71
  msg = f"Trace with ref_id {ref_id} already exists"
@@ -19,6 +19,7 @@ from splight_lib.models.exceptions import (
19
19
  InvalidFunctionConfiguration,
20
20
  MissingFunctionItemExpression,
21
21
  )
22
+ from splight_lib.models.generic import ValueTypeEnum
22
23
 
23
24
 
24
25
  class FunctionItemType(UppercaseStrEnum):
@@ -31,6 +32,12 @@ class QueryFilter(TypedDict):
31
32
  name: str
32
33
 
33
34
 
35
+ class TypedQueryFilter(TypedDict):
36
+ id: str
37
+ name: str
38
+ type: ValueTypeEnum
39
+
40
+
34
41
  class GroupUnit(LowercaseStrEnum):
35
42
  EMPTY = ""
36
43
  SECOND = auto()
@@ -62,7 +69,7 @@ class FunctionItem(BaseModel):
62
69
  expression_plain: str = ""
63
70
 
64
71
  query_filter_asset: Optional[QueryFilter] = None
65
- query_filter_attribute: Optional[QueryFilter] = None
72
+ query_filter_attribute: Optional[TypedQueryFilter] = None
66
73
 
67
74
  query_group_function: GroupCriteria = GroupCriteria.EMPTY
68
75
  query_group_unit: GroupUnit = GroupUnit.EMPTY
@@ -170,7 +177,7 @@ class Function(SplightDatabaseBaseModel):
170
177
  type: Literal["cron", "rate"]
171
178
  target_variable: str
172
179
  target_asset: QueryFilter # NOTE: optional in API
173
- target_attribute: QueryFilter # NOTE: optional in API
180
+ target_attribute: TypedQueryFilter # NOTE: optional in API
174
181
 
175
182
  cron_minutes: Optional[str] = None
176
183
  cron_hours: Optional[str] = None
@@ -15,7 +15,7 @@ class SolutionLoader:
15
15
  def from_env(cls) -> Solution:
16
16
  if not (str_instance := os.environ.get(ENV_VAR)):
17
17
  raise MissingInstanceEnvVar(ENV_VAR)
18
- str_instance = os.environ.get(ENV_VAR, "")
18
+ str_instance = os.environ.get("INSTANCE_AS_STR", "")
19
19
  instance = json.loads(str_instance)
20
20
  if not (instance_id := instance.get("id")):
21
21
  raise MissingInstanceId()
@@ -73,6 +73,7 @@ class AttributeFactory(ModelFactory[Attribute]):
73
73
  id: str = Use(lambda: str(uuid.uuid4()))
74
74
  asset: str = Use(lambda: str(uuid.uuid4()))
75
75
  unit: str = Use(lambda: random.choice(["m", "cm", "mm"]))
76
+ type: str = Use(lambda: random.choice(["Number", "String", "Boolean"]))
76
77
 
77
78
 
78
79
  class AssetFactory(ModelFactory[Asset]):
@@ -89,7 +90,11 @@ class FunctionItemFactory(ModelFactory[FunctionItem]):
89
90
  lambda: {"id": str(uuid.uuid4()), "name": "asset"}
90
91
  )
91
92
  query_filter_attribute = Use(
92
- lambda: {"id": str(uuid.uuid4()), "name": "attribute"}
93
+ lambda: {
94
+ "id": str(uuid.uuid4()),
95
+ "name": "attribute",
96
+ "type": "Number",
97
+ }
93
98
  )
94
99
 
95
100
 
@@ -1,118 +0,0 @@
1
- import os
2
- from glob import glob
3
- from tempfile import NamedTemporaryFile
4
- from typing import Dict, List, Optional
5
-
6
- import py7zr
7
- from pydantic import BaseModel, Field
8
-
9
- from splight_lib.constants import DESCRIPTION_MAX_LENGTH
10
- from splight_lib.models.database_base import (
11
- FilePath,
12
- PrivacyPolicy,
13
- SplightDatabaseBaseModel,
14
- )
15
- from splight_lib.models.component import InputParameter
16
- from splight_lib.utils.hub import (
17
- COMPRESSION_TYPE,
18
- README_FILE_1,
19
- get_ignore_pathspec,
20
- get_spec,
21
- )
22
-
23
-
24
- class Port(BaseModel):
25
- name: Optional[str]
26
- protocol: str = "tcp"
27
- internal_port: int
28
- exposed_port: int
29
-
30
-
31
- class HubServer(SplightDatabaseBaseModel):
32
- id: Optional[str] = None
33
- name: str
34
- version: str
35
- description: Optional[str] = Field(
36
- default=None, max_length=DESCRIPTION_MAX_LENGTH
37
- )
38
- tags: Optional[List[str]] = Field(default=[])
39
- privacy_policy: PrivacyPolicy = PrivacyPolicy.PUBLIC
40
-
41
- config: List[InputParameter] = []
42
- ports: List[Port] = []
43
- environment: List[Dict[str, str]] = []
44
-
45
- @classmethod
46
- def upload(cls, path: FilePath, image_file: str) -> "HubServer":
47
- db_client = cls._SplightDatabaseBaseModel__get_database_client()
48
- image_path = os.path.join(path, image_file)
49
- spec = get_spec(path)
50
- name = spec.get("name")
51
- version = spec.get("version")
52
-
53
- raw_hub_server = db_client.get(
54
- resource_name=cls.__name__,
55
- name=name,
56
- version=version,
57
- )
58
- server = cls.model_validate(spec)
59
- if raw_hub_server:
60
- old_hub_server = cls.model_validate(raw_hub_server[0])
61
- server.id = old_hub_server.id
62
-
63
- server.save()
64
-
65
- file_name = f"{name}-{version}.{COMPRESSION_TYPE}"
66
- ignore_pathspec = get_ignore_pathspec(path)
67
- versioned_path = f"{name}-{version}"
68
- # TODO: Add required files validations
69
- readme_path = os.path.join(path, README_FILE_1)
70
- if not os.path.exists(readme_path):
71
- raise FileNotFoundError(f"README.md file not found: {readme_path}")
72
- with py7zr.SevenZipFile(file_name, "w") as archive:
73
- all_files = glob(f"{path}/**", recursive=True)
74
- for filepath in all_files:
75
- if ignore_pathspec and ignore_pathspec.match_file(filepath):
76
- continue
77
- if os.path.isdir(filepath):
78
- continue
79
- if image_file in filepath:
80
- continue
81
- rel_filename = os.path.relpath(filepath, path)
82
- new_filepath = os.path.join(versioned_path, rel_filename)
83
- archive.write(filepath, new_filepath)
84
-
85
- data = server.model_dump()
86
- try:
87
- db_client.upload(
88
- "hubserverversion",
89
- instance=data,
90
- file_path=file_name,
91
- type_="source",
92
- )
93
- db_client.upload(
94
- "hubserverversion",
95
- instance=data,
96
- file_path=readme_path,
97
- type_="readme",
98
- )
99
- db_client.upload(
100
- "hubserverversion",
101
- instance=data,
102
- file_path=image_path,
103
- type_="image",
104
- )
105
- except Exception as exc:
106
- raise exc
107
- finally:
108
- if os.path.exists(file_name):
109
- os.remove(file_name)
110
- return server
111
-
112
- def download(self) -> NamedTemporaryFile:
113
- db_client = self._SplightDatabaseBaseModel__get_database_client()
114
- return db_client.download(
115
- resource_name="hubserverversion",
116
- instance=self.model_dump(),
117
- type_="source",
118
- )
@@ -1,211 +0,0 @@
1
- import re
2
- import warnings
3
- from collections import namedtuple
4
- from datetime import datetime
5
- from enum import auto
6
- from typing import Any, NamedTuple, Optional
7
-
8
- from pydantic import AnyUrl, BaseModel, Field, computed_field
9
- from strenum import LowercaseStrEnum, PascalCaseStrEnum
10
-
11
- from splight_lib.models.database_base import SplightDatabaseBaseModel
12
- from splight_lib.models.exceptions import (
13
- InvalidArgument,
14
- InvalidServerConfigType,
15
- )
16
- from splight_lib.models.file import File
17
- from splight_lib.models.hub_server import HubServer
18
- from splight_lib.models.secret import Secret
19
-
20
- warnings.filterwarnings("ignore", category=RuntimeWarning)
21
-
22
- NATIVE_TYPES = {
23
- "int": int,
24
- "bool": bool,
25
- "str": str,
26
- "float": float,
27
- "datetime": datetime,
28
- "url": AnyUrl,
29
- }
30
-
31
- DATABASE_TYPES = {
32
- "File": File,
33
- }
34
-
35
- DB_MODEL_TYPE_MAPPING = {
36
- **NATIVE_TYPES,
37
- **DATABASE_TYPES,
38
- }
39
-
40
-
41
- def get_field_value(field: dict):
42
- field_multiple = field.get("multiple", False)
43
- field_type = field.get("type")
44
- field_value = field.get("value")
45
-
46
- if not field_value:
47
- return [] if field_multiple else None
48
-
49
- if field_type in NATIVE_TYPES:
50
- value = (
51
- field_value
52
- if not isinstance(field_value, str)
53
- else parse_variable_string(field_value)
54
- )
55
- elif field_type in DATABASE_TYPES:
56
- model_class = DATABASE_TYPES[field_type]
57
- value = (
58
- model_class.retrieve(field_value)
59
- if not field_multiple
60
- else [model_class.retrieve(item) for item in field_value]
61
- )
62
- return value
63
-
64
-
65
- def get_model_class(config: BaseModel, name: str) -> NamedTuple:
66
- config_class = namedtuple(name, [x.name for x in config])
67
- return config_class
68
-
69
-
70
- def load_server_config(
71
- config: list[dict], config_class: NamedTuple
72
- ) -> NamedTuple:
73
- config_dict = {}
74
- for item in config:
75
- if item["type"] not in DB_MODEL_TYPE_MAPPING:
76
- raise InvalidServerConfigType(item["name"], item["type"])
77
- config_dict.update({item["name"]: get_field_value(item)})
78
- config = config_class(**config_dict)
79
- return config
80
-
81
-
82
- def load_server_ports(
83
- ports: list[dict], model_class: NamedTuple
84
- ) -> namedtuple:
85
- ports_dict = {}
86
- for port in ports:
87
- if isinstance(port["internal_port"], int) and not (
88
- 0 <= port["internal_port"] <= 65535
89
- ):
90
- raise ValueError(
91
- f"Internal port {port['internal_port']} is out of valid range (0-65535)"
92
- )
93
- if isinstance(port["exposed_port"], int) and not (
94
- 0 <= port["exposed_port"] <= 65535
95
- ):
96
- raise ValueError(
97
- f"External port {port['exposed_port']} is out of valid range (0-65535)"
98
- )
99
- if port["protocol"] not in ["tcp", "udp"]:
100
- raise ValueError(
101
- f"Protocol {port['protocol']} is not valid. Must be 'tcp' or 'udp'"
102
- )
103
- ports_dict.update({port["name"]: port})
104
- resources = model_class(**ports_dict)
105
- return resources
106
-
107
-
108
- class ServerStatus(PascalCaseStrEnum):
109
- RUNNING = auto()
110
- FAILED = auto()
111
- SUCCEEDED = auto()
112
- PENDING = auto()
113
- START_REQUESTED = auto()
114
- STOP_REQUESTED = auto()
115
- STOPPED = auto()
116
- UNKNOWN = auto()
117
-
118
-
119
- class PrivacyPolicy(LowercaseStrEnum):
120
- PUBLIC = auto()
121
- PRIVATE = auto()
122
-
123
-
124
- class Port(BaseModel):
125
- name: Optional[str]
126
- internal_port: int
127
- exposed_port: int
128
-
129
-
130
- class Server(SplightDatabaseBaseModel):
131
- id: Optional[str] = None
132
- name: Optional[str] = None
133
- version: str
134
- hub_server: HubServer
135
- raw_config: list[dict] = Field(alias="config")
136
- raw_ports: list[dict] = Field(alias="ports")
137
- raw_env_vars: list[dict] = Field(alias="env_vars")
138
-
139
- def model_dump(self, *args, **kwargs):
140
- kwargs.update({"by_alias": True})
141
- return super().model_dump(*args, **kwargs)
142
-
143
- def model_dump_json(self, *args, **kwargs):
144
- kwargs.update({"by_alias": True})
145
- return super().model_dump_json(*args, **kwargs)
146
-
147
- @computed_field(alias="parsed_config")
148
- @property
149
- def config(self) -> NamedTuple:
150
- model_class = get_model_class(self.hub_server.config, "Config")
151
- config = load_server_config(self.raw_config, model_class)
152
- return config
153
-
154
- @computed_field(alias="parsed_ports")
155
- @property
156
- def ports(self) -> NamedTuple:
157
- model_class = get_model_class(self.hub_server.ports, "Ports")
158
- ports = load_server_ports(self.raw_ports, model_class)
159
- return ports
160
-
161
- def update_config(self, **kwargs: dict):
162
- valid_params = [x["name"] for x in self.raw_config]
163
- for key, value in kwargs.items():
164
- if key not in valid_params:
165
- raise InvalidArgument(
166
- (
167
- f"Got invalid parameter {key}. Valid config parameter "
168
- f"are {valid_params}"
169
- )
170
- )
171
- for item in self.raw_config:
172
- if item["name"] == key:
173
- item["value"] = value
174
- break
175
-
176
- def update_ports(self, **kwargs: dict):
177
- valid_params = [x["name"] for x in self.raw_ports]
178
- for key, value in kwargs.items():
179
- if key not in valid_params:
180
- raise InvalidArgument(
181
- (
182
- f"Got invalid parameter {key}. Valid port "
183
- f"parameter are {valid_params}"
184
- )
185
- )
186
- for item in self.raw_ports:
187
- if item["name"] == key:
188
- item["value"] = value
189
- break
190
-
191
- def update_status(self, status: ServerStatus):
192
- _ = self._db_client.operate(
193
- resource_name="server-status",
194
- instance={
195
- "server": self.id,
196
- "deployment_status": status,
197
- },
198
- )
199
-
200
-
201
- def parse_variable_string(raw_value: Optional[str]) -> Any:
202
- if raw_value is None:
203
- return ""
204
- pattern = re.compile(r"^\$\{\{(\w+)\.(\w+)\}\}$")
205
- match = pattern.search(raw_value)
206
- if not match:
207
- return raw_value
208
- _, secret_name = match.groups()
209
- # TODO: handle errors (not found or not allowed)
210
- secret = Secret.decrypt(name=secret_name)
211
- return secret.value
@@ -1,5 +0,0 @@
1
- from splight_lib.server.server import ServerLoader
2
-
3
- __all__ = [
4
- ServerLoader,
5
- ]
@@ -1,3 +0,0 @@
1
- class MissingInstanceEnvVar(Exception):
2
- def __init__(self, env_var: str):
3
- super().__init__(f"Missing environment variable: {env_var}")
@@ -1,16 +0,0 @@
1
- import json
2
- import os
3
-
4
- from splight_lib.models import Server
5
- from splight_lib.server.exceptions import MissingInstanceEnvVar
6
-
7
- ENV_VAR = "SPLIGHT_SERVER_ID"
8
-
9
-
10
- class ServerLoader:
11
- @classmethod
12
- def from_env(cls) -> Server:
13
- if not (instance_id := os.environ.get(ENV_VAR)):
14
- raise MissingInstanceEnvVar(ENV_VAR)
15
- server = Server.retrieve(instance_id)
16
- return server