e6data-python-connector 2.1.21.dev0__py3-none-any.whl → 2.2.0rc0__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.
- e6data_python_connector/cluster_manager.py +1 -13
- e6data_python_connector/dialect.py +4 -1
- e6data_python_connector/e6data_grpc.py +27 -6
- {e6data_python_connector-2.1.21.dev0.dist-info → e6data_python_connector-2.2.0rc0.dist-info}/METADATA +3 -3
- {e6data_python_connector-2.1.21.dev0.dist-info → e6data_python_connector-2.2.0rc0.dist-info}/RECORD +9 -9
- {e6data_python_connector-2.1.21.dev0.dist-info → e6data_python_connector-2.2.0rc0.dist-info}/WHEEL +1 -1
- {e6data_python_connector-2.1.21.dev0.dist-info → e6data_python_connector-2.2.0rc0.dist-info}/LICENSE +0 -0
- {e6data_python_connector-2.1.21.dev0.dist-info → e6data_python_connector-2.2.0rc0.dist-info}/entry_points.txt +0 -0
- {e6data_python_connector-2.1.21.dev0.dist-info → e6data_python_connector-2.2.0rc0.dist-info}/top_level.txt +0 -0
|
@@ -25,13 +25,11 @@ class _StatusLock:
|
|
|
25
25
|
def __enter__(self):
|
|
26
26
|
self._status_thread_lock.acquire(timeout=self._LOCK_TIMEOUT)
|
|
27
27
|
self._status_multiprocessing_lock.acquire(timeout=self._LOCK_TIMEOUT)
|
|
28
|
-
print('Locked threads and processes.')
|
|
29
28
|
return self
|
|
30
29
|
|
|
31
30
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
32
31
|
self._status_thread_lock.release()
|
|
33
32
|
self._status_multiprocessing_lock.release()
|
|
34
|
-
print('Released threads and processes.')
|
|
35
33
|
|
|
36
34
|
|
|
37
35
|
status_lock = _StatusLock()
|
|
@@ -65,30 +63,25 @@ class ClusterManager:
|
|
|
65
63
|
"""
|
|
66
64
|
with status_lock as lock:
|
|
67
65
|
if lock.is_active:
|
|
68
|
-
print('Cluster is already active')
|
|
69
66
|
return True
|
|
70
67
|
status_payload = cluster_pb2.ClusterStatusRequest(
|
|
71
68
|
user=self._user,
|
|
72
69
|
password=self._password
|
|
73
70
|
)
|
|
74
71
|
current_status = self._get_connection.status(status_payload)
|
|
75
|
-
print('Current status', current_status)
|
|
76
72
|
if current_status.status == 'suspended':
|
|
77
73
|
payload = cluster_pb2.ResumeRequest(
|
|
78
74
|
user=self._user,
|
|
79
75
|
password=self._password
|
|
80
76
|
)
|
|
81
77
|
response = self._get_connection.resume(payload)
|
|
82
|
-
print('resuming response', response.status)
|
|
83
78
|
elif current_status.status == 'active':
|
|
84
|
-
print('Cluster is already active.')
|
|
85
79
|
return True
|
|
86
80
|
elif current_status.status != 'resuming':
|
|
87
81
|
"""
|
|
88
82
|
If cluster is in resuming state already, start watching for the status.
|
|
89
83
|
Cluster is in different state, cannot resume.
|
|
90
84
|
"""
|
|
91
|
-
print('Cluster is in different state, cannot resume.')
|
|
92
85
|
return False
|
|
93
86
|
while True:
|
|
94
87
|
try:
|
|
@@ -97,20 +90,15 @@ class ClusterManager:
|
|
|
97
90
|
password=self._password
|
|
98
91
|
)
|
|
99
92
|
response = self._get_connection.status(status_payload)
|
|
100
|
-
print(response)
|
|
101
93
|
if response.status == 'active':
|
|
102
94
|
lock.set_active()
|
|
103
|
-
print('Breaking because of status:', response.status)
|
|
104
95
|
return True
|
|
105
96
|
if response.status in ['suspended', 'failed']:
|
|
106
|
-
print('Breaking because of status:', response.status)
|
|
107
97
|
return False
|
|
108
98
|
if time.time() > self._timeout:
|
|
109
|
-
print('Breaking because of timeout')
|
|
110
99
|
return False
|
|
111
100
|
except _InactiveRpcError as e:
|
|
112
|
-
|
|
113
|
-
print('Retrying')
|
|
101
|
+
pass
|
|
114
102
|
time.sleep(5)
|
|
115
103
|
|
|
116
104
|
def suspend(self):
|
|
@@ -215,6 +215,7 @@ class E6dataDialect(default.DefaultDialect):
|
|
|
215
215
|
catalog_name = None
|
|
216
216
|
cluster_uuid = None
|
|
217
217
|
secure = False
|
|
218
|
+
auto_resume = False
|
|
218
219
|
|
|
219
220
|
def _dialect_specific_select_one(self):
|
|
220
221
|
return "NOOP"
|
|
@@ -230,6 +231,7 @@ class E6dataDialect(default.DefaultDialect):
|
|
|
230
231
|
self.catalog_name = url.query.get("catalog")
|
|
231
232
|
self.cluster_uuid = url.query.get("cluster-uuid")
|
|
232
233
|
self.secure = url.query.get("secure") == 'true'
|
|
234
|
+
self.auto_resume = url.query.get("auto-resume") == 'true'
|
|
233
235
|
if not self.catalog_name:
|
|
234
236
|
raise Exception('Please specify catalog in query parameter.')
|
|
235
237
|
|
|
@@ -242,7 +244,8 @@ class E6dataDialect(default.DefaultDialect):
|
|
|
242
244
|
"database": database,
|
|
243
245
|
"catalog": self.catalog_name,
|
|
244
246
|
"cluster_uuid": self.cluster_uuid,
|
|
245
|
-
'secure': self.secure
|
|
247
|
+
'secure': self.secure,
|
|
248
|
+
'auto_resume': self.auto_resume
|
|
246
249
|
}
|
|
247
250
|
return [], kwargs
|
|
248
251
|
|
|
@@ -53,14 +53,31 @@ def _parse_timestamp(value):
|
|
|
53
53
|
value = datetime.datetime.strptime(value, format)
|
|
54
54
|
else:
|
|
55
55
|
raise Exception(
|
|
56
|
-
'Cannot convert "{}" into a datetime'.format(value)
|
|
56
|
+
'Cannot convert "{}" into a datetime'.format(value)
|
|
57
|
+
)
|
|
57
58
|
else:
|
|
58
59
|
value = None
|
|
59
60
|
return value
|
|
60
61
|
|
|
61
62
|
|
|
62
|
-
TYPES_CONVERTER = {
|
|
63
|
-
|
|
63
|
+
TYPES_CONVERTER = {
|
|
64
|
+
"DECIMAL_TYPE": Decimal,
|
|
65
|
+
"TIMESTAMP_TYPE": _parse_timestamp
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def re_auth(func):
|
|
70
|
+
def wrapper(self, *args, **kwargs):
|
|
71
|
+
try:
|
|
72
|
+
return func(self, *args, **kwargs)
|
|
73
|
+
except _InactiveRpcError as e:
|
|
74
|
+
if e.code() == grpc.StatusCode.INTERNAL and 'Access denied' in e.details():
|
|
75
|
+
self.connection.get_re_authenticate_session_id()
|
|
76
|
+
return func(self, *args, **kwargs)
|
|
77
|
+
else:
|
|
78
|
+
raise e
|
|
79
|
+
|
|
80
|
+
return wrapper
|
|
64
81
|
|
|
65
82
|
|
|
66
83
|
class HiveParamEscaper(ParamEscaper):
|
|
@@ -202,6 +219,10 @@ class Connection(object):
|
|
|
202
219
|
)
|
|
203
220
|
self._client = e6x_engine_pb2_grpc.QueryEngineServiceStub(self._channel)
|
|
204
221
|
|
|
222
|
+
def get_re_authenticate_session_id(self):
|
|
223
|
+
self._session_id = None
|
|
224
|
+
return self.get_session_id
|
|
225
|
+
|
|
205
226
|
@property
|
|
206
227
|
def get_session_id(self):
|
|
207
228
|
"""
|
|
@@ -215,8 +236,7 @@ class Connection(object):
|
|
|
215
236
|
)
|
|
216
237
|
authenticate_response = self._client.authenticate(
|
|
217
238
|
authenticate_request,
|
|
218
|
-
metadata=_get_grpc_header(cluster=self.cluster_uuid)
|
|
219
|
-
# timeout=3
|
|
239
|
+
metadata=_get_grpc_header(cluster=self.cluster_uuid)
|
|
220
240
|
)
|
|
221
241
|
self._session_id = authenticate_response.sessionId
|
|
222
242
|
if not self._session_id:
|
|
@@ -497,6 +517,7 @@ class Cursor(DBAPICursor):
|
|
|
497
517
|
)
|
|
498
518
|
return self.connection.client.status(status_request, metadata=self.metadata)
|
|
499
519
|
|
|
520
|
+
@re_auth
|
|
500
521
|
def execute(self, operation, parameters=None, **kwargs):
|
|
501
522
|
"""Prepare and execute a database operation (query or command).
|
|
502
523
|
Return values are not defined.
|
|
@@ -552,6 +573,7 @@ class Cursor(DBAPICursor):
|
|
|
552
573
|
|
|
553
574
|
self._query_id = prepare_statement_response.queryId
|
|
554
575
|
self._engine_ip = prepare_statement_response.engineIP
|
|
576
|
+
|
|
555
577
|
execute_statement_request = e6x_engine_pb2.ExecuteStatementV2Request(
|
|
556
578
|
engineIP=self._engine_ip,
|
|
557
579
|
sessionId=self.connection.get_session_id,
|
|
@@ -636,7 +658,6 @@ class Cursor(DBAPICursor):
|
|
|
636
658
|
return self._fetch_all()
|
|
637
659
|
|
|
638
660
|
def fetchmany(self, size: int = None):
|
|
639
|
-
# _logger.info("fetching all from overriden method")
|
|
640
661
|
if size is None:
|
|
641
662
|
size = self.arraysize
|
|
642
663
|
if self._data is None:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: e6data-python-connector
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0rc0
|
|
4
4
|
Summary: Client for the e6data distributed SQL Engine.
|
|
5
5
|
Home-page: https://github.com/e6x-labs/e6data-python-connector
|
|
6
6
|
Author: Uniphi, Inc.
|
|
@@ -15,7 +15,7 @@ Classifier: Programming Language :: Python :: 3.8
|
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.9
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
License-File: LICENSE
|
|
18
|
-
Requires-Dist: sqlalchemy
|
|
18
|
+
Requires-Dist: sqlalchemy>=1.0.0
|
|
19
19
|
Requires-Dist: future
|
|
20
20
|
Requires-Dist: python-dateutil
|
|
21
21
|
Requires-Dist: pycryptodome
|
|
@@ -27,7 +27,7 @@ Requires-Dist: sqlalchemy
|
|
|
27
27
|
|
|
28
28
|
# e6data Python Connector
|
|
29
29
|
|
|
30
|
-

|
|
31
31
|
|
|
32
32
|
## Introduction
|
|
33
33
|
|
{e6data_python_connector-2.1.21.dev0.dist-info → e6data_python_connector-2.2.0rc0.dist-info}/RECORD
RENAMED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
e6data_python_connector/__init__.py,sha256=x_VwhPQ7XLlthR-NJL9Vl7lkLBRCG2pSjmyZSBHOBpM,103
|
|
2
|
-
e6data_python_connector/cluster_manager.py,sha256=
|
|
2
|
+
e6data_python_connector/cluster_manager.py,sha256=21UW7Sr4t5_ZlnxmcutLp-OI2jB1ldGnUmfRsa4qbxA,3635
|
|
3
3
|
e6data_python_connector/common.py,sha256=nk0CDQ5j1iu8DctBOXX4QypPYmxSgIgoA-Cn1UZXLic,9976
|
|
4
4
|
e6data_python_connector/constants.py,sha256=h5w0lWiFsxz__zUZRlo1f72-8mT_vt9gcWvtWh0viFI,682
|
|
5
5
|
e6data_python_connector/datainputstream.py,sha256=2XKW__PCGfTQ55Puqgie2LZdk_WU-YKwpEIUOQEF-sY,12592
|
|
6
6
|
e6data_python_connector/date_time_utils.py,sha256=zmIwRhEGJwDvCOUjAl6VTDWGppluA-DPl_ioHTNpJKI,14413
|
|
7
|
-
e6data_python_connector/dialect.py,sha256=
|
|
8
|
-
e6data_python_connector/e6data_grpc.py,sha256=
|
|
7
|
+
e6data_python_connector/dialect.py,sha256=hkVRjXxx9DhS8-aHpSoyMVhhHxVs3jdTE60x2aOAf5I,11312
|
|
8
|
+
e6data_python_connector/e6data_grpc.py,sha256=Zk0TMK61IGCII9biNI5GnGVbNF9uzWIuHftwLt4llCM,26695
|
|
9
9
|
e6data_python_connector/exceptions.py,sha256=vrUqdzMq3LjbCmvr5_TcRq9eKmdqGfe-uVjR0BJQf5U,382
|
|
10
10
|
e6data_python_connector/typeId.py,sha256=2EMNWK2SO5CBReNuJphma6xp-69r9GDwwys66t-kSk0,1777
|
|
11
11
|
e6data_python_connector/cluster_server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -21,9 +21,9 @@ e6data_python_connector/server/e6x_engine_pb2.py,sha256=BxJjbijNrEqXQTWEhzLm54Fq
|
|
|
21
21
|
e6data_python_connector/server/e6x_engine_pb2.pyi,sha256=_aQDLFbSCQ7ubK0Z5ZKh9_VAHFaXbMV55MXYXr85srg,18693
|
|
22
22
|
e6data_python_connector/server/e6x_engine_pb2_grpc.py,sha256=n-eTCsAjsmpgPA_bDansKZq_zMmqkK6TlQGn6IdT6L4,46671
|
|
23
23
|
e6data_python_connector/server/ttypes.py,sha256=uWxwSp4m6e-7SeSEckbZtSduGYmfzXWM09iy5eltBPA,21227
|
|
24
|
-
e6data_python_connector-2.
|
|
25
|
-
e6data_python_connector-2.
|
|
26
|
-
e6data_python_connector-2.
|
|
27
|
-
e6data_python_connector-2.
|
|
28
|
-
e6data_python_connector-2.
|
|
29
|
-
e6data_python_connector-2.
|
|
24
|
+
e6data_python_connector-2.2.0rc0.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
|
|
25
|
+
e6data_python_connector-2.2.0rc0.dist-info/METADATA,sha256=SpImMu_oNyTBJCGYfQshpGuL3_FJeK6sLCNyQMptYrE,6948
|
|
26
|
+
e6data_python_connector-2.2.0rc0.dist-info/WHEEL,sha256=UvcQYKBHoFqaQd6LKyqHw9fxEolWLQnlzP0h_LgJAfI,91
|
|
27
|
+
e6data_python_connector-2.2.0rc0.dist-info/entry_points.txt,sha256=MDK4cAOND0preLvq2Tlpnz00wXnP_Y_UopqJsAf3U7Y,77
|
|
28
|
+
e6data_python_connector-2.2.0rc0.dist-info/top_level.txt,sha256=ChOS6qLf-SQycXr0uBiVxomIfYfbH2SgwrOWhW79ab0,24
|
|
29
|
+
e6data_python_connector-2.2.0rc0.dist-info/RECORD,,
|
{e6data_python_connector-2.1.21.dev0.dist-info → e6data_python_connector-2.2.0rc0.dist-info}/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|