PyAthena 3.30.0__tar.gz → 3.31.0__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 (89) hide show
  1. {pyathena-3.30.0 → pyathena-3.31.0}/PKG-INFO +8 -8
  2. {pyathena-3.30.0 → pyathena-3.31.0}/README.md +5 -5
  3. pyathena-3.31.0/pyathena/_version.py +24 -0
  4. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/arrow/converter.py +2 -1
  5. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/converter.py +25 -3
  6. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/model.py +50 -0
  7. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/pandas/converter.py +4 -2
  8. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/pandas/result_set.py +19 -57
  9. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/parser.py +0 -23
  10. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/polars/converter.py +2 -1
  11. {pyathena-3.30.0 → pyathena-3.31.0}/pyproject.toml +5 -5
  12. pyathena-3.30.0/pyathena/_version.py +0 -34
  13. {pyathena-3.30.0 → pyathena-3.31.0}/.gitignore +0 -0
  14. {pyathena-3.30.0 → pyathena-3.31.0}/LICENSE +0 -0
  15. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/__init__.py +0 -0
  16. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/aio/__init__.py +0 -0
  17. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/aio/arrow/__init__.py +0 -0
  18. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/aio/arrow/cursor.py +0 -0
  19. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/aio/common.py +0 -0
  20. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/aio/connection.py +0 -0
  21. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/aio/cursor.py +0 -0
  22. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/aio/pandas/__init__.py +0 -0
  23. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/aio/pandas/cursor.py +0 -0
  24. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/aio/polars/__init__.py +0 -0
  25. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/aio/polars/cursor.py +0 -0
  26. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/aio/result_set.py +0 -0
  27. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/aio/s3fs/__init__.py +0 -0
  28. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/aio/s3fs/cursor.py +0 -0
  29. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/aio/spark/__init__.py +0 -0
  30. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/aio/spark/cursor.py +0 -0
  31. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/aio/sqlalchemy/__init__.py +0 -0
  32. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/aio/sqlalchemy/arrow.py +0 -0
  33. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/aio/sqlalchemy/base.py +0 -0
  34. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/aio/sqlalchemy/pandas.py +0 -0
  35. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/aio/sqlalchemy/polars.py +0 -0
  36. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/aio/sqlalchemy/rest.py +0 -0
  37. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/aio/sqlalchemy/s3fs.py +0 -0
  38. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/aio/util.py +0 -0
  39. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/arrow/__init__.py +0 -0
  40. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/arrow/async_cursor.py +0 -0
  41. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/arrow/cursor.py +0 -0
  42. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/arrow/result_set.py +0 -0
  43. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/arrow/util.py +0 -0
  44. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/async_cursor.py +0 -0
  45. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/common.py +0 -0
  46. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/connection.py +0 -0
  47. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/cursor.py +0 -0
  48. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/error.py +0 -0
  49. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/filesystem/__init__.py +0 -0
  50. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/filesystem/s3.py +0 -0
  51. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/filesystem/s3_async.py +0 -0
  52. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/filesystem/s3_executor.py +0 -0
  53. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/filesystem/s3_object.py +0 -0
  54. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/formatter.py +0 -0
  55. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/pandas/__init__.py +0 -0
  56. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/pandas/async_cursor.py +0 -0
  57. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/pandas/cursor.py +0 -0
  58. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/pandas/util.py +0 -0
  59. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/polars/__init__.py +0 -0
  60. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/polars/async_cursor.py +0 -0
  61. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/polars/cursor.py +0 -0
  62. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/polars/result_set.py +0 -0
  63. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/polars/util.py +0 -0
  64. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/py.typed +0 -0
  65. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/result_set.py +0 -0
  66. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/s3fs/__init__.py +0 -0
  67. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/s3fs/async_cursor.py +0 -0
  68. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/s3fs/converter.py +0 -0
  69. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/s3fs/cursor.py +0 -0
  70. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/s3fs/reader.py +0 -0
  71. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/s3fs/result_set.py +0 -0
  72. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/spark/__init__.py +0 -0
  73. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/spark/async_cursor.py +0 -0
  74. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/spark/common.py +0 -0
  75. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/spark/cursor.py +0 -0
  76. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/sqlalchemy/__init__.py +0 -0
  77. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/sqlalchemy/arrow.py +0 -0
  78. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/sqlalchemy/base.py +0 -0
  79. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/sqlalchemy/compiler.py +0 -0
  80. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/sqlalchemy/constants.py +0 -0
  81. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/sqlalchemy/pandas.py +0 -0
  82. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/sqlalchemy/polars.py +0 -0
  83. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/sqlalchemy/preparer.py +0 -0
  84. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/sqlalchemy/requirements.py +0 -0
  85. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/sqlalchemy/rest.py +0 -0
  86. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/sqlalchemy/s3fs.py +0 -0
  87. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/sqlalchemy/types.py +0 -0
  88. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/sqlalchemy/util.py +0 -0
  89. {pyathena-3.30.0 → pyathena-3.31.0}/pyathena/util.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyAthena
3
- Version: 3.30.0
3
+ Version: 3.31.0
4
4
  Summary: Python DB API 2.0 (PEP 249) client for Amazon Athena
5
5
  Project-URL: homepage, https://github.com/pyathena-dev/PyAthena/
6
6
  Project-URL: repository, https://github.com/pyathena-dev/PyAthena/
@@ -38,8 +38,8 @@ Classifier: Programming Language :: Python :: 3.13
38
38
  Classifier: Programming Language :: Python :: 3.14
39
39
  Classifier: Topic :: Database :: Front-Ends
40
40
  Requires-Python: >=3.10
41
- Requires-Dist: boto3>=1.26.4
42
- Requires-Dist: botocore>=1.29.4
41
+ Requires-Dist: boto3>=1.38.2
42
+ Requires-Dist: botocore>=1.41.2
43
43
  Requires-Dist: fsspec
44
44
  Requires-Dist: python-dateutil
45
45
  Requires-Dist: tenacity>=4.1.0
@@ -80,7 +80,7 @@ PyAthena is a Python [DB API 2.0 (PEP 249)](https://www.python.org/dev/peps/pep-
80
80
 
81
81
  ## Requirements
82
82
 
83
- * Python
83
+ - Python
84
84
 
85
85
  - CPython 3.10, 3.11, 3.12, 3.13, 3.14
86
86
 
@@ -136,10 +136,10 @@ Many of the implementations in this library are based on [PyHive](https://github
136
136
 
137
137
  ## Links
138
138
 
139
- - Documentation: https://pyathena.dev/
140
- - PyPI Releases: https://pypi.org/project/PyAthena/
141
- - Source Code: https://github.com/pyathena-dev/PyAthena/
142
- - Issue Tracker: https://github.com/pyathena-dev/PyAthena/issues
139
+ - Documentation: <https://pyathena.dev/>
140
+ - PyPI Releases: <https://pypi.org/project/PyAthena/>
141
+ - Source Code: <https://github.com/pyathena-dev/PyAthena/>
142
+ - Issue Tracker: <https://github.com/pyathena-dev/PyAthena/issues>
143
143
 
144
144
  ## Logo
145
145
 
@@ -21,7 +21,7 @@ PyAthena is a Python [DB API 2.0 (PEP 249)](https://www.python.org/dev/peps/pep-
21
21
 
22
22
  ## Requirements
23
23
 
24
- * Python
24
+ - Python
25
25
 
26
26
  - CPython 3.10, 3.11, 3.12, 3.13, 3.14
27
27
 
@@ -77,10 +77,10 @@ Many of the implementations in this library are based on [PyHive](https://github
77
77
 
78
78
  ## Links
79
79
 
80
- - Documentation: https://pyathena.dev/
81
- - PyPI Releases: https://pypi.org/project/PyAthena/
82
- - Source Code: https://github.com/pyathena-dev/PyAthena/
83
- - Issue Tracker: https://github.com/pyathena-dev/PyAthena/issues
80
+ - Documentation: <https://pyathena.dev/>
81
+ - PyPI Releases: <https://pypi.org/project/PyAthena/>
82
+ - Source Code: <https://github.com/pyathena-dev/PyAthena/>
83
+ - Issue Tracker: <https://github.com/pyathena-dev/PyAthena/issues>
84
84
 
85
85
  ## Logo
86
86
 
@@ -0,0 +1,24 @@
1
+ # file generated by vcs-versioning
2
+ # don't change, don't track in version control
3
+ from __future__ import annotations
4
+
5
+ __all__ = [
6
+ "__version__",
7
+ "__version_tuple__",
8
+ "version",
9
+ "version_tuple",
10
+ "__commit_id__",
11
+ "commit_id",
12
+ ]
13
+
14
+ version: str
15
+ __version__: str
16
+ __version_tuple__: tuple[int | str, ...]
17
+ version_tuple: tuple[int | str, ...]
18
+ commit_id: str | None
19
+ __commit_id__: str | None
20
+
21
+ __version__ = version = '3.31.0'
22
+ __version_tuple__ = version_tuple = (3, 31, 0)
23
+
24
+ __commit_id__ = commit_id = None
@@ -115,4 +115,5 @@ class DefaultArrowUnloadTypeConverter(Converter):
115
115
  )
116
116
 
117
117
  def convert(self, type_: str, value: str | None, type_hint: str | None = None) -> Any | None:
118
- pass
118
+ converter = self.get(type_)
119
+ return converter(value)
@@ -3,12 +3,13 @@ from __future__ import annotations
3
3
  import binascii
4
4
  import json
5
5
  import logging
6
+ import re
6
7
  from abc import ABCMeta, abstractmethod
7
8
  from collections.abc import Callable
8
9
  from copy import deepcopy
9
10
  from datetime import date, datetime, time
10
11
  from decimal import Decimal
11
- from typing import Any
12
+ from typing import Any, ClassVar
12
13
 
13
14
  from dateutil.tz import gettz
14
15
 
@@ -16,7 +17,6 @@ from pyathena.parser import (
16
17
  TypedValueConverter,
17
18
  TypeNode,
18
19
  TypeSignatureParser,
19
- _normalize_hive_syntax,
20
20
  _split_array_items,
21
21
  )
22
22
  from pyathena.util import strtobool
@@ -551,6 +551,9 @@ class DefaultTypeConverter(Converter):
551
551
  ['1', '2', '3']
552
552
  """
553
553
 
554
+ _HIVE_SYNTAX_RE: ClassVar[re.Pattern[str]] = re.compile(r"[<>:]")
555
+ _HIVE_REPLACEMENTS: ClassVar[dict[str, str]] = {"<": "(", ">": ")", ":": " "}
556
+
554
557
  def __init__(self) -> None:
555
558
  super().__init__(mappings=deepcopy(_DEFAULT_CONVERTERS), default=_to_default)
556
559
  self._parser = TypeSignatureParser()
@@ -561,6 +564,25 @@ class DefaultTypeConverter(Converter):
561
564
  )
562
565
  self._parsed_hints: dict[str, TypeNode] = {}
563
566
 
567
+ @staticmethod
568
+ def _normalize_hive_syntax(type_str: str) -> str:
569
+ """Normalize Hive-style DDL syntax to Trino-style.
570
+
571
+ Converts angle-bracket notation (``array<struct<a:int>>``) to
572
+ parenthesized notation (``array(struct(a int))``).
573
+
574
+ Args:
575
+ type_str: Type signature string, possibly using Hive syntax.
576
+
577
+ Returns:
578
+ Normalized type signature using Trino-style parenthesized notation.
579
+ """
580
+ if "<" not in type_str:
581
+ return type_str
582
+ return DefaultTypeConverter._HIVE_SYNTAX_RE.sub(
583
+ lambda m: DefaultTypeConverter._HIVE_REPLACEMENTS[m.group()], type_str
584
+ )
585
+
564
586
  def convert(self, type_: str, value: str | None, type_hint: str | None = None) -> Any | None:
565
587
  """Convert a string value to the appropriate Python type.
566
588
 
@@ -605,7 +627,7 @@ class DefaultTypeConverter(Converter):
605
627
  Returns:
606
628
  Parsed TypeNode.
607
629
  """
608
- normalized = _normalize_hive_syntax(type_hint)
630
+ normalized = self._normalize_hive_syntax(type_hint)
609
631
  if normalized not in self._parsed_hints:
610
632
  self._parsed_hints[normalized] = self._parser.parse(normalized)
611
633
  return self._parsed_hints[normalized]
@@ -111,9 +111,13 @@ class AthenaQueryExecution:
111
111
  self._query_planning_time_in_millis: int | None = statistics.get(
112
112
  "QueryPlanningTimeInMillis", None
113
113
  )
114
+ self._service_pre_processing_time_in_millis: int | None = statistics.get(
115
+ "ServicePreProcessingTimeInMillis", None
116
+ )
114
117
  self._service_processing_time_in_millis: int | None = statistics.get(
115
118
  "ServiceProcessingTimeInMillis", None
116
119
  )
120
+ self._dpu_count: float | None = statistics.get("DpuCount")
117
121
  self._data_manifest_location: str | None = statistics.get("DataManifestLocation")
118
122
  reuse_info = statistics.get("ResultReuseInformation", {})
119
123
  self._reused_previous_result: bool | None = reuse_info.get("ReusedPreviousResult")
@@ -127,6 +131,24 @@ class AthenaQueryExecution:
127
131
  acl_conf = result_conf.get("AclConfiguration", {})
128
132
  self._s3_acl_option: str | None = acl_conf.get("S3AclOption")
129
133
 
134
+ managed_results_conf = query_execution.get("ManagedQueryResultsConfiguration", {})
135
+ self._managed_query_results_enabled: bool | None = managed_results_conf.get("Enabled")
136
+ managed_results_encryption_conf = managed_results_conf.get("EncryptionConfiguration", {})
137
+ self._managed_query_results_kms_key: str | None = managed_results_encryption_conf.get(
138
+ "KmsKey"
139
+ )
140
+
141
+ s3_access_grants_conf = query_execution.get("QueryResultsS3AccessGrantsConfiguration", {})
142
+ self._enable_s3_access_grants: bool | None = s3_access_grants_conf.get(
143
+ "EnableS3AccessGrants"
144
+ )
145
+ self._create_user_level_prefix: bool | None = s3_access_grants_conf.get(
146
+ "CreateUserLevelPrefix"
147
+ )
148
+ self._s3_access_grants_authentication_type: str | None = s3_access_grants_conf.get(
149
+ "AuthenticationType"
150
+ )
151
+
130
152
  engine_version = query_execution.get("EngineVersion", {})
131
153
  self._selected_engine_version: str | None = engine_version.get(
132
154
  "SelectedEngineVersion", None
@@ -224,10 +246,18 @@ class AthenaQueryExecution:
224
246
  def query_planning_time_in_millis(self) -> int | None:
225
247
  return self._query_planning_time_in_millis
226
248
 
249
+ @property
250
+ def service_pre_processing_time_in_millis(self) -> int | None:
251
+ return self._service_pre_processing_time_in_millis
252
+
227
253
  @property
228
254
  def service_processing_time_in_millis(self) -> int | None:
229
255
  return self._service_processing_time_in_millis
230
256
 
257
+ @property
258
+ def dpu_count(self) -> float | None:
259
+ return self._dpu_count
260
+
231
261
  @property
232
262
  def output_location(self) -> str | None:
233
263
  return self._output_location
@@ -272,6 +302,26 @@ class AthenaQueryExecution:
272
302
  def result_reuse_minutes(self) -> int | None:
273
303
  return self._result_reuse_minutes
274
304
 
305
+ @property
306
+ def managed_query_results_enabled(self) -> bool | None:
307
+ return self._managed_query_results_enabled
308
+
309
+ @property
310
+ def managed_query_results_kms_key(self) -> str | None:
311
+ return self._managed_query_results_kms_key
312
+
313
+ @property
314
+ def enable_s3_access_grants(self) -> bool | None:
315
+ return self._enable_s3_access_grants
316
+
317
+ @property
318
+ def create_user_level_prefix(self) -> bool | None:
319
+ return self._create_user_level_prefix
320
+
321
+ @property
322
+ def s3_access_grants_authentication_type(self) -> str | None:
323
+ return self._s3_access_grants_authentication_type
324
+
275
325
 
276
326
  class AthenaCalculationExecutionStatus:
277
327
  """Status information for an Athena calculation execution.
@@ -81,7 +81,8 @@ class DefaultPandasTypeConverter(Converter):
81
81
  return self.__dtypes
82
82
 
83
83
  def convert(self, type_: str, value: str | None, type_hint: str | None = None) -> Any | None:
84
- pass
84
+ converter = self.get(type_)
85
+ return converter(value)
85
86
 
86
87
 
87
88
  class DefaultPandasUnloadTypeConverter(Converter):
@@ -104,4 +105,5 @@ class DefaultPandasUnloadTypeConverter(Converter):
104
105
  )
105
106
 
106
107
  def convert(self, type_: str, value: str | None, type_hint: str | None = None) -> Any | None:
107
- pass
108
+ converter = self.get(type_)
109
+ return converter(value)
@@ -320,38 +320,33 @@ class AthenaPandasResultSet(AthenaResultSet):
320
320
  """Determine the appropriate CSV engine based on configuration and compatibility.
321
321
 
322
322
  Args:
323
- file_size_bytes: Size of the CSV file in bytes.
323
+ file_size_bytes: Size of the CSV file in bytes. Only used for PyArrow
324
+ compatibility checks (minimum file size threshold).
324
325
  chunksize: Chunksize parameter (overrides self._chunksize if provided).
325
326
 
326
327
  Returns:
327
328
  CSV engine name ('pyarrow', 'c', or 'python').
328
329
  """
329
- effective_chunksize = chunksize if chunksize is not None else self._chunksize
330
+ if self._engine == "python":
331
+ return "python"
330
332
 
333
+ # Use PyArrow only when explicitly requested and all compatibility
334
+ # checks pass; otherwise fall through to the C engine default.
331
335
  if self._engine == "pyarrow":
332
- return self._get_pyarrow_engine(file_size_bytes, effective_chunksize)
333
-
334
- if self._engine in ("c", "python"):
335
- return self._engine
336
-
337
- # Auto-selection for "auto" or unknown engine values
338
- return self._get_optimal_csv_engine(file_size_bytes)
339
-
340
- def _get_pyarrow_engine(self, file_size_bytes: int | None, chunksize: int | None) -> str:
341
- """Get PyArrow engine if compatible, otherwise return optimal engine."""
342
- # Check parameter compatibility
343
- if chunksize is not None or self._quoting != 1 or self.converters:
344
- return self._get_optimal_csv_engine(file_size_bytes)
345
-
346
- # Check file size compatibility
347
- if file_size_bytes is not None and file_size_bytes < self.PYARROW_MIN_FILE_SIZE_BYTES:
348
- return self._get_optimal_csv_engine(file_size_bytes)
336
+ effective_chunksize = chunksize if chunksize is not None else self._chunksize
337
+ is_compatible = (
338
+ effective_chunksize is None
339
+ and self._quoting == 1
340
+ and not self.converters
341
+ and (file_size_bytes is None or file_size_bytes >= self.PYARROW_MIN_FILE_SIZE_BYTES)
342
+ )
343
+ if is_compatible:
344
+ try:
345
+ return self._get_available_engine(["pyarrow"])
346
+ except ImportError:
347
+ pass
349
348
 
350
- # Check availability
351
- try:
352
- return self._get_available_engine(["pyarrow"])
353
- except ImportError:
354
- return self._get_optimal_csv_engine(file_size_bytes)
349
+ return "c"
355
350
 
356
351
  def _get_available_engine(self, engine_candidates: list[str]) -> str:
357
352
  """Get the first available engine from a list of candidates.
@@ -382,19 +377,6 @@ class AthenaPandasResultSet(AthenaResultSet):
382
377
  f"{error_msgs}"
383
378
  )
384
379
 
385
- def _get_optimal_csv_engine(self, file_size_bytes: int | None = None) -> str:
386
- """Get the optimal CSV engine based on file size.
387
-
388
- Args:
389
- file_size_bytes: Size of the CSV file in bytes.
390
-
391
- Returns:
392
- 'python' for large files (>50MB) to avoid C parser limits, otherwise 'c'.
393
- """
394
- if file_size_bytes and file_size_bytes > self.LARGE_FILE_THRESHOLD_BYTES:
395
- return "python"
396
- return "c"
397
-
398
380
  def _auto_determine_chunksize(self, file_size_bytes: int) -> int | None:
399
381
  """Determine appropriate chunksize for large files based on file size.
400
382
 
@@ -594,26 +576,6 @@ class AthenaPandasResultSet(AthenaResultSet):
594
576
 
595
577
  except Exception as e:
596
578
  _logger.exception("Failed to read %s.", self.output_location)
597
- error_msg = str(e).lower()
598
- if any(
599
- phrase in error_msg
600
- for phrase in ["signed integer", "maximum", "overflow", "int32", "c parser"]
601
- ):
602
- # Enhanced error message with specific recommendations
603
- file_mb = (length or 0) // (1024 * 1024)
604
- detailed_msg = (
605
- f"Large dataset processing error ({file_mb}MB file): {e}. "
606
- "This is likely due to pandas C parser limitations. "
607
- "Recommended solutions:\n"
608
- "1. Set chunksize: cursor = connection.cursor(PandasCursor, chunksize=50000)\n"
609
- "2. Enable auto-optimization: "
610
- "cursor = connection.cursor(PandasCursor, auto_optimize_chunksize=True)\n"
611
- "3. Use PyArrow engine: "
612
- "cursor = connection.cursor(PandasCursor, engine='pyarrow')\n"
613
- "4. Use Python engine: "
614
- "cursor = connection.cursor(PandasCursor, engine='python')"
615
- )
616
- raise OperationalError(detailed_msg) from e
617
579
  raise OperationalError(*e.args) from e
618
580
 
619
581
  def _read_parquet(self, engine) -> DataFrame:
@@ -1,7 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import json
4
- import re
5
4
  from collections.abc import Callable
6
5
  from dataclasses import dataclass, field
7
6
  from typing import Any
@@ -11,28 +10,6 @@ _TYPE_ALIASES: dict[str, str] = {
11
10
  "int": "integer",
12
11
  }
13
12
 
14
- # Pattern for normalizing Hive-style type signatures to Trino-style.
15
- # Matches angle brackets and colons used in Hive DDL (e.g., array<struct<a:int>>).
16
- _HIVE_SYNTAX_RE: re.Pattern[str] = re.compile(r"[<>:]")
17
- _HIVE_REPLACEMENTS: dict[str, str] = {"<": "(", ">": ")", ":": " "}
18
-
19
-
20
- def _normalize_hive_syntax(type_str: str) -> str:
21
- """Normalize Hive-style DDL syntax to Trino-style.
22
-
23
- Converts angle-bracket notation (``array<struct<a:int>>``) to
24
- parenthesized notation (``array(struct(a int))``).
25
-
26
- Args:
27
- type_str: Type signature string, possibly using Hive syntax.
28
-
29
- Returns:
30
- Normalized type signature using Trino-style parenthesized notation.
31
- """
32
- if "<" not in type_str:
33
- return type_str
34
- return _HIVE_SYNTAX_RE.sub(lambda m: _HIVE_REPLACEMENTS[m.group()], type_str)
35
-
36
13
 
37
14
  def _split_array_items(inner: str) -> list[str]:
38
15
  """Split array items by comma, respecting brace and bracket groupings.
@@ -128,4 +128,5 @@ class DefaultPolarsUnloadTypeConverter(Converter):
128
128
  )
129
129
 
130
130
  def convert(self, type_: str, value: str | None, type_hint: str | None = None) -> Any | None:
131
- pass
131
+ converter = self.get(type_)
132
+ return converter(value)
@@ -5,8 +5,8 @@ authors = [
5
5
  {name = "laughingman7743", email = "laughingman7743@gmail.com"},
6
6
  ]
7
7
  dependencies = [
8
- "boto3>=1.26.4",
9
- "botocore>=1.29.4",
8
+ "boto3>=1.38.2",
9
+ "botocore>=1.41.2",
10
10
  "tenacity>=4.1.0",
11
11
  "fsspec",
12
12
  "python-dateutil",
@@ -226,9 +226,9 @@ allowlist_externals =
226
226
  make
227
227
  commands =
228
228
  uv sync --group dev
229
- pyathena: make test
230
- sqla: make test-sqla
231
- sqla_async: make test-sqla-async
229
+ pyathena: make test/pyathena
230
+ sqla: make test/sqla
231
+ sqla_async: make test/sqla-async
232
232
  passenv =
233
233
  TOXENV
234
234
  AWS_*
@@ -1,34 +0,0 @@
1
- # file generated by setuptools-scm
2
- # don't change, don't track in version control
3
-
4
- __all__ = [
5
- "__version__",
6
- "__version_tuple__",
7
- "version",
8
- "version_tuple",
9
- "__commit_id__",
10
- "commit_id",
11
- ]
12
-
13
- TYPE_CHECKING = False
14
- if TYPE_CHECKING:
15
- from typing import Tuple
16
- from typing import Union
17
-
18
- VERSION_TUPLE = Tuple[Union[int, str], ...]
19
- COMMIT_ID = Union[str, None]
20
- else:
21
- VERSION_TUPLE = object
22
- COMMIT_ID = object
23
-
24
- version: str
25
- __version__: str
26
- __version_tuple__: VERSION_TUPLE
27
- version_tuple: VERSION_TUPLE
28
- commit_id: COMMIT_ID
29
- __commit_id__: COMMIT_ID
30
-
31
- __version__ = version = '3.30.0'
32
- __version_tuple__ = version_tuple = (3, 30, 0)
33
-
34
- __commit_id__ = commit_id = None
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes