splight-lib 5.7.0__tar.gz → 5.7.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.
- {splight_lib-5.7.0 → splight_lib-5.7.2}/PKG-INFO +1 -1
- {splight_lib-5.7.0 → splight_lib-5.7.2}/pyproject.toml +1 -1
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/client/database/__init__.py +0 -6
- splight_lib-5.7.2/splight_lib/client/database/builder.py +11 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/client/datalake/__init__.py +0 -2
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/client/datalake/builder.py +0 -2
- splight_lib-5.7.2/splight_lib/conftest.py +10 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/models/base.py +0 -3
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/models/hub_solution.py +8 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/models/pipeline.py +0 -1
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/models/tests/test_component_object_instance.py +0 -2
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/models/tests/test_database_model.py +0 -3
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/settings.py +2 -16
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/testing/__init__.py +0 -3
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/tests/test_api_contracts.py +1 -15
- splight_lib-5.7.0/splight_lib/client/database/builder.py +0 -17
- splight_lib-5.7.0/splight_lib/client/database/local_client.py +0 -187
- splight_lib-5.7.0/splight_lib/client/datalake/local_client.py +0 -119
- {splight_lib-5.7.0 → splight_lib-5.7.2}/LICENSE.txt +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/README.md +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/__init__.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/abstract/__init__.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/abstract/client.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/auth/__init__.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/auth/exceptions.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/auth/mac_auth.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/auth/token.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/client/__init__.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/client/database/abstract.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/client/database/classmap.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/client/database/remote_client.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/client/datalake/abstract.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/client/datalake/buffer.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/client/datalake/exceptions.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/client/datalake/remote_client.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/client/datalake/schemas.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/client/exceptions.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/client/file_handler.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/client/filter.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/client/hub/__init__.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/client/hub/abstract.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/client/hub/client.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/client/tests/test_database.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/client/tests/test_datalake.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/component/__init__.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/component/abstract.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/component/exceptions.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/component/spec.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/component/tests/test_abstract.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/component/tests/test_spec.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/constants.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/encryption.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/execution/__init__.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/execution/engine.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/execution/exceptions.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/execution/scheduling.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/execution/task.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/execution/tests/test_execution.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/execution/tests/test_scheduling.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/execution/trigger.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/logging/__init__.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/logging/_internal.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/logging/component.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/logging/constants.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/logging/logging.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/logging/tests/test_logging.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/models/__init__.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/models/alert.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/models/asset.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/models/attribute.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/models/component.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/models/dashboard.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/models/data_address.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/models/exceptions.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/models/file.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/models/function.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/models/generic.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/models/hub.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/models/metadata.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/models/native.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/models/secret.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/models/tests/models.json +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/models/tests/test_metadata.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/models/tests/test_models.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/restclient/__init__.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/restclient/client.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/restclient/exceptions.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/restclient/tests/test_restclient.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/restclient/types.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/stringcase.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/tests/FakeProc.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/tests/asset_geometries.json +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/tests/test_encryption.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/utils/__init__.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/utils/custom_model.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/utils/hub.py +0 -0
- {splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/version.py +0 -0
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
from splight_lib.client.database.builder import DatabaseClientBuilder
|
|
2
|
-
from splight_lib.client.database.local_client import (
|
|
3
|
-
LOCAL_DB_FILE,
|
|
4
|
-
LocalDatabaseClient,
|
|
5
|
-
)
|
|
6
2
|
from splight_lib.client.database.remote_client import RemoteDatabaseClient
|
|
7
3
|
|
|
8
4
|
__all__ = [
|
|
9
|
-
LocalDatabaseClient,
|
|
10
5
|
DatabaseClientBuilder,
|
|
11
6
|
RemoteDatabaseClient,
|
|
12
|
-
LOCAL_DB_FILE,
|
|
13
7
|
]
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from typing import Any, Dict
|
|
2
|
+
|
|
3
|
+
from splight_lib.client.database.abstract import AbstractDatabaseClient
|
|
4
|
+
from splight_lib.client.database.remote_client import RemoteDatabaseClient
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class DatabaseClientBuilder:
|
|
8
|
+
@staticmethod
|
|
9
|
+
def build(parameters: Dict[str, Any] = {}) -> AbstractDatabaseClient:
|
|
10
|
+
db_client = RemoteDatabaseClient(**parameters)
|
|
11
|
+
return db_client
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from splight_lib.client.datalake.builder import DatalakeClientBuilder
|
|
2
|
-
from splight_lib.client.datalake.local_client import LocalDatalakeClient
|
|
3
2
|
from splight_lib.client.datalake.remote_client import (
|
|
4
3
|
BufferedAsyncRemoteDatalakeClient,
|
|
5
4
|
BufferedSyncRemoteDataClient,
|
|
@@ -11,5 +10,4 @@ __all__ = [
|
|
|
11
10
|
SyncRemoteDatalakeClient,
|
|
12
11
|
BufferedAsyncRemoteDatalakeClient,
|
|
13
12
|
BufferedSyncRemoteDataClient,
|
|
14
|
-
LocalDatalakeClient,
|
|
15
13
|
]
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from typing import Any, Dict
|
|
2
2
|
|
|
3
3
|
from splight_lib.client.datalake.abstract import AbstractDatalakeClient
|
|
4
|
-
from splight_lib.client.datalake.local_client import LocalDatalakeClient
|
|
5
4
|
from splight_lib.client.datalake.remote_client import (
|
|
6
5
|
BufferedAsyncRemoteDatalakeClient,
|
|
7
6
|
BufferedSyncRemoteDataClient,
|
|
@@ -13,7 +12,6 @@ DL_CLIENT_TYPE_MAP = {
|
|
|
13
12
|
DatalakeClientType.BUFFERED_ASYNC: BufferedAsyncRemoteDatalakeClient,
|
|
14
13
|
DatalakeClientType.BUFFERED_SYNC: BufferedSyncRemoteDataClient,
|
|
15
14
|
DatalakeClientType.SYNC: SyncRemoteDatalakeClient,
|
|
16
|
-
DatalakeClientType.LOCAL: LocalDatalakeClient,
|
|
17
15
|
}
|
|
18
16
|
|
|
19
17
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from splight_lib.client.database.abstract import AbstractDatabaseClient
|
|
4
|
+
from splight_lib.client.datalake.abstract import AbstractDatalakeClient
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@pytest.fixture(autouse=True)
|
|
8
|
+
def reset_singletons():
|
|
9
|
+
AbstractDatabaseClient._instances = {}
|
|
10
|
+
AbstractDatalakeClient._instances = {}
|
|
@@ -67,9 +67,7 @@ class SplightDatabaseBaseModel(BaseModel):
|
|
|
67
67
|
@staticmethod
|
|
68
68
|
def __get_database_client() -> AbstractDatabaseClient:
|
|
69
69
|
db_client = DatabaseClientBuilder.build(
|
|
70
|
-
local=settings.LOCAL_ENVIRONMENT,
|
|
71
70
|
parameters={
|
|
72
|
-
"path": settings.CURRENT_DIR,
|
|
73
71
|
"base_url": settings.SPLIGHT_PLATFORM_API_HOST,
|
|
74
72
|
"access_id": settings.SPLIGHT_ACCESS_ID,
|
|
75
73
|
"secret_key": settings.SPLIGHT_SECRET_KEY,
|
|
@@ -182,7 +180,6 @@ class SplightDatalakeBaseModel(BaseModel):
|
|
|
182
180
|
db_client = DatalakeClientBuilder.build(
|
|
183
181
|
dl_client_type=settings.DL_CLIENT_TYPE,
|
|
184
182
|
parameters={
|
|
185
|
-
"path": settings.CURRENT_DIR,
|
|
186
183
|
"base_url": settings.SPLIGHT_PLATFORM_API_HOST,
|
|
187
184
|
"access_id": settings.SPLIGHT_ACCESS_ID,
|
|
188
185
|
"secret_key": settings.SPLIGHT_SECRET_KEY,
|
|
@@ -1,11 +1,18 @@
|
|
|
1
|
+
from enum import auto
|
|
1
2
|
from typing import Dict, List, Optional
|
|
2
3
|
|
|
3
4
|
from pydantic import Field
|
|
5
|
+
from strenum import LowercaseStrEnum
|
|
4
6
|
|
|
5
7
|
from splight_lib.constants import DESCRIPTION_MAX_LENGTH
|
|
6
8
|
from splight_lib.models.base import FilePath, SplightDatabaseBaseModel
|
|
7
9
|
|
|
8
10
|
|
|
11
|
+
class PrivacyPolicy(LowercaseStrEnum):
|
|
12
|
+
PUBLIC = auto()
|
|
13
|
+
PRIVATE = auto()
|
|
14
|
+
|
|
15
|
+
|
|
9
16
|
class HubSolution(SplightDatabaseBaseModel):
|
|
10
17
|
id: Optional[str] = None
|
|
11
18
|
name: str
|
|
@@ -14,6 +21,7 @@ class HubSolution(SplightDatabaseBaseModel):
|
|
|
14
21
|
default=None, max_length=DESCRIPTION_MAX_LENGTH
|
|
15
22
|
)
|
|
16
23
|
tags: Optional[List[str]] = Field(default=None)
|
|
24
|
+
privacy_policy: PrivacyPolicy = PrivacyPolicy.PUBLIC
|
|
17
25
|
|
|
18
26
|
main_file: Optional[FilePath] = Field(default=None, exclude=True)
|
|
19
27
|
variables_file: Optional[FilePath] = Field(default=None, exclude=True)
|
|
@@ -14,7 +14,6 @@ def get_datalake_client() -> AbstractDatalakeClient:
|
|
|
14
14
|
client = DatalakeClientBuilder.build(
|
|
15
15
|
dl_client_type=settings.DL_CLIENT_TYPE,
|
|
16
16
|
parameters={
|
|
17
|
-
"path": settings.CURRENT_DIR,
|
|
18
17
|
"base_url": settings.SPLIGHT_PLATFORM_API_HOST,
|
|
19
18
|
"access_id": settings.SPLIGHT_ACCESS_ID,
|
|
20
19
|
"secret_key": settings.SPLIGHT_SECRET_KEY,
|
{splight_lib-5.7.0 → splight_lib-5.7.2}/splight_lib/models/tests/test_component_object_instance.py
RENAMED
|
@@ -15,9 +15,7 @@ from splight_lib.models.component import ( # noqa: E402
|
|
|
15
15
|
CustomType,
|
|
16
16
|
)
|
|
17
17
|
from splight_lib.models.exceptions import InvalidObjectInstance # noqa: E402
|
|
18
|
-
from splight_lib.settings import settings # noqa: E402
|
|
19
18
|
|
|
20
|
-
settings.configure(LOCAL_ENVIRONMENT=True)
|
|
21
19
|
warnings.filterwarnings("ignore", category=RuntimeWarning)
|
|
22
20
|
|
|
23
21
|
|
|
@@ -13,9 +13,6 @@ from splight_lib.client.database.remote_client import ( # noqa: E402
|
|
|
13
13
|
RemoteDatabaseClient,
|
|
14
14
|
)
|
|
15
15
|
from splight_lib.models.base import SplightDatabaseBaseModel # noqa: E402
|
|
16
|
-
from splight_lib.settings import settings # noqa: E402
|
|
17
|
-
|
|
18
|
-
settings.configure(LOCAL_ENVIRONMENT=True)
|
|
19
16
|
|
|
20
17
|
|
|
21
18
|
class Resource(SplightDatabaseBaseModel):
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import os
|
|
2
2
|
from enum import Enum
|
|
3
|
-
from typing import Any, Dict,
|
|
3
|
+
from typing import Any, Dict, Tuple, Type
|
|
4
4
|
|
|
5
5
|
import yaml
|
|
6
|
-
from pydantic import ConfigDict
|
|
6
|
+
from pydantic import ConfigDict
|
|
7
7
|
from pydantic.fields import FieldInfo
|
|
8
8
|
from pydantic_settings import BaseSettings, PydanticBaseSettingsSource
|
|
9
9
|
|
|
@@ -65,11 +65,6 @@ class SplightSettings(BaseSettings, Singleton):
|
|
|
65
65
|
SPLIGHT_SECRET_KEY: str = ""
|
|
66
66
|
SPLIGHT_PLATFORM_API_HOST: str = "https://api.splight-ai.com"
|
|
67
67
|
|
|
68
|
-
# Parameters for local environment
|
|
69
|
-
# TODO: to deprecate this and its effects
|
|
70
|
-
LOCAL_ENVIRONMENT: bool = False
|
|
71
|
-
CURRENT_DIR: Optional[str] = None
|
|
72
|
-
|
|
73
68
|
# Parameters for the datalake client
|
|
74
69
|
# Review if is better to use another class for only the DL Client settings
|
|
75
70
|
DL_CLIENT_TYPE: DatalakeClientType = DatalakeClientType.BUFFERED_ASYNC
|
|
@@ -78,15 +73,6 @@ class SplightSettings(BaseSettings, Singleton):
|
|
|
78
73
|
|
|
79
74
|
model_config = ConfigDict(extra="ignore")
|
|
80
75
|
|
|
81
|
-
@model_validator(mode="after")
|
|
82
|
-
@classmethod
|
|
83
|
-
def validate_local_environment(
|
|
84
|
-
cls, instance: "SplightSettings"
|
|
85
|
-
) -> "SplightSettings":
|
|
86
|
-
if instance.LOCAL_ENVIRONMENT:
|
|
87
|
-
instance.CURRENT_DIR = os.getcwd()
|
|
88
|
-
return instance
|
|
89
|
-
|
|
90
76
|
def configure(self, **params: Dict):
|
|
91
77
|
self.model_validate(params)
|
|
92
78
|
|
|
@@ -13,7 +13,7 @@ from openapi_schema_validator import validate
|
|
|
13
13
|
from polyfactory import Use
|
|
14
14
|
from polyfactory.factories.pydantic_factory import ModelFactory
|
|
15
15
|
|
|
16
|
-
from splight_lib.models import (
|
|
16
|
+
from splight_lib.models import (
|
|
17
17
|
Asset,
|
|
18
18
|
Attribute,
|
|
19
19
|
Function,
|
|
@@ -145,21 +145,7 @@ def read_swagger(url: str) -> Dict[str, Any]:
|
|
|
145
145
|
return yaml.safe_load(response.text)
|
|
146
146
|
|
|
147
147
|
|
|
148
|
-
# if __name__ == "__main__":
|
|
149
148
|
def test_api_contract():
|
|
150
|
-
# if len(sys.argv) == 1:
|
|
151
|
-
# models_to_validate = list(MODEL_MAPPING.keys())
|
|
152
|
-
# elif len(sys.argv) == 2:
|
|
153
|
-
# model_name = sys.argv[1]
|
|
154
|
-
# if model_name not in MODEL_MAPPING:
|
|
155
|
-
# valid_names = list(MODEL_MAPPING.keys())
|
|
156
|
-
# raise ValueError(
|
|
157
|
-
# f"Got invalid model name. Valid models are {valid_names}"
|
|
158
|
-
# )
|
|
159
|
-
# models_to_validate = [sys.argv[1]]
|
|
160
|
-
# elif len(sys.argv) > 2:
|
|
161
|
-
# raise ValueError("Invalid number of arguments")
|
|
162
|
-
|
|
163
149
|
api_url = os.getenv(
|
|
164
150
|
"SPLIGHT_PLATFORM_API_HOST", "https://integrationapi.splight-ai.com"
|
|
165
151
|
)
|
|
@@ -1,17 +0,0 @@
|
|
|
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
|
|
@@ -1,187 +0,0 @@
|
|
|
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
|
-
LOCAL_DB_FILE = "splight-db.json"
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class LocalDatabaseClient(AbstractDatabaseClient):
|
|
19
|
-
"""Database Client implementation for a local database that uses a
|
|
20
|
-
JSON file.
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
def __init__(self, path: str, *args, **kwargs):
|
|
24
|
-
super().__init__()
|
|
25
|
-
self._db_file = os.path.join(path, LOCAL_DB_FILE)
|
|
26
|
-
|
|
27
|
-
if not os.path.exists(self._db_file):
|
|
28
|
-
self._save_db(self._db_file, {})
|
|
29
|
-
logger.debug(
|
|
30
|
-
"Local database client initialized.", tags=LogTags.DATABASE
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
def save(self, resource_name: str, instance: Dict) -> Dict:
|
|
34
|
-
"""Creates or updates a resource depending on the name if
|
|
35
|
-
it contains the id or not.
|
|
36
|
-
|
|
37
|
-
Parameters
|
|
38
|
-
----------
|
|
39
|
-
resource_name: str
|
|
40
|
-
The name of the resource to be created or updated.
|
|
41
|
-
instance : Dict
|
|
42
|
-
A dictionary with resource to be created or updated
|
|
43
|
-
|
|
44
|
-
Returns
|
|
45
|
-
-------
|
|
46
|
-
Dict with the created or updated resource.
|
|
47
|
-
|
|
48
|
-
Raises
|
|
49
|
-
------
|
|
50
|
-
InvalidModelName thrown when the model name is not correct.
|
|
51
|
-
"""
|
|
52
|
-
logger.debug("Saving instance", tags=LogTags.DATABASE)
|
|
53
|
-
|
|
54
|
-
model_name = resource_name.lower()
|
|
55
|
-
if instance.get("id"):
|
|
56
|
-
saved_instance = self._update(model_name, instance)
|
|
57
|
-
else:
|
|
58
|
-
saved_instance = self._create(model_name, instance)
|
|
59
|
-
return saved_instance
|
|
60
|
-
|
|
61
|
-
def delete(self, resource_name: str, id: str):
|
|
62
|
-
"""Deletes a resource from the database
|
|
63
|
-
|
|
64
|
-
Parameters
|
|
65
|
-
----------
|
|
66
|
-
resource_name : str
|
|
67
|
-
The resource name
|
|
68
|
-
id : str
|
|
69
|
-
The resource's id.
|
|
70
|
-
|
|
71
|
-
Raises
|
|
72
|
-
------
|
|
73
|
-
InvalidModelName thrown when the model name is not correct.
|
|
74
|
-
"""
|
|
75
|
-
logger.debug("Deleting instance %s.", id, tags=LogTags.DATABASE)
|
|
76
|
-
model_name = resource_name.lower()
|
|
77
|
-
db = self._load_db_file(self._db_file)
|
|
78
|
-
db_instances = db.get(model_name, {})
|
|
79
|
-
|
|
80
|
-
if id not in db_instances:
|
|
81
|
-
raise InstanceNotFound(model_name, id)
|
|
82
|
-
|
|
83
|
-
_ = db_instances.pop(id)
|
|
84
|
-
self._save_db(self._db_file, db)
|
|
85
|
-
|
|
86
|
-
def operate(self, resource_name: str, instance: Dict) -> Dict:
|
|
87
|
-
raise NotImplementedError("Method not allowed for Local Database")
|
|
88
|
-
|
|
89
|
-
def _get(
|
|
90
|
-
self,
|
|
91
|
-
resource_name: str,
|
|
92
|
-
first: bool = False,
|
|
93
|
-
**kwargs,
|
|
94
|
-
) -> Union[Dict, List[Dict]]:
|
|
95
|
-
"""Retrieves one or multiple resources. If the parameter id is passed
|
|
96
|
-
as a kwarg, the instance with that id will be retrieved.
|
|
97
|
-
|
|
98
|
-
Parameters
|
|
99
|
-
----------
|
|
100
|
-
resource_name : str
|
|
101
|
-
The name of the resource.
|
|
102
|
-
first: bool
|
|
103
|
-
Whether to retrieve first element or not.
|
|
104
|
-
|
|
105
|
-
Returns
|
|
106
|
-
-------
|
|
107
|
-
Union[Dict, List[Dict]] list of resource or single resource.
|
|
108
|
-
"""
|
|
109
|
-
resource_id = kwargs.pop("id", None)
|
|
110
|
-
model_name = resource_name.lower()
|
|
111
|
-
if resource_id:
|
|
112
|
-
result = self._retrieve_single(model_name, resource_id)
|
|
113
|
-
else:
|
|
114
|
-
result = self._retrieve_multiple(model_name, first=first, **kwargs)
|
|
115
|
-
return result
|
|
116
|
-
|
|
117
|
-
def _retrieve_single(self, model_name: str, resource_id: str) -> Dict:
|
|
118
|
-
db = self._load_db_file(self._db_file)
|
|
119
|
-
db_instances = db.get(model_name, {})
|
|
120
|
-
if resource_id not in db_instances:
|
|
121
|
-
raise InstanceNotFound(model_name, resource_id)
|
|
122
|
-
return db_instances.get(resource_id)
|
|
123
|
-
|
|
124
|
-
def _retrieve_multiple(
|
|
125
|
-
self, model_name: str, first: bool = False, **kwargs
|
|
126
|
-
) -> List[Dict]:
|
|
127
|
-
db = self._load_db_file(self._db_file)
|
|
128
|
-
db_instances = db.get(model_name, {})
|
|
129
|
-
|
|
130
|
-
filters = self._validate_filters(kwargs)
|
|
131
|
-
filtered = self._filter(db_instances, filters=filters)
|
|
132
|
-
instances = list(filtered.values())
|
|
133
|
-
if first:
|
|
134
|
-
return [instances[0]]
|
|
135
|
-
return instances
|
|
136
|
-
|
|
137
|
-
def download(
|
|
138
|
-
self, instances: Dict, decrtypt: bool = True, **kwargs
|
|
139
|
-
) -> NamedTemporaryFile:
|
|
140
|
-
raise NotImplementedError("Method not implemented for Local Database")
|
|
141
|
-
|
|
142
|
-
def _create(self, resource_name: str, instance: Dict) -> Dict:
|
|
143
|
-
db = self._load_db_file(self._db_file)
|
|
144
|
-
db_instances = db.get(resource_name, {})
|
|
145
|
-
instance["id"] = str(uuid4())
|
|
146
|
-
db_instances.update({instance["id"]: instance})
|
|
147
|
-
db[resource_name] = db_instances
|
|
148
|
-
self._save_db(self._db_file, db)
|
|
149
|
-
return instance
|
|
150
|
-
|
|
151
|
-
def _update(self, resource_name: str, instance: Dict) -> Dict:
|
|
152
|
-
db = self._load_db_file(self._db_file)
|
|
153
|
-
db_instances = db.get(resource_name, {})
|
|
154
|
-
|
|
155
|
-
if instance["id"] not in db_instances:
|
|
156
|
-
raise InstanceNotFound(resource_name, instance["id"])
|
|
157
|
-
db_instances[instance["id"]] = instance
|
|
158
|
-
self._save_db(self._db_file, db)
|
|
159
|
-
return instance
|
|
160
|
-
|
|
161
|
-
def _filter(
|
|
162
|
-
self, instances: Dict[str, Dict], filters: Dict
|
|
163
|
-
) -> Dict[str, Dict]:
|
|
164
|
-
filtered = instances
|
|
165
|
-
for key, value in filters.items():
|
|
166
|
-
filtered = filter(
|
|
167
|
-
partial(value_filter_on_tuple, key, value), filtered.items()
|
|
168
|
-
)
|
|
169
|
-
filtered = {item[0]: item[1] for item in filtered}
|
|
170
|
-
return filtered
|
|
171
|
-
|
|
172
|
-
def _load_db_file(self, file_path: str) -> Dict:
|
|
173
|
-
with open(file_path, "r") as fid:
|
|
174
|
-
data = json.load(fid)
|
|
175
|
-
return data
|
|
176
|
-
|
|
177
|
-
def _save_db(self, file_path: str, db: Dict):
|
|
178
|
-
with open(file_path, "w") as fid:
|
|
179
|
-
json.dump(db, fid, indent=2)
|
|
180
|
-
|
|
181
|
-
def _validate_filters(self, filters_raw: Dict):
|
|
182
|
-
invalid_filters = ["ignore_hook"]
|
|
183
|
-
return {
|
|
184
|
-
key: value
|
|
185
|
-
for key, value in filters_raw.items()
|
|
186
|
-
if key not in invalid_filters
|
|
187
|
-
}
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import os
|
|
3
|
-
from datetime import datetime, timedelta, timezone
|
|
4
|
-
from functools import partial
|
|
5
|
-
from typing import Dict, List, Optional, Union
|
|
6
|
-
|
|
7
|
-
import pandas as pd
|
|
8
|
-
|
|
9
|
-
from splight_lib.client.datalake.abstract import AbstractDatalakeClient
|
|
10
|
-
from splight_lib.client.file_handler import FixedLineNumberFileHandler
|
|
11
|
-
from splight_lib.client.filter import value_filter
|
|
12
|
-
from splight_lib.logging._internal import LogTags, get_splight_logger
|
|
13
|
-
|
|
14
|
-
logger = get_splight_logger()
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class LocalDatalakeClient(AbstractDatalakeClient):
|
|
18
|
-
"""Datalake client implementation for a storing locally documents
|
|
19
|
-
in different files.
|
|
20
|
-
"""
|
|
21
|
-
|
|
22
|
-
_DEFAULT = "default"
|
|
23
|
-
_PREFIX = "splight-dl_"
|
|
24
|
-
_SUFFIX = ".json"
|
|
25
|
-
_TOTAL_DOCS = 10000
|
|
26
|
-
|
|
27
|
-
def __init__(self, path: str, *args, **kwargs):
|
|
28
|
-
super().__init__()
|
|
29
|
-
self._base_path = path
|
|
30
|
-
logger.info(
|
|
31
|
-
"Local datalake client initialized.", tags=LogTags.DATALAKE
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
def save(
|
|
35
|
-
self,
|
|
36
|
-
collection: str,
|
|
37
|
-
instances: Union[List[Dict], Dict],
|
|
38
|
-
) -> List[Dict]:
|
|
39
|
-
instances = instances if isinstance(instances, list) else [instances]
|
|
40
|
-
|
|
41
|
-
logger.debug("Saving instances %s.", instances, tags=LogTags.DATALAKE)
|
|
42
|
-
instances = [json.dumps(instance) for instance in instances]
|
|
43
|
-
|
|
44
|
-
file_path = os.path.join(
|
|
45
|
-
self._base_path, self._get_file_name(collection)
|
|
46
|
-
)
|
|
47
|
-
handler = FixedLineNumberFileHandler(
|
|
48
|
-
file_path=file_path, total_lines=self._TOTAL_DOCS
|
|
49
|
-
)
|
|
50
|
-
handler.write(instances)
|
|
51
|
-
return instances
|
|
52
|
-
|
|
53
|
-
def _raw_get(
|
|
54
|
-
self,
|
|
55
|
-
resource_name: str,
|
|
56
|
-
collection: str,
|
|
57
|
-
limit_: int = 1000,
|
|
58
|
-
skip_: int = 0,
|
|
59
|
-
sort: Union[List, str] = ["timestamp__desc"],
|
|
60
|
-
group_id: Optional[Union[List, str]] = None,
|
|
61
|
-
group_fields: Optional[Union[List, str]] = None,
|
|
62
|
-
tzinfo: timezone = timezone(timedelta()),
|
|
63
|
-
**filters,
|
|
64
|
-
) -> List[Dict]:
|
|
65
|
-
filters.update(
|
|
66
|
-
{
|
|
67
|
-
"output_format": resource_name,
|
|
68
|
-
}
|
|
69
|
-
)
|
|
70
|
-
filters = self._parse_filters(filters)
|
|
71
|
-
|
|
72
|
-
file_path = os.path.join(
|
|
73
|
-
self._base_path, self._get_file_name(collection)
|
|
74
|
-
)
|
|
75
|
-
handler = FixedLineNumberFileHandler(
|
|
76
|
-
file_path=file_path, total_lines=self._TOTAL_DOCS
|
|
77
|
-
)
|
|
78
|
-
documents = [
|
|
79
|
-
json.loads(doc) for doc in handler.read()[skip_ : skip_ + limit_]
|
|
80
|
-
]
|
|
81
|
-
documents = self._filter(documents, filters=filters)
|
|
82
|
-
|
|
83
|
-
reverse = False
|
|
84
|
-
if "__desc" not in sort:
|
|
85
|
-
reverse = True
|
|
86
|
-
documents.sort(key=lambda x: x["timestamp"], reverse=reverse)
|
|
87
|
-
|
|
88
|
-
return documents
|
|
89
|
-
|
|
90
|
-
def delete(self, collection: str, **kwargs) -> None:
|
|
91
|
-
logger.debug(
|
|
92
|
-
"Skipping deleting objects when using Local datalake client."
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
def execute_query(
|
|
96
|
-
self,
|
|
97
|
-
from_timestamp: datetime,
|
|
98
|
-
to_timestamp: Optional[datetime],
|
|
99
|
-
query: Dict,
|
|
100
|
-
) -> pd.DataFrame:
|
|
101
|
-
raise NotImplementedError("Method not available for the local client")
|
|
102
|
-
|
|
103
|
-
def _filter(self, instances: List[dict], filters: Dict) -> List[dict]:
|
|
104
|
-
filtered = instances
|
|
105
|
-
for key, value in filters.items():
|
|
106
|
-
filtered = filter(partial(value_filter, key, value), filtered)
|
|
107
|
-
filtered = list(filtered)
|
|
108
|
-
return filtered
|
|
109
|
-
|
|
110
|
-
def _parse_filters(self, filters: List[dict]):
|
|
111
|
-
new_filters = {}
|
|
112
|
-
for key, value in filters.items():
|
|
113
|
-
if value is None:
|
|
114
|
-
continue
|
|
115
|
-
new_filters[key] = value
|
|
116
|
-
return new_filters
|
|
117
|
-
|
|
118
|
-
def _get_file_name(self, collection: str) -> str:
|
|
119
|
-
return f"{self._PREFIX}{collection}{self._SUFFIX}"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|