e6data-python-connector 2.3.12rc11__tar.gz → 2.3.12rc31__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 (87) hide show
  1. {e6data_python_connector-2.3.12rc11/e6data_python_connector.egg-info → e6data_python_connector-2.3.12rc31}/PKG-INFO +49 -2
  2. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/README.md +48 -1
  3. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/datainputstream.py +24 -7
  4. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/e6data_grpc.py +33 -52
  5. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31/e6data_python_connector.egg-info}/PKG-INFO +49 -2
  6. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/setup.py +1 -1
  7. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/LICENSE +0 -0
  8. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/MANIFEST.in +0 -0
  9. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/__init__.py +0 -0
  10. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/cluster_manager.py +0 -0
  11. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/cluster_server/__init__.py +0 -0
  12. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/cluster_server/cluster_pb2.py +0 -0
  13. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/cluster_server/cluster_pb2_grpc.py +0 -0
  14. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/common.py +0 -0
  15. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/connection_pool.py +0 -0
  16. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/constants.py +0 -0
  17. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/date_time_utils.py +0 -0
  18. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/dialect.py +0 -0
  19. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/e6x_vector/__init__.py +0 -0
  20. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/e6x_vector/constants.py +0 -0
  21. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/e6x_vector/ttypes.py +0 -0
  22. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/exceptions.py +0 -0
  23. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/server/QueryEngineService.py +0 -0
  24. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/server/__init__.py +0 -0
  25. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/server/constants.py +0 -0
  26. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/server/e6x_engine_pb2.py +0 -0
  27. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/server/e6x_engine_pb2.pyi +0 -0
  28. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/server/e6x_engine_pb2_grpc.py +0 -0
  29. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/server/ttypes.py +0 -0
  30. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/strategy.py +0 -0
  31. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/typeId.py +0 -0
  32. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector.egg-info/SOURCES.txt +0 -0
  33. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector.egg-info/dependency_links.txt +0 -0
  34. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector.egg-info/entry_points.txt +0 -0
  35. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector.egg-info/requires.txt +0 -0
  36. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector.egg-info/top_level.txt +0 -0
  37. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/gen-py/__init__.py +0 -0
  38. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/gen-py/e6x_vector/__init__.py +0 -0
  39. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/gen-py/e6x_vector/constants.py +0 -0
  40. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/gen-py/e6x_vector/ttypes.py +0 -0
  41. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/pyproject.toml +0 -0
  42. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/setup.cfg +0 -0
  43. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/__init__.py +0 -0
  44. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/analyze_38_nines.py +0 -0
  45. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/analyze_all_cases.py +0 -0
  46. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/analyze_binary.py +0 -0
  47. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/analyze_correct_value.py +0 -0
  48. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/analyze_fields.py +0 -0
  49. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/check_decimal_errors.py +0 -0
  50. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/cleanup_test_files.py +0 -0
  51. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/debug_38_nines.py +0 -0
  52. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/debug_binary.py +0 -0
  53. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/final_test.py +0 -0
  54. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/move_tests.py +0 -0
  55. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/quick_test.py +0 -0
  56. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_38_nines.py +0 -0
  57. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_all_decimal128_cases.py +0 -0
  58. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_cluster_manager_efficiency.py +0 -0
  59. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_cluster_manager_none_strategy.py +0 -0
  60. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_cluster_manager_strategy.py +0 -0
  61. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_comprehensive.py +0 -0
  62. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_connection_pool.py +0 -0
  63. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_connection_pool_e2e.py +0 -0
  64. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_current_implementation.py +0 -0
  65. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_decimal128_binary_parsing.py +0 -0
  66. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_decimal128_parsing.py +0 -0
  67. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_fix.py +0 -0
  68. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_improved_parsing.py +0 -0
  69. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_known_case.py +0 -0
  70. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_manual_analysis.py +0 -0
  71. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_mock_server.py +0 -0
  72. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_multiprocessing_fix.py +0 -0
  73. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_new_implementation.py +0 -0
  74. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_pool_concurrency_simple.py +0 -0
  75. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_pool_threading_multiprocessing.py +0 -0
  76. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_simple_connection_pool.py +0 -0
  77. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_specific_binary.py +0 -0
  78. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_strategy.py +0 -0
  79. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_strategy_logic.py +0 -0
  80. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_strategy_persistence_fix.py +0 -0
  81. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_strategy_sharing_fix.py +0 -0
  82. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_user_binary_value.py +0 -0
  83. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/tests.py +0 -0
  84. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/tests_grpc.py +0 -0
  85. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/validate_decimal128.py +0 -0
  86. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/validate_implementation.py +0 -0
  87. {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/verify_decimal_fix.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: e6data-python-connector
3
- Version: 2.3.12rc11
3
+ Version: 2.3.12rc31
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.
@@ -39,7 +39,7 @@ Dynamic: summary
39
39
 
40
40
  # e6data Python Connector
41
41
 
42
- ![version](https://img.shields.io/badge/version-2.3.12rc11-blue.svg)
42
+ ![version](https://img.shields.io/badge/version-2.3.12rc31-blue.svg)
43
43
 
44
44
  ## Introduction
45
45
 
@@ -125,6 +125,7 @@ The `Connection` class supports the following parameters:
125
125
  | `auto_resume` | bool | No | True | Automatically resume cluster if suspended |
126
126
  | `grpc_options` | dict | No | None | Additional gRPC configuration options |
127
127
  | `debug` | bool | No | False | Enable debug logging for troubleshooting |
128
+ | `require_fastbinary` | bool | No | True | Require fastbinary module for Thrift deserialization. Set to False to use pure Python implementation if system dependencies cannot be installed |
128
129
 
129
130
  #### Secure Connection Example
130
131
 
@@ -158,6 +159,51 @@ conn = Connection(
158
159
  )
159
160
  ```
160
161
 
162
+ #### Handling Missing System Dependencies
163
+
164
+ The e6data connector uses the `fastbinary` module (from Apache Thrift) for optimal performance when deserializing data. This module requires system-level dependencies (`python3-devel` and `gcc-c++`) to be installed.
165
+
166
+ **Default Behavior (Recommended):**
167
+ By default, the connector requires `fastbinary` to be available. If it's not found, the connection will fail immediately with a clear error message:
168
+
169
+ ```python
170
+ conn = Connection(
171
+ host=host,
172
+ port=port,
173
+ username=username,
174
+ password=password,
175
+ database=database
176
+ )
177
+ # Raises exception if fastbinary is not available
178
+ ```
179
+
180
+ **Fallback to Pure Python:**
181
+ If you cannot install system dependencies (e.g., in restricted environments, serverless platforms, or containers without build tools), you can disable the `fastbinary` requirement. The connector will fall back to a pure Python implementation with a performance penalty:
182
+
183
+ ```python
184
+ conn = Connection(
185
+ host=host,
186
+ port=port,
187
+ username=username,
188
+ password=password,
189
+ database=database,
190
+ require_fastbinary=False # Allow operation without fastbinary
191
+ )
192
+ # Logs warning but continues with pure Python implementation
193
+ ```
194
+
195
+ **When to use `require_fastbinary=False`:**
196
+ - Running in AWS Lambda or other serverless environments
197
+ - Docker containers built without compilation tools
198
+ - Restricted environments where system packages cannot be installed
199
+ - Development/testing environments where performance is not critical
200
+
201
+ **Performance Impact:**
202
+ - With `fastbinary`: Optimal performance for data deserialization
203
+ - Without `fastbinary` (pure Python): ~2-3x slower deserialization, but otherwise fully functional
204
+
205
+ **Note:** It's strongly recommended to install system dependencies when possible for best performance. The `require_fastbinary=False` option should only be used when system dependencies cannot be installed.
206
+
161
207
  ### Perform a Queries & Get Results
162
208
 
163
209
  ```python
@@ -691,5 +737,6 @@ python your_script.py
691
737
  | 456 Strategy Error | Automatic blue-green failover will handle this |
692
738
  | Memory issues with large results | Use `fetchall_buffer()` instead of `fetchall()` |
693
739
  | gRPC message size errors | Configure `grpc_options` with appropriate message size limits |
740
+ | fastbinary import error | Install system dependencies (`python3-devel`, `gcc-c++`) or set `require_fastbinary=False` |
694
741
 
695
742
  See [TECH_DOC.md](TECH_DOC.md) for detailed technical documentation.
@@ -1,6 +1,6 @@
1
1
  # e6data Python Connector
2
2
 
3
- ![version](https://img.shields.io/badge/version-2.3.12rc11-blue.svg)
3
+ ![version](https://img.shields.io/badge/version-2.3.12rc31-blue.svg)
4
4
 
5
5
  ## Introduction
6
6
 
@@ -86,6 +86,7 @@ The `Connection` class supports the following parameters:
86
86
  | `auto_resume` | bool | No | True | Automatically resume cluster if suspended |
87
87
  | `grpc_options` | dict | No | None | Additional gRPC configuration options |
88
88
  | `debug` | bool | No | False | Enable debug logging for troubleshooting |
89
+ | `require_fastbinary` | bool | No | True | Require fastbinary module for Thrift deserialization. Set to False to use pure Python implementation if system dependencies cannot be installed |
89
90
 
90
91
  #### Secure Connection Example
91
92
 
@@ -119,6 +120,51 @@ conn = Connection(
119
120
  )
120
121
  ```
121
122
 
123
+ #### Handling Missing System Dependencies
124
+
125
+ The e6data connector uses the `fastbinary` module (from Apache Thrift) for optimal performance when deserializing data. This module requires system-level dependencies (`python3-devel` and `gcc-c++`) to be installed.
126
+
127
+ **Default Behavior (Recommended):**
128
+ By default, the connector requires `fastbinary` to be available. If it's not found, the connection will fail immediately with a clear error message:
129
+
130
+ ```python
131
+ conn = Connection(
132
+ host=host,
133
+ port=port,
134
+ username=username,
135
+ password=password,
136
+ database=database
137
+ )
138
+ # Raises exception if fastbinary is not available
139
+ ```
140
+
141
+ **Fallback to Pure Python:**
142
+ If you cannot install system dependencies (e.g., in restricted environments, serverless platforms, or containers without build tools), you can disable the `fastbinary` requirement. The connector will fall back to a pure Python implementation with a performance penalty:
143
+
144
+ ```python
145
+ conn = Connection(
146
+ host=host,
147
+ port=port,
148
+ username=username,
149
+ password=password,
150
+ database=database,
151
+ require_fastbinary=False # Allow operation without fastbinary
152
+ )
153
+ # Logs warning but continues with pure Python implementation
154
+ ```
155
+
156
+ **When to use `require_fastbinary=False`:**
157
+ - Running in AWS Lambda or other serverless environments
158
+ - Docker containers built without compilation tools
159
+ - Restricted environments where system packages cannot be installed
160
+ - Development/testing environments where performance is not critical
161
+
162
+ **Performance Impact:**
163
+ - With `fastbinary`: Optimal performance for data deserialization
164
+ - Without `fastbinary` (pure Python): ~2-3x slower deserialization, but otherwise fully functional
165
+
166
+ **Note:** It's strongly recommended to install system dependencies when possible for best performance. The `require_fastbinary=False` option should only be used when system dependencies cannot be installed.
167
+
122
168
  ### Perform a Queries & Get Results
123
169
 
124
170
  ```python
@@ -652,5 +698,6 @@ python your_script.py
652
698
  | 456 Strategy Error | Automatic blue-green failover will handle this |
653
699
  | Memory issues with large results | Use `fetchall_buffer()` instead of `fetchall()` |
654
700
  | gRPC message size errors | Configure `grpc_options` with appropriate message size limits |
701
+ | fastbinary import error | Install system dependencies (`python3-devel`, `gcc-c++`) or set `require_fastbinary=False` |
655
702
 
656
703
  See [TECH_DOC.md](TECH_DOC.md) for detailed technical documentation.
@@ -12,20 +12,27 @@ from e6data_python_connector.e6x_vector.ttypes import Chunk, Vector, VectorType
12
12
  from e6data_python_connector.constants import ZONE
13
13
  from e6data_python_connector.date_time_utils import floor_div, floor_mod, timezone_from_offset
14
14
 
15
+ # Try to import fastbinary - it's optional but provides better performance
16
+ _fastbinary_available = False
15
17
  try:
16
18
  from thrift.protocol import fastbinary
19
+ _fastbinary_available = True
17
20
  except ImportError:
18
- raise Exception(
19
- """
20
- Failed to import fastbinary.
21
- Did you install system dependencies?
22
- Please verify https://github.com/e6x-labs/e6data-python-connector#dependencies
23
- """
24
- )
21
+ pass # Will check require_fastbinary flag at connection creation time
25
22
 
26
23
  _logger = logging.getLogger(__name__)
27
24
 
28
25
 
26
+ def is_fastbinary_available():
27
+ """
28
+ Check if fastbinary module is available.
29
+
30
+ Returns:
31
+ bool: True if fastbinary is available, False otherwise
32
+ """
33
+ return _fastbinary_available
34
+
35
+
29
36
  def _binary_to_decimal128(binary_data, scale=None):
30
37
  """
31
38
  Convert binary data to Decimal128.
@@ -504,6 +511,16 @@ def read_values_from_array(query_columns_description: list, dis: DataInputStream
504
511
 
505
512
 
506
513
  def read_rows_from_chunk(query_columns_description: list, buffer):
514
+ """
515
+ Read rows from a Thrift-encoded chunk buffer.
516
+
517
+ Args:
518
+ query_columns_description: List of column descriptions
519
+ buffer: Thrift-encoded binary buffer
520
+
521
+ Returns:
522
+ List of rows
523
+ """
507
524
  # Create a transport and protocol instance for deserialization
508
525
  transport = TTransport.TMemoryBuffer(buffer)
509
526
  protocol = TBinaryProtocol.TBinaryProtocolAccelerated(transport)
@@ -26,7 +26,7 @@ from e6data_python_connector.cluster_manager import ClusterManager
26
26
  from e6data_python_connector.strategy import _get_grpc_header as _get_strategy_header
27
27
  from e6data_python_connector.common import DBAPITypeObject, ParamEscaper, DBAPICursor
28
28
  from e6data_python_connector.constants import *
29
- from e6data_python_connector.datainputstream import get_query_columns_info, read_rows_from_chunk
29
+ from e6data_python_connector.datainputstream import get_query_columns_info, read_rows_from_chunk, is_fastbinary_available
30
30
  from e6data_python_connector.server import e6x_engine_pb2_grpc, e6x_engine_pb2
31
31
  from e6data_python_connector.typeId import *
32
32
 
@@ -335,6 +335,7 @@ class Connection(object):
335
335
  scheme: str = 'e6data',
336
336
  grpc_options: dict = None,
337
337
  debug: bool = False,
338
+ require_fastbinary: bool = True,
338
339
  ):
339
340
  """
340
341
  Parameters
@@ -368,6 +369,10 @@ class Connection(object):
368
369
  - keepalive_time_ms: This parameter defines the time, in milliseconds, Default to 30 seconds
369
370
  debug: bool, Optional
370
371
  Flag to enable debug logging for blue-green deployment strategy changes
372
+ require_fastbinary: bool, Optional
373
+ Flag to require fastbinary module for Thrift deserialization. If True (default),
374
+ raises an exception if fastbinary is not available. If False, logs a warning
375
+ and continues with pure Python implementation (with reduced performance).
371
376
  """
372
377
  if not username or not password:
373
378
  raise ValueError("username or password cannot be empty.")
@@ -387,6 +392,29 @@ class Connection(object):
387
392
 
388
393
  self._auto_resume = auto_resume
389
394
 
395
+ # Store require_fastbinary flag
396
+ self._require_fastbinary = require_fastbinary
397
+
398
+ # Check fastbinary availability at connection creation time
399
+ if not is_fastbinary_available():
400
+ if require_fastbinary:
401
+ raise Exception(
402
+ """
403
+ Failed to import fastbinary.
404
+ Did you install system dependencies?
405
+ Please verify https://github.com/e6x-labs/e6data-python-connector#dependencies
406
+
407
+ To continue without fastbinary (with reduced performance), set require_fastbinary=False
408
+ in the connection parameters.
409
+ """
410
+ )
411
+ else:
412
+ logger.warning(
413
+ "fastbinary module is not available. Using pure Python implementation. "
414
+ "Performance may be degraded. To enable fastbinary, install system dependencies: "
415
+ "https://github.com/e6x-labs/e6data-python-connector#dependencies"
416
+ )
417
+
390
418
  self._grpc_options = grpc_options
391
419
  if self._grpc_options is None:
392
420
  self._grpc_options = dict()
@@ -853,56 +881,6 @@ class Connection(object):
853
881
  )
854
882
  return dry_run_response.dryrunValue
855
883
 
856
- def get_logical_plan(self, query, catalog=None, schema=None):
857
- """
858
- Gets the logical execution plan for a query without executing it.
859
- This method performs syntax, parsing, and plan compilation, then returns the logical plan.
860
-
861
- Args:
862
- query (str): The SQL query to get the plan for.
863
- catalog (str, optional): Catalog name. Uses connection's catalog if not provided.
864
- schema (str, optional): Schema/database name. Uses connection's database if not provided.
865
-
866
- Returns:
867
- dict: A dictionary with:
868
- - 'success' (bool): True if plan generation succeeded, False otherwise
869
- - 'plan' (str, optional): The logical plan string if successful
870
- - 'error' (str, optional): Error message if plan generation failed
871
-
872
- Example:
873
- >>> result = conn.get_logical_plan("SELECT * FROM table")
874
- >>> if result['success']:
875
- ... print(f"Plan: {result['plan']}")
876
- >>> else:
877
- ... print(f"Error: {result['error']}")
878
- """
879
- catalog_to_use = catalog if catalog is not None else self.catalog_name
880
- schema_to_use = schema if schema is not None else self.database
881
-
882
- try:
883
- dry_run_request = e6x_engine_pb2.DryRunRequestV2(
884
- sessionId=self.get_session_id,
885
- schema=schema_to_use,
886
- catalog=catalog_to_use,
887
- queryString=query
888
- )
889
-
890
- dry_run_response = self._client.dryRunV2(
891
- dry_run_request,
892
- metadata=_get_grpc_header(cluster=self.cluster_name, strategy=_get_active_strategy())
893
- )
894
-
895
- return {
896
- 'success': True,
897
- 'plan': dry_run_response.dryrunValue
898
- }
899
-
900
- except Exception as e:
901
- return {
902
- 'success': False,
903
- 'error': str(e)
904
- }
905
-
906
884
  def get_tables(self, catalog, database):
907
885
  """
908
886
  Retrieves the list of tables from the specified catalog and database.
@@ -1514,7 +1492,10 @@ class Cursor(DBAPICursor):
1514
1492
  if not buffer or len(buffer) == 0:
1515
1493
  return None
1516
1494
  # one batch retrieves the predefined set of rows
1517
- return read_rows_from_chunk(self._query_columns_description, buffer)
1495
+ return read_rows_from_chunk(
1496
+ self._query_columns_description,
1497
+ buffer
1498
+ )
1518
1499
 
1519
1500
  def fetchall(self):
1520
1501
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: e6data-python-connector
3
- Version: 2.3.12rc11
3
+ Version: 2.3.12rc31
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.
@@ -39,7 +39,7 @@ Dynamic: summary
39
39
 
40
40
  # e6data Python Connector
41
41
 
42
- ![version](https://img.shields.io/badge/version-2.3.12rc11-blue.svg)
42
+ ![version](https://img.shields.io/badge/version-2.3.12rc31-blue.svg)
43
43
 
44
44
  ## Introduction
45
45
 
@@ -125,6 +125,7 @@ The `Connection` class supports the following parameters:
125
125
  | `auto_resume` | bool | No | True | Automatically resume cluster if suspended |
126
126
  | `grpc_options` | dict | No | None | Additional gRPC configuration options |
127
127
  | `debug` | bool | No | False | Enable debug logging for troubleshooting |
128
+ | `require_fastbinary` | bool | No | True | Require fastbinary module for Thrift deserialization. Set to False to use pure Python implementation if system dependencies cannot be installed |
128
129
 
129
130
  #### Secure Connection Example
130
131
 
@@ -158,6 +159,51 @@ conn = Connection(
158
159
  )
159
160
  ```
160
161
 
162
+ #### Handling Missing System Dependencies
163
+
164
+ The e6data connector uses the `fastbinary` module (from Apache Thrift) for optimal performance when deserializing data. This module requires system-level dependencies (`python3-devel` and `gcc-c++`) to be installed.
165
+
166
+ **Default Behavior (Recommended):**
167
+ By default, the connector requires `fastbinary` to be available. If it's not found, the connection will fail immediately with a clear error message:
168
+
169
+ ```python
170
+ conn = Connection(
171
+ host=host,
172
+ port=port,
173
+ username=username,
174
+ password=password,
175
+ database=database
176
+ )
177
+ # Raises exception if fastbinary is not available
178
+ ```
179
+
180
+ **Fallback to Pure Python:**
181
+ If you cannot install system dependencies (e.g., in restricted environments, serverless platforms, or containers without build tools), you can disable the `fastbinary` requirement. The connector will fall back to a pure Python implementation with a performance penalty:
182
+
183
+ ```python
184
+ conn = Connection(
185
+ host=host,
186
+ port=port,
187
+ username=username,
188
+ password=password,
189
+ database=database,
190
+ require_fastbinary=False # Allow operation without fastbinary
191
+ )
192
+ # Logs warning but continues with pure Python implementation
193
+ ```
194
+
195
+ **When to use `require_fastbinary=False`:**
196
+ - Running in AWS Lambda or other serverless environments
197
+ - Docker containers built without compilation tools
198
+ - Restricted environments where system packages cannot be installed
199
+ - Development/testing environments where performance is not critical
200
+
201
+ **Performance Impact:**
202
+ - With `fastbinary`: Optimal performance for data deserialization
203
+ - Without `fastbinary` (pure Python): ~2-3x slower deserialization, but otherwise fully functional
204
+
205
+ **Note:** It's strongly recommended to install system dependencies when possible for best performance. The `require_fastbinary=False` option should only be used when system dependencies cannot be installed.
206
+
161
207
  ### Perform a Queries & Get Results
162
208
 
163
209
  ```python
@@ -691,5 +737,6 @@ python your_script.py
691
737
  | 456 Strategy Error | Automatic blue-green failover will handle this |
692
738
  | Memory issues with large results | Use `fetchall_buffer()` instead of `fetchall()` |
693
739
  | gRPC message size errors | Configure `grpc_options` with appropriate message size limits |
740
+ | fastbinary import error | Install system dependencies (`python3-devel`, `gcc-c++`) or set `require_fastbinary=False` |
694
741
 
695
742
  See [TECH_DOC.md](TECH_DOC.md) for detailed technical documentation.
@@ -12,7 +12,7 @@
12
12
 
13
13
  import setuptools
14
14
 
15
- VERSION = (2, 3, 12,'rc11')
15
+ VERSION = (2, 3, 12, 'rc31',)
16
16
 
17
17
 
18
18
  def get_long_desc():