dc-python-sdk 1.5.48__py3-none-any.whl → 1.5.49__py3-none-any.whl

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dc-python-sdk
3
- Version: 1.5.48
3
+ Version: 1.5.49
4
4
  Summary: Data Connector Python SDK
5
5
  Home-page: https://github.com/data-connector/dc-python-sdk
6
6
  Author: DataConnector
@@ -1,14 +1,15 @@
1
- dc_python_sdk-1.5.48.dist-info/licenses/LICENSE,sha256=ACwmltkrXIz5VsEQcrqljq-fat6ZXAMepjXGoe40KtE,1069
1
+ dc_python_sdk-1.5.49.dist-info/licenses/LICENSE,sha256=ACwmltkrXIz5VsEQcrqljq-fat6ZXAMepjXGoe40KtE,1069
2
2
  dc_sdk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  dc_sdk/app.py,sha256=VeGe1q2F71XtZp9VWBUlNowGcF6J-gYsqOu7k2CaeuU,8320
4
- dc_sdk/cli.py,sha256=fu4ePzpurYO_URvxyaaUuiptOLqiWiwLoieSbKeni3c,891
4
+ dc_sdk/cli.py,sha256=ZJFx7JR8RtndB96xyD68zJmwIvLD25dG0kyYqlkazfQ,848
5
5
  dc_sdk/errors.py,sha256=ajykvkoXXXfPfbb68FoI9I9zXAXi_D3C8vRFHLivb7c,13909
6
- dc_sdk/handler.py,sha256=zvdTq1ScxXNmELiZkY4Ot3ksZl8FEXf1AN-ExVA4CFo,6388
6
+ dc_sdk/handler.py,sha256=4OLamGvRoFu4dSirXq7y1-IcDKvqMeSUirg4gFf1dI8,7746
7
7
  dc_sdk/types.py,sha256=cqT1vvFzf7k3-BdKsxK9mWty9pa3jewjB7T4id_XyEE,899
8
8
  dc_sdk/src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  dc_sdk/src/ai.py,sha256=aIKN6TiBKF8ZJYNpcphwWNqtI34Ni36UipxT-AEyQ1I,23321
10
10
  dc_sdk/src/ai_http.py,sha256=9c1X4Sr-2uutTrovHSZVmAacLLwcmFaQ8vA-tOKC0L0,24696
11
- dc_sdk/src/mapping.py,sha256=NuXrdE1MuRVRT7ILpc86RrVJq60t6Dl_lnlG1A7Ulks,3653
11
+ dc_sdk/src/connection_status.py,sha256=HjagxTFfh8ckbijzC5S3nhYFNtdZi9fNzJ_lPCOtlEQ,893
12
+ dc_sdk/src/mapping.py,sha256=W0ES1Tz3s4LnJ5ipfvJiq1zk3zQkA-EzMdd_5ivTYVA,5902
12
13
  dc_sdk/src/pipeline.py,sha256=s0Orptelh651iBCs6XBCa4L8pGpCLt71EHuVwtVGNUE,25614
13
14
  dc_sdk/src/server.py,sha256=2ZhITJhVcj-jd4a-768lAmmmDjTWATGmgwKD-1OVOVI,3028
14
15
  dc_sdk/src/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -23,8 +24,8 @@ dc_sdk/src/services/environment.py,sha256=lKOuDyzFbjdriPVeVy1GGeuZjutzhwUsZCQcF8
23
24
  dc_sdk/src/services/loader.py,sha256=0zlQm4HOPKffN9Q6YlMv73fCMBsrwkEBnka5rEJTvqU,1175
24
25
  dc_sdk/src/services/logger.py,sha256=GrQGfgYfrzmPYFRHkctDSg54jvN7ObveETTPezYldXs,2055
25
26
  dc_sdk/src/services/session.py,sha256=SpaZ_qnxMbEZO5fxsbjw6WZXVP5JpncnWalgLqB3MYo,423
26
- dc_python_sdk-1.5.48.dist-info/METADATA,sha256=APRnb2zTaepQvRWmd1La9EGEP16vbzI70cryb8-DtmU,15980
27
- dc_python_sdk-1.5.48.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
28
- dc_python_sdk-1.5.48.dist-info/entry_points.txt,sha256=HSIKPlg7qer7Atu8oOKVpptahi_ZxqfJE-Bh2bmVSss,43
29
- dc_python_sdk-1.5.48.dist-info/top_level.txt,sha256=gD_FZnF6mZfFU5EmdB2knYHDHKfH5kXJMtSgEZga3BI,7
30
- dc_python_sdk-1.5.48.dist-info/RECORD,,
27
+ dc_python_sdk-1.5.49.dist-info/METADATA,sha256=9RlaOCysI6vgB4UyAY95I8KOywaBF2jd_BBYLC9kB4E,15980
28
+ dc_python_sdk-1.5.49.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
29
+ dc_python_sdk-1.5.49.dist-info/entry_points.txt,sha256=HSIKPlg7qer7Atu8oOKVpptahi_ZxqfJE-Bh2bmVSss,43
30
+ dc_python_sdk-1.5.49.dist-info/top_level.txt,sha256=gD_FZnF6mZfFU5EmdB2knYHDHKfH5kXJMtSgEZga3BI,7
31
+ dc_python_sdk-1.5.49.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (82.0.1)
2
+ Generator: setuptools (83.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
dc_sdk/cli.py CHANGED
@@ -18,8 +18,6 @@ def main():
18
18
 
19
19
  print("version: ", version("dc-python-sdk"))
20
20
 
21
- print(f"[DC SDK] Command: {command}")
22
-
23
21
  if command == "http":
24
22
  from dc_sdk.src.server import start_server
25
23
  start_server()
dc_sdk/handler.py CHANGED
@@ -1,5 +1,6 @@
1
1
  from dc_sdk.errors import Error
2
2
  from dc_sdk.src.mapping import Mapping
3
+ from dc_sdk.src.connection_status import STATUS_ERROR
3
4
  import traceback
4
5
  from importlib.metadata import version
5
6
 
@@ -9,7 +10,9 @@ def get_action_name(action: int) -> str:
9
10
  1: "retrieving fields",
10
11
  2: "retrieving 5 row preview",
11
12
  3: "testing connection",
12
- 4: "starting the connector"
13
+ 4: "starting the connector",
14
+ 5: "retrieving metadata",
15
+ 6: "retrieving objects",
13
16
  }[action]
14
17
 
15
18
  def apply_data_filters(results, data_filters):
@@ -159,6 +162,9 @@ def handler(event, context):
159
162
  mapping = None
160
163
  action = int(event['action']) if 'action' in event else 4
161
164
  get_objects = event.get('get_objects', True)
165
+ skip_authenticate = event.get('skip_authenticate', False)
166
+ force_authenticate = event.get('force_authenticate', False)
167
+ include_metadata = event.get('include_metadata', True)
162
168
  credentials_dict = event['credentials'] if 'credentials' in event else None
163
169
  object_id = event['object_id'] if 'object_id' in event else None
164
170
  field_ids = event['mapping'] if 'mapping' in event else None
@@ -174,9 +180,14 @@ def handler(event, context):
174
180
 
175
181
  if action == 0:
176
182
  if get_objects:
177
- results, message = mapping.connect_get_objects()
183
+ results, message = mapping.connect_get_objects(
184
+ skip_authenticate=skip_authenticate,
185
+ force_authenticate=force_authenticate,
186
+ )
178
187
  else:
179
- results, message = mapping.authenticate()
188
+ results, message = mapping.authenticate(
189
+ force_authenticate=force_authenticate or not skip_authenticate,
190
+ )
180
191
  elif action == 1:
181
192
  results, message = mapping.get_fields(object_id, options)
182
193
  elif action == 2:
@@ -185,6 +196,17 @@ def handler(event, context):
185
196
  results = apply_data_filters(results, data_filters)
186
197
  elif action == 3:
187
198
  results, message = mapping.test_connection()
199
+ elif action == 5:
200
+ results, message = mapping.get_metadata_only(
201
+ skip_authenticate=skip_authenticate,
202
+ force_authenticate=force_authenticate,
203
+ )
204
+ elif action == 6:
205
+ results, message = mapping.get_objects_only(
206
+ skip_authenticate=skip_authenticate,
207
+ force_authenticate=force_authenticate,
208
+ include_metadata=include_metadata,
209
+ )
188
210
  else:
189
211
  raise Error("Invalid action", "InvalidActionError")
190
212
  except Error as e:
@@ -192,19 +214,28 @@ def handler(event, context):
192
214
  internal_error = e.internal
193
215
  error_trace = traceback.format_exc()
194
216
  error = error_trace
217
+ if mapping:
218
+ mapping._set_connection_status(STATUS_ERROR)
195
219
 
196
220
  except Exception as e:
197
221
  error_trace = traceback.format_exc()
198
222
  error = error_trace
199
223
  internal_error = True
224
+ if mapping:
225
+ mapping._set_connection_status(STATUS_ERROR)
200
226
 
201
227
  if error:
202
228
  print(error)
203
229
 
230
+ last_status_dsc = None
231
+ if mapping and mapping.connector.credentials:
232
+ last_status_dsc = mapping.connector.credentials.get("last_status_dsc")
233
+
204
234
  return {
205
235
  'message': message if not internal_error else f"Something went wrong with {action_name}",
206
236
  'results': results,
207
237
  'credentials': mapping.connector.credentials if mapping else None,
238
+ 'last_status_dsc': last_status_dsc,
208
239
  'error': error,
209
240
  'internal_error': internal_error
210
241
  }
@@ -0,0 +1,34 @@
1
+ STATUS_CONNECTED = "Connected"
2
+ STATUS_ERROR = "Error"
3
+ STATUS_UNKNOWN = "Unknown"
4
+ STATUS_NOT_SETUP = "NotSetup"
5
+ STATUS_PENDING = "Pending"
6
+
7
+
8
+ def normalize_status(status):
9
+ if not status:
10
+ return STATUS_UNKNOWN
11
+
12
+ normalized = str(status).strip()
13
+ lowered = normalized.lower()
14
+
15
+ if lowered in ("connected", "success"):
16
+ return STATUS_CONNECTED
17
+ if lowered in ("error", "failed", "failed to connect"):
18
+ return STATUS_ERROR
19
+ if lowered in ("notsetup", "not_setup", "not setup"):
20
+ return STATUS_NOT_SETUP
21
+ if lowered == "pending":
22
+ return STATUS_PENDING
23
+ if lowered == "unknown":
24
+ return STATUS_UNKNOWN
25
+
26
+ return normalized
27
+
28
+
29
+ def should_skip_authenticate(status):
30
+ return normalize_status(status) == STATUS_CONNECTED
31
+
32
+
33
+ def status_from_authenticated(authenticated):
34
+ return STATUS_CONNECTED if authenticated else STATUS_ERROR
dc_sdk/src/mapping.py CHANGED
@@ -1,97 +1,176 @@
1
1
  from dc_sdk import errors
2
2
  import logging
3
3
  from dc_sdk.src.services.loader import load_connector
4
+ from dc_sdk.src.connection_status import (
5
+ STATUS_CONNECTED,
6
+ STATUS_ERROR,
7
+ should_skip_authenticate,
8
+ )
4
9
 
5
10
  logger = logging.getLogger(__name__)
11
+
12
+
6
13
  class Mapping():
7
14
  def __init__(self, credentials):
8
15
  Connector = load_connector()
9
16
  self.connector = Connector(credentials)
10
17
 
11
- def authenticate(self):
12
- results = None
13
- metadata = None
14
- message = None
18
+ def _set_connection_status(self, status):
19
+ if self.connector.credentials is None:
20
+ self.connector.credentials = {}
21
+ self.connector.credentials["last_status_dsc"] = status
15
22
 
16
- if self.connector.authenticate():
23
+ def _initialize_connector_session(self):
24
+ init = getattr(self.connector, "ensure_initialized", None)
25
+ if callable(init):
26
+ init()
27
+ return
28
+
29
+ legacy_init = getattr(self.connector, "_ensure_initialized", None)
30
+ if callable(legacy_init):
31
+ legacy_init()
32
+ return
33
+
34
+ if not self.connector.authenticate():
35
+ raise errors.AuthenticationError(message="Failed to initialize connection session")
36
+
37
+ def _ensure_session(self, force_authenticate=False):
38
+ credentials = self.connector.credentials or {}
39
+ status = credentials.get("last_status_dsc")
40
+
41
+ if not force_authenticate and should_skip_authenticate(status):
17
42
  try:
18
- metadata = self.connector.get_metadata()
19
- except errors.NotImplementedError:
20
- pass
21
- except:
22
- logger.exception("Error getting metadata")
43
+ self._initialize_connector_session()
44
+ return True
45
+ except Exception:
46
+ self._set_connection_status(STATUS_ERROR)
47
+ raise
48
+
49
+ if self.connector.authenticate():
50
+ self._set_connection_status(STATUS_CONNECTED)
51
+ return True
52
+
53
+ self._set_connection_status(STATUS_ERROR)
54
+ raise errors.AuthenticationError(message="Failed to authenticate")
55
+
56
+ def _resolve_session(self, skip_authenticate=False, force_authenticate=False):
57
+ if force_authenticate:
58
+ self._ensure_session(force_authenticate=True)
59
+ return
60
+
61
+ credentials = self.connector.credentials or {}
62
+ status = credentials.get("last_status_dsc")
63
+
64
+ if skip_authenticate and should_skip_authenticate(status):
65
+ self._ensure_session(force_authenticate=False)
66
+ return
67
+
68
+ if skip_authenticate and not should_skip_authenticate(status):
69
+ self._ensure_session(force_authenticate=True)
70
+ return
71
+
72
+ self._ensure_session(force_authenticate=False)
73
+
74
+ def _safe_get_metadata(self):
75
+ try:
76
+ return self.connector.get_metadata()
77
+ except errors.NotImplementedError:
78
+ return None
79
+ except Exception:
80
+ logger.exception("Error getting metadata")
81
+ return None
23
82
 
24
- results = {
25
- 'metadata': metadata
26
- }
83
+ def authenticate(self, force_authenticate=True):
84
+ results = None
85
+ message = None
86
+
87
+ self._ensure_session(force_authenticate=force_authenticate)
27
88
 
28
- message = "Authenticated successfully"
29
- else:
30
- raise errors.AuthenticationError(message="Failed to authenticate")
89
+ metadata = self._safe_get_metadata()
90
+ results = {
91
+ "metadata": metadata
92
+ }
93
+ message = "Authenticated successfully"
31
94
 
32
95
  return [results, message]
33
96
 
34
- def connect_get_objects(self):
97
+ def connect_get_objects(self, skip_authenticate=False, force_authenticate=False):
35
98
  results = None
36
99
  metadata = None
37
100
  objects = None
38
101
  message = None
39
102
 
40
- if self.connector.authenticate():
41
- objects = self.connector.get_objects()
42
- try:
43
- metadata = self.connector.get_metadata()
44
- except errors.NotImplementedError:
45
- pass
46
- except Exception as e:
47
- print("Error getting metadata")
48
- print(str(e))
49
-
50
- results = {
51
- 'metadata': metadata,
52
- 'objects': objects,
53
- }
54
- message = "Authenticated successfully"
55
- else:
56
- # If not authenticated, raise the authentication error.
57
- raise errors.AuthenticationError(message="Failed to authenticate")
103
+ self._resolve_session(
104
+ skip_authenticate=skip_authenticate,
105
+ force_authenticate=force_authenticate,
106
+ )
107
+
108
+ objects = self.connector.get_objects()
109
+ metadata = self._safe_get_metadata()
110
+
111
+ results = {
112
+ "metadata": metadata,
113
+ "objects": objects,
114
+ }
115
+ message = "Retrieved objects"
58
116
 
59
117
  return [results, message]
60
-
118
+
119
+ def get_metadata_only(self, skip_authenticate=False, force_authenticate=False):
120
+ self._resolve_session(
121
+ skip_authenticate=skip_authenticate,
122
+ force_authenticate=force_authenticate,
123
+ )
124
+
125
+ metadata = self._safe_get_metadata()
126
+ return [{"metadata": metadata}, "Retrieved metadata"]
127
+
128
+ def get_objects_only(self, skip_authenticate=False, force_authenticate=False, include_metadata=True):
129
+ self._resolve_session(
130
+ skip_authenticate=skip_authenticate,
131
+ force_authenticate=force_authenticate,
132
+ )
133
+
134
+ objects = self.connector.get_objects()
135
+ results = {"objects": objects}
136
+
137
+ if include_metadata:
138
+ results["metadata"] = self._safe_get_metadata()
139
+
140
+ return [results, "Retrieved objects"]
141
+
61
142
  def test_connection(self):
62
143
  results = None
63
144
  message = None
64
145
 
65
- if self.connector.authenticate():
66
- message = "Authenticated successfully"
67
- else:
68
- # If not authenticated, raise the authentication error.
69
- raise errors.AuthenticationError(message="Failed to authenticate")
146
+ self._ensure_session(force_authenticate=True)
147
+ message = "Authenticated successfully"
70
148
 
71
149
  return [results, message]
72
150
 
73
151
  def get_fields(self, object_id, options):
74
152
  results = None
75
153
  message = None
76
- if self.connector.authenticate():
77
- results = self.connector.get_fields(object_id, options=options)
78
- message = "Retrieved fields"
79
- else:
80
- # If not authenticated, raise the authentication error.
81
- raise errors.AuthenticationError("Failed to authenticate")
154
+ self._ensure_session(force_authenticate=False)
155
+ results = self.connector.get_fields(object_id, options=options)
156
+ message = "Retrieved fields"
82
157
 
83
158
  return [results, message]
84
159
 
85
- def get_five_row_preview(self, object_id, field_ids, options, n_rows = 5, filters = None, next_page = None):
160
+ def get_five_row_preview(self, object_id, field_ids, options, n_rows=5, filters=None, next_page=None):
86
161
  results = None
87
162
  message = None
88
163
 
89
- if self.connector.authenticate():
90
- results = self.connector.get_data(object_id, field_ids=field_ids, n_rows=n_rows, filters=filters, next_page=next_page, options=options)
91
- message = "Retrieved 5 row preview"
92
- else:
93
- # If not authenticated, raise the authentication error.
94
- raise errors.AuthenticationError("Failed to authenticate")
164
+ self._ensure_session(force_authenticate=False)
165
+ results = self.connector.get_data(
166
+ object_id,
167
+ field_ids=field_ids,
168
+ n_rows=n_rows,
169
+ filters=filters,
170
+ next_page=next_page,
171
+ options=options,
172
+ )
173
+ message = "Retrieved 5 row preview"
95
174
 
96
175
  return [results, message]
97
176
 
@@ -99,11 +178,14 @@ class Mapping():
99
178
  results = None
100
179
  message = None
101
180
 
102
- if self.connector.authenticate():
103
- results = self.connector.get_data(object_id, field_ids=field_ids, n_rows=n_rows, next_page=next_page, options=options)
104
- message = "Retrieved data"
105
- else:
106
- # If not authenticated, raise the authentication error.
107
- raise errors.AuthenticationError("Failed to authenticate")
181
+ self._ensure_session(force_authenticate=False)
182
+ results = self.connector.get_data(
183
+ object_id,
184
+ field_ids=field_ids,
185
+ n_rows=n_rows,
186
+ next_page=next_page,
187
+ options=options,
188
+ )
189
+ message = "Retrieved data"
108
190
 
109
- return [results, message]
191
+ return [results, message]