splight-lib 2.3.18__tar.gz → 2.3.20__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 (115) hide show
  1. {splight-lib-2.3.18 → splight-lib-2.3.20}/PKG-INFO +1 -1
  2. {splight-lib-2.3.18 → splight-lib-2.3.20}/setup.py +1 -1
  3. splight-lib-2.3.20/splight_lib/client/communication/__init__.py +11 -0
  4. splight-lib-2.3.20/splight_lib/client/communication/local_client.py +6 -0
  5. splight-lib-2.3.18/remote_splight_lib/communication/client.py → splight-lib-2.3.20/splight_lib/client/communication/remote_client.py +6 -5
  6. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/client/datalake/remote_client.py +1 -1
  7. splight-lib-2.3.20/splight_lib/client/hub/__init__.py +5 -0
  8. {splight-lib-2.3.18/remote_splight_lib → splight-lib-2.3.20/splight_lib/client}/hub/client.py +2 -2
  9. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/component/abstract.py +11 -11
  10. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/settings.py +2 -2
  11. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib.egg-info/PKG-INFO +1 -1
  12. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib.egg-info/SOURCES.txt +6 -15
  13. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib.egg-info/top_level.txt +0 -1
  14. splight-lib-2.3.18/remote_splight_lib/__init__.py +0 -1
  15. splight-lib-2.3.18/remote_splight_lib/auth/__init__.py +0 -1
  16. splight-lib-2.3.18/remote_splight_lib/auth/auth.py +0 -7
  17. splight-lib-2.3.18/remote_splight_lib/communication/__init__.py +0 -3
  18. splight-lib-2.3.18/remote_splight_lib/database/__init__.py +0 -3
  19. splight-lib-2.3.18/remote_splight_lib/database/client.py +0 -235
  20. splight-lib-2.3.18/remote_splight_lib/datalake/__init__.py +0 -1
  21. splight-lib-2.3.18/remote_splight_lib/datalake/client.py +0 -259
  22. splight-lib-2.3.18/remote_splight_lib/exceptions.py +0 -6
  23. splight-lib-2.3.18/remote_splight_lib/hub/__init__.py +0 -1
  24. splight-lib-2.3.18/remote_splight_lib/settings.py +0 -18
  25. splight-lib-2.3.18/splight_lib/client/database/classmap.py +0 -33
  26. {splight-lib-2.3.18 → splight-lib-2.3.20}/LICENSE.txt +0 -0
  27. {splight-lib-2.3.18 → splight-lib-2.3.20}/README.md +0 -0
  28. {splight-lib-2.3.18 → splight-lib-2.3.20}/setup.cfg +0 -0
  29. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/__init__.py +0 -0
  30. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/auth/__init__.py +0 -0
  31. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/auth/abstract.py +0 -0
  32. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/auth/exceptions.py +0 -0
  33. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/cache/__init__.py +0 -0
  34. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/cache/abstract.py +0 -0
  35. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/client/__init__.py +0 -0
  36. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/client/abstract.py +0 -0
  37. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/client/filter.py +0 -0
  38. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/client/hooks.py +0 -0
  39. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/communication/__init__.py +0 -0
  40. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/communication/abstract.py +0 -0
  41. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/communication/exceptions.py +0 -0
  42. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/database/__init__.py +0 -0
  43. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/database/abstract.py +0 -0
  44. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/datalake/__init__.py +0 -0
  45. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/datalake/abstract.py +0 -0
  46. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/deployment/__init__.py +0 -0
  47. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/deployment/abstract.py +0 -0
  48. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/endpoints/__init__.py +0 -0
  49. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/hub/__init__.py +0 -0
  50. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/hub/abstract.py +0 -0
  51. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/notification/__init__.py +0 -0
  52. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/notification/abstract.py +0 -0
  53. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/remote/__init__.py +0 -0
  54. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/remote/abstract.py +0 -0
  55. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/storage/__init__.py +0 -0
  56. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_abstract/storage/abstract.py +0 -0
  57. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/__init__.py +0 -0
  58. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/auth/__init__.py +0 -0
  59. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/auth/exceptions.py +0 -0
  60. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/auth/mac_auth.py +0 -0
  61. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/auth/token.py +0 -0
  62. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/client/__init__.py +0 -0
  63. {splight-lib-2.3.18/remote_splight_lib → splight-lib-2.3.20/splight_lib/client}/communication/classmap.py +0 -0
  64. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/client/database/__init__.py +0 -0
  65. {splight-lib-2.3.18/remote_splight_lib → splight-lib-2.3.20/splight_lib/client}/database/classmap.py +0 -0
  66. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/client/database/local_client.py +0 -0
  67. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/client/database/remote_client.py +0 -0
  68. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/client/datalake/__init__.py +0 -0
  69. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/client/datalake/local_client.py +0 -0
  70. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/client/exceptions.py +0 -0
  71. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/client/file_handler.py +0 -0
  72. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/client/filter.py +0 -0
  73. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/client/settings.py +0 -0
  74. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/component/__init__.py +0 -0
  75. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/encryption.py +0 -0
  76. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/execution.py +0 -0
  77. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/logging/__init__.py +0 -0
  78. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/logging/_internal.py +0 -0
  79. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/logging/component.py +0 -0
  80. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/logging/logging.py +0 -0
  81. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/restclient/__init__.py +0 -0
  82. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/restclient/client.py +0 -0
  83. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/restclient/exceptions.py +0 -0
  84. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/restclient/types.py +0 -0
  85. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib/webhook.py +0 -0
  86. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib.egg-info/dependency_links.txt +0 -0
  87. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib.egg-info/not-zip-safe +0 -0
  88. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_lib.egg-info/requires.txt +0 -0
  89. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/__init__.py +0 -0
  90. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/alert.py +0 -0
  91. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/asset.py +0 -0
  92. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/attribute.py +0 -0
  93. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/base.py +0 -0
  94. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/blockchain.py +0 -0
  95. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/channel.py +0 -0
  96. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/communication/__init__.py +0 -0
  97. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/communication/context.py +0 -0
  98. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/communication/events.py +0 -0
  99. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/component.py +0 -0
  100. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/constants.py +0 -0
  101. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/credential.py +0 -0
  102. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/datalake.py +0 -0
  103. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/deployment.py +0 -0
  104. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/exception.py +0 -0
  105. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/file.py +0 -0
  106. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/hub.py +0 -0
  107. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/namespace.py +0 -0
  108. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/notification.py +0 -0
  109. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/query.py +0 -0
  110. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/secret.py +0 -0
  111. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/setpoint.py +0 -0
  112. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/severity.py +0 -0
  113. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/user.py +0 -0
  114. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/variable.py +0 -0
  115. {splight-lib-2.3.18 → splight-lib-2.3.20}/splight_models/webhook.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: splight-lib
3
- Version: 2.3.18
3
+ Version: 2.3.20
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.18",
17
+ version="2.3.20",
18
18
  author="Splight",
19
19
  author_email="factory@splight-ae.com",
20
20
  packages=find_packages(),
@@ -0,0 +1,11 @@
1
+ from splight_lib.client.communication.local_client import (
2
+ LocalCommunicationClient,
3
+ )
4
+ from splight_lib.client.communication.remote_client import (
5
+ RemoteCommunicationClient,
6
+ )
7
+
8
+ __all__ = [
9
+ LocalCommunicationClient,
10
+ RemoteCommunicationClient,
11
+ ]
@@ -0,0 +1,6 @@
1
+ # TBD
2
+ from splight_abstract.communication import AbstractCommunicationClient
3
+
4
+
5
+ class LocalCommunicationClient(AbstractCommunicationClient):
6
+ pass
@@ -4,14 +4,14 @@ from typing import Callable, Dict
4
4
  import pysher
5
5
  import requests
6
6
  from furl import furl
7
- from remote_splight_lib.auth.auth import SplightAuthToken
8
- from remote_splight_lib.communication.classmap import CLASSMAP
9
- from remote_splight_lib.settings import settings
10
7
  from retry import retry
11
8
  from splight_abstract.communication import (
12
9
  AbstractCommunicationClient,
13
10
  ClientNotReady,
14
11
  )
12
+ from splight_lib.auth import SplightAuthToken
13
+ from splight_lib.client.communication.classmap import CLASSMAP
14
+ from splight_lib.client.settings import settings_remote as settings
15
15
  from splight_lib.logging._internal import LogTags, get_splight_logger
16
16
  from splight_models.communication import (
17
17
  CommunicationClientStatus,
@@ -57,7 +57,7 @@ class CommunicationFactory:
57
57
  return self._model.parse_obj(data)
58
58
 
59
59
 
60
- class CommunicationClient(AbstractCommunicationClient):
60
+ class RemoteCommunicationClient(AbstractCommunicationClient):
61
61
  def __init__(self, daemon: bool = True, *args, **kwargs):
62
62
  super().__init__(*args, **kwargs)
63
63
  self._status = CommunicationClientStatus.STOPPED
@@ -81,7 +81,8 @@ class CommunicationClient(AbstractCommunicationClient):
81
81
  )
82
82
  except Exception as e:
83
83
  logger.warning(
84
- "Failed to start communication client due to exception %s. Moving forward without remote commands.",
84
+ "Failed to start communication client due to exception %s. "
85
+ "Moving forward without remote commands.",
85
86
  e,
86
87
  exc_info=True,
87
88
  tags=LogTags.COMMUNICATION,
@@ -7,7 +7,6 @@ from typing import Dict, List, Union
7
7
  import pandas as pd
8
8
  from furl import furl
9
9
  from pydantic import BaseModel
10
- from remote_splight_lib.auth import SplightAuthToken
11
10
  from retry import retry
12
11
  from splight_abstract import AbstractRemoteClient, QuerySet
13
12
  from splight_abstract.datalake import (
@@ -15,6 +14,7 @@ from splight_abstract.datalake import (
15
14
  validate_datalake_instance_type,
16
15
  validate_datalake_resource_type,
17
16
  )
17
+ from splight_lib.auth import SplightAuthToken
18
18
  from splight_lib.client.exceptions import SPLIGHT_REQUEST_EXCEPTIONS
19
19
  from splight_lib.client.settings import settings_remote as settings
20
20
  from splight_lib.logging._internal import LogTags, get_splight_logger
@@ -0,0 +1,5 @@
1
+ from splight_lib.client.hub.client import SplightHubClient
2
+
3
+ __all__ = [
4
+ SplightHubClient,
5
+ ]
@@ -3,13 +3,13 @@ from typing import Dict, List, Optional, Tuple, Type
3
3
  import requests
4
4
  from furl import furl
5
5
  from pydantic import BaseModel
6
- from remote_splight_lib.auth import SplightAuthToken
7
- from remote_splight_lib.settings import settings
8
6
  from splight_abstract import (
9
7
  AbstractHubClient,
10
8
  AbstractHubSubClient,
11
9
  validate_client_resource_type,
12
10
  )
11
+ from splight_lib.auth import SplightAuthToken
12
+ from splight_lib.client.settings import settings_remote as settings
13
13
  from splight_models import HubComponent, HubComponentVersion
14
14
 
15
15
 
@@ -7,14 +7,22 @@ from collections import defaultdict
7
7
  from functools import cached_property, partial
8
8
  from tempfile import NamedTemporaryFile
9
9
  from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Type, Union
10
- from retry import retry
11
10
 
12
11
  import splight_models as spmodels
13
12
  from mergedeep import Strategy as mergeStrategy
14
13
  from mergedeep import merge
15
14
  from pydantic import BaseModel, main
15
+ from retry import retry
16
+ from splight_lib.auth import SplightAuthToken
17
+ from splight_lib.client.settings import settings_remote
16
18
  from splight_lib.execution import ExecutionClient, Thread
17
19
  from splight_lib.logging._internal import LogTags, get_splight_logger
20
+ from splight_lib.restclient import (
21
+ ConnectError,
22
+ HTTPError,
23
+ SplightRestClient,
24
+ Timeout,
25
+ )
18
26
  from splight_lib.settings import setup as default_setup
19
27
  from splight_models import (
20
28
  Binding,
@@ -47,14 +55,6 @@ from splight_models.setpoint import (
47
55
  SetPointResponseStatus,
48
56
  SetPointUpdateEvent,
49
57
  )
50
- from remote_splight_lib.auth import SplightAuthToken
51
- from splight_lib.restclient import (
52
- ConnectError,
53
- HTTPError,
54
- SplightRestClient,
55
- Timeout,
56
- )
57
- from splight_lib.client.settings import settings_remote
58
58
 
59
59
  logger = get_splight_logger()
60
60
  REQUEST_EXCEPTIONS = (HTTPError, Timeout, ConnectError)
@@ -744,7 +744,7 @@ class AbstractComponent(
744
744
  @retry(REQUEST_EXCEPTIONS, tries=3, delay=2, jitter=1)
745
745
  def _check_duplicated_component(self):
746
746
  """
747
- Validates that there are no other connections to communication client
747
+ Validates that there are no other connections to communication client
748
748
  """
749
749
  token = SplightAuthToken(
750
750
  access_key=settings_remote.SPLIGHT_ACCESS_ID,
@@ -755,7 +755,7 @@ class AbstractComponent(
755
755
  api_url = f"{settings_remote.SPLIGHT_PLATFORM_API_HOST}/v2/engine/component/components/{self.instance_id}/connections/"
756
756
  response = rest_client.get(api_url)
757
757
  if response.status_code == 200:
758
- connections = response.json()['subscription_count']
758
+ connections = response.json()["subscription_count"]
759
759
  if int(connections) > 0:
760
760
  raise DuplicatedComponentException(
761
761
  f"Component with id {self.instance_id} is already running."
@@ -48,9 +48,9 @@ class SplightBaseSettings(BaseSettings):
48
48
  DATABASE_CLIENT: str = "splight_lib.client.database.RemoteDatabaseClient"
49
49
  DATALAKE_CLIENT: str = "splight_lib.client.datalake.RemoteDatalakeClient"
50
50
  COMMUNICATION_CLIENT: str = (
51
- "remote_splight_lib.communication.CommunicationClient"
51
+ "splight_lib.client.communication.RemoteCommunicationClient"
52
52
  )
53
- HUB_CLIENT: str = "remote_splight_lib.hub.SplightHubClient"
53
+ HUB_CLIENT: str = "splight_lib.client.hub.SplightHubClient"
54
54
  NAMESPACE: str = "NO_NAMESPACE"
55
55
 
56
56
  @property
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: splight-lib
3
- Version: 2.3.18
3
+ Version: 2.3.20
4
4
  Summary: Library for public use. Splight
5
5
  Home-page: UNKNOWN
6
6
  Author: Splight
@@ -1,21 +1,6 @@
1
1
  LICENSE.txt
2
2
  README.md
3
3
  setup.py
4
- remote_splight_lib/__init__.py
5
- remote_splight_lib/exceptions.py
6
- remote_splight_lib/settings.py
7
- remote_splight_lib/auth/__init__.py
8
- remote_splight_lib/auth/auth.py
9
- remote_splight_lib/communication/__init__.py
10
- remote_splight_lib/communication/classmap.py
11
- remote_splight_lib/communication/client.py
12
- remote_splight_lib/database/__init__.py
13
- remote_splight_lib/database/classmap.py
14
- remote_splight_lib/database/client.py
15
- remote_splight_lib/datalake/__init__.py
16
- remote_splight_lib/datalake/client.py
17
- remote_splight_lib/hub/__init__.py
18
- remote_splight_lib/hub/client.py
19
4
  splight_abstract/__init__.py
20
5
  splight_abstract/auth/__init__.py
21
6
  splight_abstract/auth/abstract.py
@@ -64,6 +49,10 @@ splight_lib/client/exceptions.py
64
49
  splight_lib/client/file_handler.py
65
50
  splight_lib/client/filter.py
66
51
  splight_lib/client/settings.py
52
+ splight_lib/client/communication/__init__.py
53
+ splight_lib/client/communication/classmap.py
54
+ splight_lib/client/communication/local_client.py
55
+ splight_lib/client/communication/remote_client.py
67
56
  splight_lib/client/database/__init__.py
68
57
  splight_lib/client/database/classmap.py
69
58
  splight_lib/client/database/local_client.py
@@ -71,6 +60,8 @@ splight_lib/client/database/remote_client.py
71
60
  splight_lib/client/datalake/__init__.py
72
61
  splight_lib/client/datalake/local_client.py
73
62
  splight_lib/client/datalake/remote_client.py
63
+ splight_lib/client/hub/__init__.py
64
+ splight_lib/client/hub/client.py
74
65
  splight_lib/component/__init__.py
75
66
  splight_lib/component/abstract.py
76
67
  splight_lib/logging/__init__.py
@@ -1,4 +1,3 @@
1
- remote_splight_lib
2
1
  splight_abstract
3
2
  splight_lib
4
3
  splight_models
@@ -1 +0,0 @@
1
- from .auth import SplightAuthToken
@@ -1,7 +0,0 @@
1
- class SplightAuthToken:
2
- def __init__(self, access_key: str, secret_key: str):
3
- self._token = f"Splight {access_key} {secret_key}"
4
-
5
- @property
6
- def header(self):
7
- return {"Authorization": self._token}
@@ -1,3 +0,0 @@
1
- from remote_splight_lib.communication.client import CommunicationClient
2
-
3
- __all__ = [CommunicationClient]
@@ -1,3 +0,0 @@
1
- from remote_splight_lib.database.client import DatabaseClient
2
-
3
- __all__ = [DatabaseClient]
@@ -1,235 +0,0 @@
1
- import json
2
- from tempfile import NamedTemporaryFile
3
- from typing import Dict, List, Type
4
-
5
- from furl import furl
6
- from pydantic import BaseModel
7
- from remote_splight_lib.auth import SplightAuthToken
8
- from remote_splight_lib.exceptions import InvalidModel
9
- from remote_splight_lib.settings import settings
10
- from requests import Session
11
- from requests.exceptions import ConnectionError, Timeout
12
- from retry import retry
13
- from splight_abstract.database import AbstractDatabaseClient
14
- from splight_abstract.remote import AbstractRemoteClient
15
- from splight_lib.encryption import EncryptionClient
16
- from splight_lib.logging._internal import LogTags, get_splight_logger
17
- from splight_models import File
18
-
19
- from .classmap import CLASSMAP
20
-
21
- logger = get_splight_logger()
22
-
23
- REQUEST_EXCEPTIONS = (ConnectionError, Timeout)
24
-
25
-
26
- class DatabaseClient(AbstractDatabaseClient, AbstractRemoteClient):
27
- """Splight API Database Client.
28
- Responsible for interacting with database resources using HTTP requests
29
- to the Splight API.
30
- """
31
-
32
- def __init__(self, namespace: str = "default"):
33
- super(DatabaseClient, self).__init__(namespace=namespace)
34
- self._base_url = furl(settings.SPLIGHT_PLATFORM_API_HOST)
35
- token = SplightAuthToken(
36
- access_key=settings.SPLIGHT_ACCESS_ID,
37
- secret_key=settings.SPLIGHT_SECRET_KEY,
38
- )
39
- self._session = Session()
40
- self._session.headers.update(token.header)
41
- logger.info("Database client initialized.", tags=LogTags.DATABASE)
42
-
43
- @retry(REQUEST_EXCEPTIONS, tries=3, delay=1)
44
- def save(self, instance: BaseModel) -> BaseModel:
45
- """Creates or updates a new resource depending on the model if
46
- it contains the id or not.
47
-
48
- Parameters
49
- ----------
50
- instance : BaseModel
51
- The instance of the model to be created or updated
52
-
53
- Returns
54
- -------
55
- BaseModel with the created or updated resource.
56
-
57
- Raises
58
- ------
59
- InvalidModel thrown when the model name is not correct.
60
- """
61
- logger.debug("Saving instance %s.", instance.id, tags=LogTags.DATABASE)
62
-
63
- constructor = type(instance)
64
- model_data = self._get_model_data(constructor)
65
-
66
- path = model_data["path"]
67
- if instance.id:
68
- output = self._update(path, instance.id, instance)
69
- else:
70
- output = self._create(path, instance)
71
- instance.id = output["id"]
72
- return constructor.parse_obj(output)
73
-
74
- @retry(REQUEST_EXCEPTIONS, tries=3, delay=1)
75
- def delete(self, resource_type: Type, id: str):
76
- """Deletes a resource from the database
77
-
78
- Parameters
79
- ----------
80
- resource_type : Type
81
- The resource type to be deleted
82
- id : str
83
- The resource's id.
84
-
85
- Raises
86
- ------
87
- InvalidModel thrown when the model name is not correct.
88
- """
89
- logger.debug("Deleting instance %s.", id, tags=LogTags.DATABASE)
90
- model_data = self._get_model_data(resource_type)
91
- path = model_data["path"]
92
- url = self._base_url / f"{path}/{id}/"
93
- response = self._session.delete(url)
94
- response.raise_for_status()
95
-
96
- @retry(REQUEST_EXCEPTIONS, tries=3, delay=1)
97
- def _get(
98
- self,
99
- resource_type: Type,
100
- first: bool = False,
101
- limit_: int = -1,
102
- skip_: int = 0,
103
- page_size: int = -1,
104
- deleted: bool = False,
105
- **kwargs,
106
- ) -> List[BaseModel]:
107
- model_data = self._get_model_data(resource_type)
108
- path = model_data["path"]
109
- response = self._list(
110
- path,
111
- limit_=limit_,
112
- skip_=skip_,
113
- deleted=deleted,
114
- page_size=page_size,
115
- **kwargs,
116
- )
117
- parsed = [
118
- resource_type.parse_obj(resource)
119
- for resource in response["results"]
120
- ]
121
- if first:
122
- return parsed[0] if parsed else None
123
- return parsed
124
-
125
- @retry(REQUEST_EXCEPTIONS, tries=3, delay=1)
126
- def count(self, resource_type: Type, **kwargs) -> int:
127
- """Returns the number of resources in the database for a given model
128
-
129
- Parameters
130
- ----------
131
- resource_type : str
132
- The model name
133
-
134
- Returns
135
- -------
136
- int
137
-
138
- Raises
139
- ------
140
- InvalidModel thrown when the model name is not correct.
141
- """
142
-
143
- model_data = self._get_model_data(resource_type)
144
- path = model_data["path"]
145
- kwargs["page"] = 1 # Always start from the first page
146
- response = self._list(path, **kwargs)
147
- logger.debug(
148
- "Counted %s objects of type: %s.",
149
- response["count"],
150
- resource_type,
151
- tags=LogTags.DATABASE,
152
- )
153
- return response["count"]
154
-
155
- @retry(REQUEST_EXCEPTIONS, tries=3, delay=1)
156
- def download(
157
- self, instance: BaseModel, decrypt: bool = True, **kwargs
158
- ) -> NamedTemporaryFile:
159
- """Returns the number of resources in the database for a given model
160
-
161
- Parameters
162
- ----------
163
- instance : BaseModel
164
- The instance of the model to be downloaded
165
-
166
- Returns
167
- -------
168
- TemporaryFile
169
- the file object
170
-
171
- Raises
172
- ------
173
- InvalidModel thrown when the model name is not correct.
174
- """
175
- constructor = type(instance)
176
- model_data = self._get_model_data(constructor)
177
- path = model_data["path"]
178
- url = self._base_url / f"{path}/{instance.id}/download"
179
- response = self._session.get(url)
180
- response.raise_for_status()
181
- f = NamedTemporaryFile("wb+")
182
- f.write(response.content)
183
- f.seek(0)
184
- if decrypt and instance.encrypted:
185
- encryption_manager = EncryptionClient()
186
- encryption_manager.decrypt_file(path=f.name)
187
- logger.debug("Downloaded instance %s.", id, tags=LogTags.DATABASE)
188
- return f
189
-
190
- def _pages(self, path: str, **kwargs):
191
- next_page = kwargs["page"]
192
- while next_page:
193
- response = self._list(path, **kwargs)
194
- yield response
195
- next_page = (
196
- response["next"].split("page=")[1]
197
- if response["next"]
198
- else None
199
- )
200
- kwargs["page"] = next_page
201
-
202
- def _list(self, path: str, **kwargs):
203
- url = self._base_url / f"{path}/"
204
- params = self._parse_params(**kwargs)
205
- response = self._session.get(url, params=params)
206
- response.raise_for_status()
207
- return response.json()
208
-
209
- @staticmethod
210
- def _get_model_data(constructor: Type):
211
- model_data = CLASSMAP.get(constructor)
212
- if not model_data:
213
- raise InvalidModel(constructor.schema()["title"])
214
- return model_data
215
-
216
- def _create(self, path: str, instance: BaseModel) -> Dict:
217
- url = self._base_url / f"{path}/"
218
- data = json.loads(instance.json(exclude_none=True))
219
- if isinstance(instance, File):
220
- with open(instance.file, "rb") as f:
221
- file = {"file": f}
222
- response = self._session.post(url, data=data, files=file)
223
- else:
224
- response = self._session.post(url, json=data)
225
-
226
- response.raise_for_status()
227
- return response.json()
228
-
229
- def _update(self, path: str, resource_id: str, data: BaseModel) -> Dict:
230
- url = self._base_url / f"{path}/{resource_id}/"
231
- response = self._session.put(
232
- url, json=json.loads(data.json(exclude_none=True))
233
- )
234
- response.raise_for_status()
235
- return response.json()
@@ -1 +0,0 @@
1
- from .client import DatalakeClient
@@ -1,259 +0,0 @@
1
- import json
2
- from datetime import timedelta, timezone
3
- from io import StringIO
4
- from tempfile import NamedTemporaryFile
5
- from typing import Dict, List, Union
6
-
7
- import pandas as pd
8
- from furl import furl
9
- from pydantic import BaseModel
10
- from remote_splight_lib.auth import SplightAuthToken
11
- from remote_splight_lib.settings import settings
12
- from retry import retry
13
- from splight_abstract import AbstractRemoteClient, QuerySet
14
- from splight_abstract.datalake import (
15
- AbstractDatalakeClient,
16
- validate_datalake_instance_type,
17
- validate_datalake_resource_type,
18
- )
19
- from splight_lib.logging._internal import LogTags, get_splight_logger
20
- from splight_lib.restclient import (
21
- ConnectError,
22
- HTTPError,
23
- SplightRestClient,
24
- Timeout,
25
- )
26
- from splight_models import DatalakeModel, Query
27
-
28
- logger = get_splight_logger()
29
-
30
- REQUEST_EXCEPTIONS = (HTTPError, Timeout, ConnectError)
31
-
32
-
33
- class DatalakeClient(AbstractDatalakeClient, AbstractRemoteClient):
34
- _PREFIX = "v2/engine/datalake"
35
-
36
- def __init__(self, namespace: str = "default"):
37
- super(DatalakeClient, self).__init__(namespace=namespace)
38
- self._base_url = furl(settings.SPLIGHT_PLATFORM_API_HOST)
39
- token = SplightAuthToken(
40
- access_key=settings.SPLIGHT_ACCESS_ID,
41
- secret_key=settings.SPLIGHT_SECRET_KEY,
42
- )
43
- self._restclient = SplightRestClient()
44
- self._restclient.update_headers(token.header)
45
- logger.info("Datalake client initialized.", tags=LogTags.DATALAKE)
46
-
47
- @retry(REQUEST_EXCEPTIONS, tries=3, delay=2, jitter=1)
48
- def _raw_save(
49
- self,
50
- collection: str,
51
- instances: List[DatalakeModel],
52
- ) -> List[DatalakeModel]:
53
- url = self._base_url / f"{self._PREFIX}/save/"
54
- data = [json.loads(model.json()) for model in instances]
55
- response = self._restclient.post(
56
- url, params={"source": collection}, json=data
57
- )
58
- response.raise_for_status()
59
- return instances
60
-
61
- @retry(REQUEST_EXCEPTIONS, tries=3, delay=2, jitter=1)
62
- def _raw_get(
63
- self,
64
- resource_type: DatalakeModel,
65
- collection: str,
66
- limit_: int = 50,
67
- skip_: int = 0,
68
- sort: Union[List, str] = ["timestamp__desc"],
69
- group_id: Union[List, str] = [],
70
- group_fields: Union[List, str] = [],
71
- tzinfo: timezone = timezone(timedelta()),
72
- **kwargs,
73
- ) -> List[BaseModel]:
74
- # /datalake/data/
75
- url = self._base_url / f"{self._PREFIX}/data/"
76
- valid_kwargs = self._validated_kwargs(resource_type, **kwargs)
77
- valid_kwargs.update(
78
- {
79
- "source": collection,
80
- "limit_": limit_,
81
- "skip_": skip_,
82
- "sort": sort,
83
- # "tzinfo": tzinfo
84
- }
85
- )
86
- if group_id:
87
- valid_kwargs.update({"group_id": group_id})
88
- if group_fields:
89
- valid_kwargs.update({"group_fields": group_fields})
90
- params = self._parse_params(**valid_kwargs)
91
- response = self._restclient.get(url, params=params)
92
- response.raise_for_status()
93
- output = [
94
- resource_type.parse_obj(item)
95
- for item in response.json()["results"]
96
- ]
97
- return output
98
-
99
- @retry(REQUEST_EXCEPTIONS, tries=3, delay=2, jitter=1)
100
- def _raw_delete(self, collection: str, **kwargs) -> None:
101
- # DELETE /datalake/delete/
102
- url = self._base_url / f"{self._PREFIX}/delete/"
103
- params = {"source": collection}
104
- response = self._restclient.delete(url, params=params, json=kwargs)
105
- response.raise_for_status()
106
-
107
- @validate_datalake_resource_type
108
- def get(
109
- self,
110
- resource_type: DatalakeModel,
111
- *args,
112
- **kwargs,
113
- ) -> List[BaseModel]:
114
- logger.debug(
115
- "Retrieving object of type %s from datalake.",
116
- resource_type,
117
- tags=LogTags.DATALAKE,
118
- )
119
- kwargs["get_func"] = "_raw_get"
120
- kwargs["count_func"] = "None"
121
- kwargs["collection"] = resource_type.Meta.collection_name
122
- kwargs["resource_type"] = resource_type
123
- return QuerySet(self, *args, **kwargs)
124
-
125
- def get_output(
126
- self, resource_type: DatalakeModel, query: Query
127
- ) -> List[Dict]:
128
- # TODO: Add add_fields, project and renaming
129
- logger.debug(
130
- "Retrieving output of type %s from datalake.",
131
- resource_type,
132
- tags=LogTags.DATALAKE,
133
- )
134
- return self._raw_get(
135
- resource_type=resource_type,
136
- collection=query.source,
137
- limit_=query.limit,
138
- skip_=query.skip,
139
- sort=query.sort,
140
- group_id=query.group_id,
141
- group_fields=query.group_fields,
142
- tzinfo=timezone(timedelta(hours=query.timezone_offset)),
143
- **query.filters,
144
- )
145
-
146
- @retry(REQUEST_EXCEPTIONS, tries=3, delay=2, jitter=1)
147
- @validate_datalake_resource_type
148
- def get_dataframe(
149
- self, resource_type: DatalakeModel, **kwargs
150
- ) -> pd.DataFrame:
151
- # GET /datalake/dumpdata/?source=collection
152
- url = self._base_url / f"{self._PREFIX}/dumpdata/"
153
- collection = resource_type.Meta.collection_name
154
- kwargs.update({"source": collection})
155
- params = self._parse_params(**kwargs)
156
- response = self._restclient.get(url, params=params)
157
- response.raise_for_status()
158
- logger.debug(
159
- "Retrieving dataframe from datalake.", tags=LogTags.DATALAKE
160
- )
161
-
162
- df: pd.DataFrame = pd.DataFrame(pd.read_csv(StringIO(response.text)))
163
- if df.empty:
164
- return df
165
- df["timestamp"] = pd.to_datetime(df["timestamp"])
166
- df.set_index("timestamp", inplace=True)
167
- return df
168
-
169
- def get_dataset(
170
- self, resource_type: DatalakeModel, queries: List[Dict]
171
- ) -> pd.DataFrame:
172
- # TODO this should be
173
- # def get_dataset(self, queries: List[Query]) -> pd.DataFrame:
174
- logger.debug(
175
- "Retrieving dataset from datalake.", tags=LogTags.DATALAKE
176
- )
177
-
178
- dfs = [
179
- self.get_dataframe(resource_type=resource_type, **query)
180
- for query in queries
181
- ]
182
- if dfs:
183
- return pd.concat(dfs, axis=1)
184
- return pd.DataFrame(dfs)
185
-
186
- @validate_datalake_instance_type
187
- def save(
188
- self,
189
- instances: List[DatalakeModel],
190
- ) -> List[DatalakeModel]:
191
- # POST /datalake/save/
192
- logger.debug("Saving instances %s.", instances, tags=LogTags.DATALAKE)
193
- if not instances:
194
- return instances
195
- resource_type = instances[0].__class__
196
- collection = resource_type.Meta.collection_name
197
- return self._raw_save(collection=collection, instances=instances)
198
-
199
- @retry(REQUEST_EXCEPTIONS, tries=3, delay=2, jitter=1)
200
- @validate_datalake_resource_type
201
- def save_dataframe(
202
- self, resource_type: DatalakeModel, dataframe: pd.DataFrame
203
- ) -> None:
204
- # POST /datalake/loaddata/
205
- logger.debug("Saving dataframe.", tags=LogTags.DATALAKE)
206
-
207
- url = self._base_url / f"{self._PREFIX}/loaddata/"
208
-
209
- tmp_file = NamedTemporaryFile("w")
210
- with open(tmp_file.name, "wb") as fid:
211
- dataframe.to_csv(fid)
212
- collection = resource_type.Meta.collection_name
213
- response = self._restclient.post(
214
- url,
215
- data={"source": collection},
216
- files={"file": open(tmp_file.name, mode="rb")},
217
- )
218
- response.raise_for_status()
219
-
220
- @validate_datalake_resource_type
221
- def delete(self, resource_type: DatalakeModel, **kwargs) -> None:
222
- logger.debug(
223
- "Deleting resources of type %s from datalake.",
224
- resource_type,
225
- tags=LogTags.DATALAKE,
226
- )
227
-
228
- collection = resource_type.Meta.collection_name
229
- return self._raw_delete(collection=collection, **kwargs)
230
-
231
- @retry(REQUEST_EXCEPTIONS, tries=3, delay=2, jitter=1)
232
- def create_index(self, collection: str, indexes: List[Dict]) -> None:
233
- # POST /datalake/index/
234
- logger.debug(
235
- "Creating index for collection: %s.",
236
- collection,
237
- tags=LogTags.DATALAKE,
238
- )
239
- url = self._base_url / f"{self._PREFIX}/index/"
240
- data = {"source": collection, "index": indexes}
241
- response = self._restclient.post(url, json=data)
242
- response.raise_for_status()
243
-
244
- @retry(REQUEST_EXCEPTIONS, tries=3, delay=2, jitter=1)
245
- def raw_aggregate(
246
- self, collection: str, pipeline: List[Dict]
247
- ) -> List[Dict]:
248
- logger.debug(
249
- "Aggregate on datalake collection: %s.",
250
- collection,
251
- tags=LogTags.DATALAKE,
252
- )
253
- # POST /datalake/aggregate/?source=collection
254
- url = self._base_url / f"{self._PREFIX}/aggregate/"
255
- params = {"source": collection}
256
- data = {"pipeline": pipeline}
257
- response = self._restclient.post(url, params=params, data=data)
258
- response.raise_for_status()
259
- return response.json()
@@ -1,6 +0,0 @@
1
- class InvalidModel(Exception):
2
- def __init__(self, model_name: str):
3
- self._msg = f"Model {model_name} is not a valid database model"
4
-
5
- def __str__(self) -> str:
6
- return self._msg
@@ -1 +0,0 @@
1
- from remote_splight_lib.hub.client import SplightHubClient
@@ -1,18 +0,0 @@
1
- from pydantic import BaseSettings, Field
2
-
3
-
4
- class SplightRemoteSettings(BaseSettings):
5
- # TODO: Unify env variables accross all the platform/lib/components
6
- SPLIGHT_PLATFORM_API_HOST: str = Field(
7
- "https://api.splight-ae.com",
8
- env=["SPLIGHT_PLATFORM_API_HOST", "SPLIGHT_API_HOST"],
9
- )
10
- SPLIGHT_ACCESS_ID: str = Field(
11
- ..., env=["SPLIGHT_ACCESS_ID", "SPLIGHT_AUTH_ACCESS_ID"]
12
- )
13
- SPLIGHT_SECRET_KEY: str = Field(
14
- ..., env=["SPLIGHT_SECRET_KEY", "SPLIGHT_AUTH_SECRET_KEY"]
15
- )
16
-
17
-
18
- settings = SplightRemoteSettings()
@@ -1,33 +0,0 @@
1
- from splight_models import (
2
- Alert,
3
- AlertCondition,
4
- Asset,
5
- Attribute,
6
- BlockchainContract,
7
- Component,
8
- ComponentCommand,
9
- ComponentObject,
10
- File,
11
- HubComponent,
12
- Notification,
13
- Query,
14
- Secret,
15
- SetPoint,
16
- )
17
-
18
- CLASSMAP = {
19
- Component: {"path": "v2/engine/component/components"},
20
- Alert: {"path": "v2/engine/alert/alerts"},
21
- AlertCondition: {"path": "v2/engine/alert/conditions"},
22
- Asset: {"path": "v2/engine/assets"},
23
- Attribute: {"path": "v2/engine/attributes"},
24
- File: {"path": "v2/engine/files"},
25
- Notification: {"path": "v2/account/notifications"},
26
- BlockchainContract: {"path": "v2/backoffice/blockchain/contracts"},
27
- ComponentObject: {"path": "v2/engine/component/objects"},
28
- ComponentCommand: {"path": "v2/engine/component/commands"},
29
- Query: {"path": "v2/engine/queries"},
30
- Secret: {"path": "v2/engine/secrets"},
31
- HubComponent: {"path": "v2/engine/hub/component-versions"},
32
- SetPoint: {"path": "v2/engine/setpoints"},
33
- }
File without changes
File without changes
File without changes