e6data-python-connector 2.2.3rc4__tar.gz → 2.2.4__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 (36) hide show
  1. {e6data_python_connector-2.2.3rc4/e6data_python_connector.egg-info → e6data_python_connector-2.2.4}/PKG-INFO +2 -2
  2. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/README.md +1 -1
  3. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector/cluster_manager.py +45 -28
  4. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector/e6data_grpc.py +293 -24
  5. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4/e6data_python_connector.egg-info}/PKG-INFO +2 -2
  6. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/setup.py +1 -1
  7. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/LICENSE +0 -0
  8. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/MANIFEST.in +0 -0
  9. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector/__init__.py +0 -0
  10. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector/cluster_server/__init__.py +0 -0
  11. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector/cluster_server/cluster_pb2.py +0 -0
  12. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector/cluster_server/cluster_pb2_grpc.py +0 -0
  13. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector/common.py +0 -0
  14. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector/constants.py +0 -0
  15. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector/datainputstream.py +0 -0
  16. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector/date_time_utils.py +0 -0
  17. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector/dialect.py +0 -0
  18. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector/e6x_vector/__init__.py +0 -0
  19. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector/e6x_vector/constants.py +0 -0
  20. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector/e6x_vector/ttypes.py +0 -0
  21. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector/exceptions.py +0 -0
  22. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector/server/QueryEngineService.py +0 -0
  23. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector/server/__init__.py +0 -0
  24. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector/server/constants.py +0 -0
  25. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector/server/e6x_engine_pb2.py +0 -0
  26. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector/server/e6x_engine_pb2.pyi +0 -0
  27. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector/server/e6x_engine_pb2_grpc.py +0 -0
  28. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector/server/ttypes.py +0 -0
  29. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector/typeId.py +0 -0
  30. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector.egg-info/SOURCES.txt +0 -0
  31. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector.egg-info/dependency_links.txt +0 -0
  32. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector.egg-info/entry_points.txt +0 -0
  33. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector.egg-info/requires.txt +0 -0
  34. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/e6data_python_connector.egg-info/top_level.txt +0 -0
  35. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/pyproject.toml +0 -0
  36. {e6data_python_connector-2.2.3rc4 → e6data_python_connector-2.2.4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: e6data-python-connector
3
- Version: 2.2.3rc4
3
+ Version: 2.2.4
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: e6data, Inc.
@@ -38,7 +38,7 @@ Dynamic: summary
38
38
 
39
39
  # e6data Python Connector
40
40
 
41
- ![version](https://img.shields.io/badge/version-2.2.3rc4-blue.svg)
41
+ ![version](https://img.shields.io/badge/version-2.2.4-blue.svg)
42
42
 
43
43
  ## Introduction
44
44
 
@@ -1,6 +1,6 @@
1
1
  # e6data Python Connector
2
2
 
3
- ![version](https://img.shields.io/badge/version-2.2.3rc4-blue.svg)
3
+ ![version](https://img.shields.io/badge/version-2.2.4-blue.svg)
4
4
 
5
5
  ## Introduction
6
6
 
@@ -8,6 +8,19 @@ import multiprocessing
8
8
 
9
9
 
10
10
  def _get_grpc_header(engine_ip=None, cluster=None):
11
+ """
12
+ Generate gRPC metadata headers for the request.
13
+
14
+ This function creates a list of metadata headers to be used in gRPC requests.
15
+ It includes optional headers for the engine IP and cluster UUID.
16
+
17
+ Args:
18
+ engine_ip (str, optional): The IP address of the engine. Defaults to None.
19
+ cluster (str, optional): The UUID of the cluster. Defaults to None.
20
+
21
+ Returns:
22
+ list: A list of tuples representing the gRPC metadata headers.
23
+ """
11
24
  metadata = []
12
25
  if engine_ip:
13
26
  metadata.append(('plannerip', engine_ip))
@@ -123,7 +136,7 @@ class ClusterManager:
123
136
  cluster_uuid (str): The unique identifier for the target cluster.
124
137
  """
125
138
 
126
- def __init__(self, host: str, port: int, user: str, password: str, secure_channel: bool = False, timeout=60 * 3, cluster_uuid=None):
139
+ def __init__(self, host: str, port: int, user: str, password: str, secure_channel: bool = False, timeout=60 * 3, cluster_uuid=None, grpc_options=None):
127
140
  """
128
141
  Initializes a new instance of the ClusterManager class.
129
142
 
@@ -147,6 +160,9 @@ class ClusterManager:
147
160
  self._timeout = time.time() + timeout
148
161
  self._secure_channel = secure_channel
149
162
  self.cluster_uuid = cluster_uuid
163
+ self._grpc_options = grpc_options
164
+ if grpc_options is None:
165
+ self._grpc_options = dict()
150
166
 
151
167
  @property
152
168
  def _get_connection(self):
@@ -161,14 +177,34 @@ class ClusterManager:
161
177
  if self._secure_channel:
162
178
  self._channel = grpc.secure_channel(
163
179
  target='{}:{}'.format(self._host, self._port),
180
+ options=self._grpc_options,
164
181
  credentials=grpc.ssl_channel_credentials()
165
182
  )
166
183
  else:
167
184
  self._channel = grpc.insecure_channel(
168
- target='{}:{}'.format(self._host, self._port)
185
+ target='{}:{}'.format(self._host, self._port),
186
+ options=self._grpc_options
169
187
  )
170
188
  return cluster_pb2_grpc.ClusterServiceStub(self._channel)
171
189
 
190
+ def _check_cluster_status(self):
191
+ while True:
192
+ try:
193
+ # Create a status request payload with user credentials
194
+ status_payload = cluster_pb2.ClusterStatusRequest(
195
+ user=self._user,
196
+ password=self._password
197
+ )
198
+ # Send the status request to the cluster service
199
+ response = self._get_connection.status(
200
+ status_payload,
201
+ metadata=_get_grpc_header(cluster=self.cluster_uuid)
202
+ )
203
+ # Yield the current status
204
+ yield response.status
205
+ except _InactiveRpcError as e:
206
+ yield None
207
+
172
208
  def resume(self) -> bool:
173
209
  """
174
210
  Resumes the cluster if it is currently suspended or not in the 'active' state.
@@ -220,7 +256,6 @@ class ClusterManager:
220
256
  payload,
221
257
  metadata=_get_grpc_header(cluster=self.cluster_uuid)
222
258
  )
223
- print(f'Cluster resume response: {response}')
224
259
  elif current_status.status == 'active':
225
260
  return True
226
261
  elif current_status.status != 'resuming':
@@ -228,34 +263,16 @@ class ClusterManager:
228
263
  If cluster cannot be resumed due to its current state,
229
264
  or already in a process of resuming, terminate the operation.
230
265
  """
231
- print(f'Cluster is not suspended status, raising error.')
232
266
  return False
233
267
 
234
- # Wait for the cluster to become active
235
- while True:
236
- try:
237
- status_payload = cluster_pb2.ClusterStatusRequest(
238
- user=self._user,
239
- password=self._password
240
- )
241
- response = self._get_connection.status(
242
- status_payload,
243
- metadata=_get_grpc_header(cluster=self.cluster_uuid)
244
- )
245
- print(f'Cluster status response: {response}')
246
- if response.status == 'active':
247
- print('Cluster is now active, starting execution.')
248
- lock.set_active()
249
- return True
250
- if response.status in ['suspended', 'failed']:
251
- print(f'Trying to resume the cluster, found status: {response.status}, raising error.')
252
- return False
253
- if time.time() > self._timeout:
254
- print('Cluster resume timed out.')
255
- return False
256
- except _InactiveRpcError as e:
257
- pass
268
+ for status in self._check_cluster_status():
269
+ if status == 'active':
270
+ return True
271
+ elif status == 'failed' or time.time() > self._timeout:
272
+ return False
273
+ # Wait for 5 seconds before the next status check
258
274
  time.sleep(5)
275
+ return False
259
276
 
260
277
  def suspend(self):
261
278
  """
@@ -262,6 +262,18 @@ class Connection(object):
262
262
  self._client = e6x_engine_pb2_grpc.QueryEngineServiceStub(self._channel)
263
263
 
264
264
  def get_re_authenticate_session_id(self):
265
+ """
266
+ Re-authenticates the session by closing the current connection and creating a new client.
267
+
268
+ This method is used to re-establish the session ID by closing the existing gRPC channel,
269
+ creating a new client, and then retrieving a new session ID.
270
+
271
+ Returns:
272
+ str: The new session ID after re-authentication.
273
+
274
+ Raises:
275
+ Exception: If there is an error during the re-authentication process.
276
+ """
265
277
  self.close()
266
278
  self._create_client()
267
279
  return self.get_session_id
@@ -316,35 +328,58 @@ class Connection(object):
316
328
  raise e
317
329
  return self._session_id
318
330
 
319
- def update_users(self, user_info):
320
- self.client.updateUsers(userInfo=user_info)
321
-
322
- def set_prop_map(self, prop_map: str):
323
- """
324
- To enable to disable the caches.
325
- :param prop_map: To set engine props
331
+ def __enter__(self):
326
332
  """
327
- set_props_request = e6x_engine_pb2.SetPropsRequest(sessionId=self.get_session_id, props=prop_map)
328
- self._client.setProps(set_props_request)
333
+ Enters the runtime context related to this object.
329
334
 
330
- def __enter__(self):
331
- """Transport should already be opened by __init__"""
335
+ This method is called when the execution flow enters the context of the `with` statement.
336
+
337
+ Returns:
338
+ Connection: The current instance of the connection.
339
+ """
332
340
  return self
333
341
 
334
342
  def __exit__(self, exc_type, exc_val, exc_tb):
335
- """Call close"""
343
+ """
344
+ Exits the runtime context related to this object.
345
+
346
+ This method is called when the execution flow exits the context of the `with` statement.
347
+
348
+ Args:
349
+ exc_type (Type[BaseException]): The type of exception raised (if any).
350
+ exc_val (BaseException): The exception instance raised (if any).
351
+ exc_tb (Traceback): The traceback object of the exception (if any).
352
+ """
336
353
  self.close()
337
354
 
338
355
  def close(self):
356
+ """
357
+ Closes the gRPC channel and resets the session ID.
358
+
359
+ This method ensures that the gRPC channel is properly closed and the session ID is reset to None.
360
+ """
339
361
  if self._channel is not None:
340
362
  self._channel.close()
341
363
  self._channel = None
342
364
  self._session_id = None
343
365
 
344
366
  def check_connection(self):
367
+ """
368
+ Checks if the gRPC channel is still open.
369
+
370
+ Returns:
371
+ bool: True if the gRPC channel is open, False otherwise.
372
+ """
345
373
  return self._channel is not None
346
374
 
347
375
  def clear(self, query_id, engine_ip=None):
376
+ """
377
+ Clears the query results from the server.
378
+
379
+ Args:
380
+ query_id (str): The ID of the query to be cleared.
381
+ engine_ip (str, optional): The IP address of the engine. Defaults to None.
382
+ """
348
383
  clear_request = e6x_engine_pb2.ClearRequest(
349
384
  sessionId=self.get_session_id,
350
385
  queryId=query_id,
@@ -356,10 +391,22 @@ class Connection(object):
356
391
  )
357
392
 
358
393
  def reopen(self):
394
+ """
395
+ Reopens the gRPC channel by closing the current channel and creating a new client.
396
+
397
+ This method is useful for re-establishing the connection if it was previously closed.
398
+ """
359
399
  self._channel.close()
360
400
  self._create_client()
361
401
 
362
402
  def query_cancel(self, engine_ip, query_id):
403
+ """
404
+ Cancels the execution of a query on the server.
405
+
406
+ Args:
407
+ engine_ip (str): The IP address of the engine.
408
+ query_id (str): The ID of the query to be canceled.
409
+ """
363
410
  cancel_query_request = e6x_engine_pb2.CancelQueryRequest(
364
411
  engineIP=engine_ip,
365
412
  sessionId=self.get_session_id,
@@ -371,6 +418,15 @@ class Connection(object):
371
418
  )
372
419
 
373
420
  def dry_run(self, query):
421
+ """
422
+ Performs a dry run of the query to validate its syntax and structure.
423
+
424
+ Args:
425
+ query (str): The SQL query to be validated.
426
+
427
+ Returns:
428
+ str: The result of the dry run validation.
429
+ """
374
430
  dry_run_request = e6x_engine_pb2.DryRunRequest(
375
431
  sessionId=self.get_session_id,
376
432
  schema=self.database,
@@ -383,6 +439,16 @@ class Connection(object):
383
439
  return dry_run_response.dryrunValue
384
440
 
385
441
  def get_tables(self, catalog, database):
442
+ """
443
+ Retrieves the list of tables from the specified catalog and database.
444
+
445
+ Args:
446
+ catalog (str): The catalog name.
447
+ database (str): The database name.
448
+
449
+ Returns:
450
+ list: A list of table names.
451
+ """
386
452
  get_table_request = e6x_engine_pb2.GetTablesV2Request(
387
453
  sessionId=self.get_session_id,
388
454
  schema=database,
@@ -395,6 +461,17 @@ class Connection(object):
395
461
  return list(get_table_response.tables)
396
462
 
397
463
  def get_columns(self, catalog, database, table):
464
+ """
465
+ Retrieves the list of columns for the specified table in the given catalog and database.
466
+
467
+ Args:
468
+ catalog (str): The catalog name.
469
+ database (str): The database name.
470
+ table (str): The table name.
471
+
472
+ Returns:
473
+ list: A list of dictionaries containing column information.
474
+ """
398
475
  get_columns_request = e6x_engine_pb2.GetColumnsV2Request(
399
476
  sessionId=self.get_session_id,
400
477
  schema=database,
@@ -408,6 +485,15 @@ class Connection(object):
408
485
  return [{'fieldName': row.fieldName, 'fieldType': row.fieldType} for row in get_columns_response.fieldInfo]
409
486
 
410
487
  def get_schema_names(self, catalog):
488
+ """
489
+ Retrieves the list of schema names from the specified catalog.
490
+
491
+ Args:
492
+ catalog (str): The catalog name.
493
+
494
+ Returns:
495
+ list: A list of schema names.
496
+ """
411
497
  get_schema_request = e6x_engine_pb2.GetSchemaNamesV2Request(
412
498
  sessionId=self.get_session_id,
413
499
  catalog=catalog
@@ -419,29 +505,65 @@ class Connection(object):
419
505
  return list(get_schema_response.schemas)
420
506
 
421
507
  def commit(self):
422
- """We do not support transactions, so this does nothing."""
508
+ """
509
+ Commits the current transaction.
510
+
511
+ Note:
512
+ This method does nothing as transactions are not supported.
513
+ """
423
514
  pass
424
515
 
425
516
  def cursor(self, catalog_name=None, db_name=None):
426
- """Return a new :py:class:`Cursor` object using the connection."""
517
+ """
518
+ Creates a new cursor object for executing queries.
519
+
520
+ Args:
521
+ catalog_name (str, optional): The catalog name. Defaults to None.
522
+ db_name (str, optional): The database name. Defaults to None.
523
+
524
+ Returns:
525
+ Cursor: A new cursor object.
526
+ """
427
527
  return Cursor(self, database=db_name, catalog_name=catalog_name)
428
528
 
429
529
  def rollback(self):
430
- raise Exception("e6xdb does not support transactions") # pragma: no cover
530
+ """
531
+ Rolls back the current transaction.
532
+
533
+ Raises:
534
+ Exception: Always raises an exception as transactions are not supported.
535
+ """
536
+ raise Exception("e6data does not support transactions") # pragma: no cover
431
537
 
432
538
  @property
433
539
  def client(self):
540
+ """
541
+ Returns the gRPC client stub for interacting with the server.
542
+
543
+ Returns:
544
+ e6x_engine_pb2_grpc.QueryEngineServiceStub: The gRPC client stub.
545
+ """
434
546
  return self._client
435
547
 
436
548
 
437
549
  class Cursor(DBAPICursor):
438
- """These objects represent a database cursor, which is used to manage the context of a fetch
550
+ """
551
+ These objects represent a database cursor, which is used to manage the context of a fetch
439
552
  operation.
440
553
  Cursors are not isolated, i.e., any changes done to the database by a cursor are immediately
441
554
  visible by other cursors or connections.
442
555
  """
443
556
 
444
557
  def __init__(self, connection: Connection, array_size=1000, database=None, catalog_name=None):
558
+ """
559
+ Initialize a new Cursor object.
560
+
561
+ Args:
562
+ connection (Connection): The connection object to the database.
563
+ array_size (int, optional): The number of rows to fetch at a time. Defaults to 1000.
564
+ database (str, optional): The database name. Defaults to None.
565
+ catalog_name (str, optional): The catalog name. Defaults to None.
566
+ """
445
567
  super(Cursor, self).__init__()
446
568
  self._array_size = array_size
447
569
  self.connection = connection
@@ -462,15 +584,32 @@ class Cursor(DBAPICursor):
462
584
 
463
585
  @property
464
586
  def metadata(self):
587
+ """
588
+ Get the gRPC metadata for the current query.
589
+
590
+ Returns:
591
+ list: A list of tuples containing gRPC metadata.
592
+ """
465
593
  return _get_grpc_header(engine_ip=self._engine_ip, cluster=self.connection.cluster_uuid)
466
594
 
467
595
  @property
468
596
  def arraysize(self):
597
+ """
598
+ Get the array size for fetching rows.
599
+
600
+ Returns:
601
+ int: The number of rows to fetch at a time.
602
+ """
469
603
  return self._arraysize
470
604
 
471
605
  @arraysize.setter
472
606
  def arraysize(self, value):
473
- """Array size cannot be None, and should be an integer"""
607
+ """
608
+ Set the array size for fetching rows.
609
+
610
+ Args:
611
+ value (int): The number of rows to fetch at a time.
612
+ """
474
613
  default_arraysize = 1000
475
614
  try:
476
615
  self._arraysize = int(value) or default_arraysize
@@ -506,14 +645,29 @@ class Cursor(DBAPICursor):
506
645
  return self._description
507
646
 
508
647
  def __enter__(self):
648
+ """
649
+ Enter the runtime context related to this object.
650
+
651
+ Returns:
652
+ Cursor: The current instance of the cursor.
653
+ """
509
654
  return self
510
655
 
511
656
  def __exit__(self, exc_type, exc_val, exc_tb):
657
+ """
658
+ Exit the runtime context related to this object.
659
+
660
+ Args:
661
+ exc_type (Type[BaseException]): The type of exception raised (if any).
662
+ exc_val (BaseException): The exception instance raised (if any).
663
+ exc_tb (Traceback): The traceback object of the exception (if any).
664
+ """
512
665
  self.close()
513
666
 
514
667
  def close(self):
515
- """Close the operation handle"""
516
- # self.connection.close()
668
+ """
669
+ Close the operation handle and reset the cursor state.
670
+ """
517
671
  try:
518
672
  self.clear()
519
673
  except:
@@ -530,17 +684,44 @@ class Cursor(DBAPICursor):
530
684
  self._database = None
531
685
 
532
686
  def get_tables(self):
687
+ """
688
+ Retrieve the list of tables from the current database.
689
+
690
+ Returns:
691
+ list: A list of table names.
692
+ """
533
693
  schema = self.connection.database
534
694
  return self.connection.get_tables(catalog=self._catalog_name, database=schema)
535
695
 
536
696
  def get_columns(self, table):
697
+ """
698
+ Retrieve the list of columns for the specified table.
699
+
700
+ Args:
701
+ table (str): The table name.
702
+
703
+ Returns:
704
+ list: A list of dictionaries containing column information.
705
+ """
537
706
  schema = self.connection.database
538
707
  return self.connection.get_columns(catalog=self._catalog_name, database=schema, table=table)
539
708
 
540
709
  def get_schema_names(self):
710
+ """
711
+ Retrieve the list of schema names from the current catalog.
712
+
713
+ Returns:
714
+ list: A list of schema names.
715
+ """
541
716
  return self.connection.get_schema_names(catalog=self._catalog_name)
542
717
 
543
718
  def clear(self, query_id=None):
719
+ """
720
+ Clear the query results from the server.
721
+
722
+ Args:
723
+ query_id (str, optional): The ID of the query to be cleared. Defaults to None.
724
+ """
544
725
  if not query_id:
545
726
  query_id = self._query_id
546
727
  clear_request = e6x_engine_pb2.ClearOrCancelQueryRequest(
@@ -551,9 +732,24 @@ class Cursor(DBAPICursor):
551
732
  return self.connection.client.clearOrCancelQuery(clear_request, metadata=self.metadata)
552
733
 
553
734
  def cancel(self, query_id):
735
+ """
736
+ Cancel the execution of a query on the server.
737
+
738
+ Args:
739
+ query_id (str): The ID of the query to be canceled.
740
+ """
554
741
  self.connection.query_cancel(engine_ip=self._engine_ip, query_id=query_id)
555
742
 
556
743
  def status(self, query_id):
744
+ """
745
+ Get the status of the specified query.
746
+
747
+ Args:
748
+ query_id (str): The ID of the query.
749
+
750
+ Returns:
751
+ StatusResponse: The status response of the query.
752
+ """
557
753
  status_request = e6x_engine_pb2.StatusRequest(
558
754
  sessionId=self.connection.get_session_id,
559
755
  queryId=query_id,
@@ -563,12 +759,17 @@ class Cursor(DBAPICursor):
563
759
 
564
760
  @re_auth
565
761
  def execute(self, operation, parameters=None, **kwargs):
566
- """Prepare and execute a database operation (query or command).
567
- Return values are not defined.
568
762
  """
763
+ Prepare and execute a database operation (query or command).
764
+
765
+ Args:
766
+ operation (str): The SQL query or command to execute.
767
+ parameters (dict, optional): The parameters to bind to the query. Defaults to None.
768
+
769
+ Returns:
770
+ str: The query ID of the executed query.
569
771
  """
570
- Semicolon is now not supported. So removing it from query end.
571
- """
772
+ # Semicolon is now not supported. So removing it from query end.
572
773
  operation = operation.strip() # Remove leading and trailing whitespaces.
573
774
  if operation.endswith(';'):
574
775
  operation = operation[:-1]
@@ -632,10 +833,19 @@ class Cursor(DBAPICursor):
632
833
 
633
834
  @property
634
835
  def rowcount(self):
836
+ """
837
+ Get the number of rows affected by the last execute operation.
838
+
839
+ Returns:
840
+ int: The number of rows affected.
841
+ """
635
842
  self.update_mete_data()
636
843
  return self._rowcount
637
844
 
638
845
  def update_mete_data(self):
846
+ """
847
+ Update the metadata for the current query.
848
+ """
639
849
  result_meta_data_request = e6x_engine_pb2.GetResultMetadataRequest(
640
850
  engineIP=self._engine_ip,
641
851
  sessionId=self.connection.get_session_id,
@@ -650,6 +860,12 @@ class Cursor(DBAPICursor):
650
860
  self._is_metadata_updated = True
651
861
 
652
862
  def _fetch_more(self):
863
+ """
864
+ Fetch more rows from the server.
865
+
866
+ Returns:
867
+ list: A list of rows fetched from the server.
868
+ """
653
869
  batch_size = self._arraysize
654
870
  self._data = list()
655
871
  for i in range(batch_size):
@@ -660,6 +876,12 @@ class Cursor(DBAPICursor):
660
876
  return self._data
661
877
 
662
878
  def _fetch_all(self):
879
+ """
880
+ Fetch all rows from the server.
881
+
882
+ Returns:
883
+ list: A list of all rows fetched from the server.
884
+ """
663
885
  self._data = list()
664
886
  while True:
665
887
  rows = self.fetch_batch()
@@ -671,6 +893,15 @@ class Cursor(DBAPICursor):
671
893
  return rows
672
894
 
673
895
  def fetchall_buffer(self, query_id=None):
896
+ """
897
+ Fetch all rows from the server in a buffered manner.
898
+
899
+ Args:
900
+ query_id (str, optional): The ID of the query. Defaults to None.
901
+
902
+ Yields:
903
+ list: A list of rows fetched from the server.
904
+ """
674
905
  if query_id:
675
906
  self._query_id = query_id
676
907
  while True:
@@ -680,6 +911,12 @@ class Cursor(DBAPICursor):
680
911
  yield rows
681
912
 
682
913
  def fetch_batch(self):
914
+ """
915
+ Fetch a batch of rows from the server.
916
+
917
+ Returns:
918
+ list: A list of rows fetched from the server.
919
+ """
683
920
  client = self.connection.client
684
921
  get_next_result_batch_request = e6x_engine_pb2.GetNextResultBatchRequest(
685
922
  engineIP=self._engine_ip,
@@ -699,9 +936,24 @@ class Cursor(DBAPICursor):
699
936
  return read_rows_from_chunk(self._query_columns_description, buffer)
700
937
 
701
938
  def fetchall(self):
939
+ """
940
+ Fetch all rows from the server.
941
+
942
+ Returns:
943
+ list: A list of all rows fetched from the server.
944
+ """
702
945
  return self._fetch_all()
703
946
 
704
947
  def fetchmany(self, size: int = None):
948
+ """
949
+ Fetch a specified number of rows from the server.
950
+
951
+ Args:
952
+ size (int, optional): The number of rows to fetch. Defaults to None.
953
+
954
+ Returns:
955
+ list: A list of rows fetched from the server.
956
+ """
705
957
  if size is None:
706
958
  size = self.arraysize
707
959
  if self._data is None:
@@ -720,13 +972,24 @@ class Cursor(DBAPICursor):
720
972
  return rows
721
973
 
722
974
  def fetchone(self):
723
- # _logger.info("fetch One returning the batch itself which is limited by predefined no.of rows")
975
+ """
976
+ Fetch a single row from the server.
977
+
978
+ Returns:
979
+ list: A single row fetched from the server.
980
+ """
724
981
  rows = self.fetchmany(1)
725
982
  if rows is None or len(rows) == 0:
726
983
  return None
727
984
  return rows
728
985
 
729
986
  def explain(self):
987
+ """
988
+ Get the execution plan for the current query.
989
+
990
+ Returns:
991
+ str: The execution plan of the query.
992
+ """
730
993
  explain_request = e6x_engine_pb2.ExplainRequest(
731
994
  engineIP=self._engine_ip,
732
995
  sessionId=self.connection.get_session_id,
@@ -739,6 +1002,12 @@ class Cursor(DBAPICursor):
739
1002
  return explain_response.explain
740
1003
 
741
1004
  def explain_analyse(self):
1005
+ """
1006
+ Get the execution plan for the current query.
1007
+
1008
+ Returns:
1009
+ dict: The execution plan of the query.
1010
+ """
742
1011
  explain_analyze_request = e6x_engine_pb2.ExplainAnalyzeRequest(
743
1012
  engineIP=self._engine_ip,
744
1013
  sessionId=self.connection.get_session_id,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: e6data-python-connector
3
- Version: 2.2.3rc4
3
+ Version: 2.2.4
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: e6data, Inc.
@@ -38,7 +38,7 @@ Dynamic: summary
38
38
 
39
39
  # e6data Python Connector
40
40
 
41
- ![version](https://img.shields.io/badge/version-2.2.3rc4-blue.svg)
41
+ ![version](https://img.shields.io/badge/version-2.2.4-blue.svg)
42
42
 
43
43
  ## Introduction
44
44
 
@@ -12,7 +12,7 @@
12
12
 
13
13
  import setuptools
14
14
 
15
- VERSION = (2, 2, 3, 'rc4')
15
+ VERSION = (2, 2, 4)
16
16
 
17
17
 
18
18
  def get_long_desc():