PyAthena 3.29.3__tar.gz → 3.30.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 (100) hide show
  1. {pyathena-3.29.3 → pyathena-3.30.0}/PKG-INFO +8 -7
  2. {pyathena-3.29.3 → pyathena-3.30.0}/README.md +7 -6
  3. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/__init__.py +11 -12
  4. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/_version.py +2 -2
  5. pyathena-3.30.0/pyathena/aio/arrow/__init__.py +0 -0
  6. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/aio/arrow/cursor.py +27 -28
  7. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/aio/common.py +54 -55
  8. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/aio/connection.py +2 -3
  9. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/aio/cursor.py +25 -21
  10. pyathena-3.30.0/pyathena/aio/pandas/__init__.py +0 -0
  11. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/aio/pandas/cursor.py +28 -34
  12. pyathena-3.30.0/pyathena/aio/polars/__init__.py +0 -0
  13. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/aio/polars/cursor.py +28 -29
  14. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/aio/result_set.py +26 -20
  15. pyathena-3.30.0/pyathena/aio/s3fs/__init__.py +0 -0
  16. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/aio/s3fs/cursor.py +24 -25
  17. pyathena-3.30.0/pyathena/aio/spark/__init__.py +0 -0
  18. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/aio/spark/cursor.py +25 -28
  19. pyathena-3.30.0/pyathena/aio/sqlalchemy/__init__.py +0 -0
  20. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/aio/sqlalchemy/arrow.py +0 -1
  21. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/aio/sqlalchemy/base.py +17 -17
  22. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/aio/sqlalchemy/pandas.py +1 -2
  23. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/aio/sqlalchemy/polars.py +0 -1
  24. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/aio/sqlalchemy/rest.py +0 -1
  25. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/aio/sqlalchemy/s3fs.py +0 -1
  26. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/aio/util.py +3 -3
  27. pyathena-3.30.0/pyathena/arrow/__init__.py +0 -0
  28. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/arrow/async_cursor.py +26 -23
  29. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/arrow/converter.py +7 -7
  30. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/arrow/cursor.py +29 -24
  31. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/arrow/result_set.py +28 -32
  32. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/arrow/util.py +3 -4
  33. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/async_cursor.py +36 -26
  34. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/common.py +95 -98
  35. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/connection.py +82 -89
  36. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/converter.py +107 -81
  37. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/cursor.py +40 -35
  38. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/error.py +4 -25
  39. pyathena-3.30.0/pyathena/filesystem/__init__.py +0 -0
  40. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/filesystem/s3.py +94 -73
  41. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/filesystem/s3_async.py +28 -33
  42. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/filesystem/s3_executor.py +4 -4
  43. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/filesystem/s3_object.py +96 -96
  44. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/formatter.py +18 -24
  45. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/model.py +157 -157
  46. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/pandas/__init__.py +0 -1
  47. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/pandas/async_cursor.py +28 -24
  48. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/pandas/converter.py +7 -7
  49. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/pandas/cursor.py +30 -32
  50. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/pandas/result_set.py +60 -61
  51. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/pandas/util.py +44 -51
  52. pyathena-3.30.0/pyathena/parser.py +537 -0
  53. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/polars/__init__.py +0 -1
  54. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/polars/async_cursor.py +29 -23
  55. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/polars/converter.py +6 -6
  56. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/polars/cursor.py +30 -31
  57. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/polars/result_set.py +50 -54
  58. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/polars/util.py +4 -5
  59. pyathena-3.30.0/pyathena/py.typed +0 -0
  60. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/result_set.py +248 -150
  61. pyathena-3.30.0/pyathena/s3fs/__init__.py +0 -0
  62. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/s3fs/async_cursor.py +29 -20
  63. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/s3fs/converter.py +16 -3
  64. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/s3fs/cursor.py +26 -21
  65. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/s3fs/reader.py +15 -16
  66. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/s3fs/result_set.py +46 -24
  67. pyathena-3.30.0/pyathena/spark/__init__.py +0 -0
  68. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/spark/async_cursor.py +15 -16
  69. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/spark/common.py +31 -32
  70. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/spark/cursor.py +15 -16
  71. pyathena-3.30.0/pyathena/sqlalchemy/__init__.py +0 -0
  72. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/sqlalchemy/arrow.py +0 -1
  73. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/sqlalchemy/base.py +48 -62
  74. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/sqlalchemy/compiler.py +83 -83
  75. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/sqlalchemy/constants.py +3 -6
  76. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/sqlalchemy/pandas.py +1 -2
  77. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/sqlalchemy/polars.py +0 -1
  78. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/sqlalchemy/preparer.py +4 -5
  79. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/sqlalchemy/requirements.py +0 -1
  80. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/sqlalchemy/rest.py +0 -1
  81. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/sqlalchemy/s3fs.py +0 -1
  82. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/sqlalchemy/types.py +13 -14
  83. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/sqlalchemy/util.py +2 -3
  84. {pyathena-3.29.3 → pyathena-3.30.0}/pyathena/util.py +11 -10
  85. {pyathena-3.29.3 → pyathena-3.30.0}/pyproject.toml +26 -1
  86. pyathena-3.29.3/pyathena/aio/__init__.py +0 -1
  87. pyathena-3.29.3/pyathena/aio/arrow/__init__.py +0 -1
  88. pyathena-3.29.3/pyathena/aio/pandas/__init__.py +0 -1
  89. pyathena-3.29.3/pyathena/aio/polars/__init__.py +0 -1
  90. pyathena-3.29.3/pyathena/aio/s3fs/__init__.py +0 -1
  91. pyathena-3.29.3/pyathena/aio/spark/__init__.py +0 -1
  92. pyathena-3.29.3/pyathena/aio/sqlalchemy/__init__.py +0 -1
  93. pyathena-3.29.3/pyathena/arrow/__init__.py +0 -1
  94. pyathena-3.29.3/pyathena/filesystem/__init__.py +0 -1
  95. pyathena-3.29.3/pyathena/s3fs/__init__.py +0 -1
  96. pyathena-3.29.3/pyathena/spark/__init__.py +0 -1
  97. pyathena-3.29.3/pyathena/sqlalchemy/__init__.py +0 -1
  98. {pyathena-3.29.3 → pyathena-3.30.0}/.gitignore +0 -0
  99. {pyathena-3.29.3 → pyathena-3.30.0}/LICENSE +0 -0
  100. /pyathena-3.29.3/pyathena/py.typed → /pyathena-3.30.0/pyathena/aio/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyAthena
3
- Version: 3.29.3
3
+ Version: 3.30.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/
@@ -92,12 +92,13 @@ $ pip install PyAthena
92
92
 
93
93
  Extra packages:
94
94
 
95
- | Package | Install command | Version |
96
- |------------|--------------------------------------|----------|
97
- | SQLAlchemy | `pip install PyAthena[SQLAlchemy]` | >=1.0.0 |
98
- | Pandas | `pip install PyAthena[Pandas]` | >=1.3.0 |
99
- | Arrow | `pip install PyAthena[Arrow]` | >=10.0.0 |
100
- | Polars | `pip install PyAthena[Polars]` | >=1.0.0 |
95
+ | Package | Install command | Version |
96
+ |---------------|-----------------------------------------|----------|
97
+ | SQLAlchemy | `pip install PyAthena[SQLAlchemy]` | >=1.0.0 |
98
+ | AioSQLAlchemy | `pip install PyAthena[AioSQLAlchemy]` | >=2.0.0 |
99
+ | Pandas | `pip install PyAthena[Pandas]` | >=1.3.0 |
100
+ | Arrow | `pip install PyAthena[Arrow]` | >=10.0.0 |
101
+ | Polars | `pip install PyAthena[Polars]` | >=1.0.0 |
101
102
 
102
103
  ## Usage
103
104
 
@@ -33,12 +33,13 @@ $ pip install PyAthena
33
33
 
34
34
  Extra packages:
35
35
 
36
- | Package | Install command | Version |
37
- |------------|--------------------------------------|----------|
38
- | SQLAlchemy | `pip install PyAthena[SQLAlchemy]` | >=1.0.0 |
39
- | Pandas | `pip install PyAthena[Pandas]` | >=1.3.0 |
40
- | Arrow | `pip install PyAthena[Arrow]` | >=10.0.0 |
41
- | Polars | `pip install PyAthena[Polars]` | >=1.0.0 |
36
+ | Package | Install command | Version |
37
+ |---------------|-----------------------------------------|----------|
38
+ | SQLAlchemy | `pip install PyAthena[SQLAlchemy]` | >=1.0.0 |
39
+ | AioSQLAlchemy | `pip install PyAthena[AioSQLAlchemy]` | >=2.0.0 |
40
+ | Pandas | `pip install PyAthena[Pandas]` | >=1.3.0 |
41
+ | Arrow | `pip install PyAthena[Arrow]` | >=10.0.0 |
42
+ | Polars | `pip install PyAthena[Polars]` | >=1.0.0 |
42
43
 
43
44
  ## Usage
44
45
 
@@ -1,10 +1,9 @@
1
- # -*- coding: utf-8 -*-
2
1
  from __future__ import annotations
3
2
 
4
3
  import datetime
5
- from typing import TYPE_CHECKING, Any, FrozenSet, Type, overload
4
+ from typing import TYPE_CHECKING, Any, overload
6
5
 
7
- from pyathena.error import * # noqa
6
+ from pyathena.error import * # noqa: F403
8
7
 
9
8
  if TYPE_CHECKING:
10
9
  from pyathena.aio.connection import AioConnection
@@ -28,7 +27,7 @@ threadsafety: int = 2
28
27
  paramstyle: str = "pyformat"
29
28
 
30
29
 
31
- class DBAPITypeObject(FrozenSet[str]):
30
+ class DBAPITypeObject(frozenset[str]):
32
31
  """Type Objects and Constructors
33
32
 
34
33
  https://www.python.org/dev/peps/pep-0249/#type-objects-and-constructors
@@ -60,22 +59,22 @@ TIME: DBAPITypeObject = DBAPITypeObject(("time", "time with time zone"))
60
59
  DATETIME: DBAPITypeObject = DBAPITypeObject(("timestamp", "timestamp with time zone"))
61
60
  JSON: DBAPITypeObject = DBAPITypeObject(("json",))
62
61
 
63
- Date: Type[datetime.date] = datetime.date
64
- Time: Type[datetime.time] = datetime.time
65
- Timestamp: Type[datetime.datetime] = datetime.datetime
62
+ Date: type[datetime.date] = datetime.date
63
+ Time: type[datetime.time] = datetime.time
64
+ Timestamp: type[datetime.datetime] = datetime.datetime
66
65
 
67
66
 
68
67
  @overload
69
- def connect(*args, cursor_class: None = ..., **kwargs) -> "Connection[Cursor]": ...
68
+ def connect(*args, cursor_class: None = ..., **kwargs) -> Connection[Cursor]: ...
70
69
 
71
70
 
72
71
  @overload
73
72
  def connect(
74
- *args, cursor_class: Type[ConnectionCursor], **kwargs
75
- ) -> "Connection[ConnectionCursor]": ...
73
+ *args, cursor_class: type[ConnectionCursor], **kwargs
74
+ ) -> Connection[ConnectionCursor]: ...
76
75
 
77
76
 
78
- def connect(*args, **kwargs) -> "Connection[Any]":
77
+ def connect(*args, **kwargs) -> Connection[Any]:
79
78
  """Create a new database connection to Amazon Athena.
80
79
 
81
80
  This function provides the main entry point for establishing connections
@@ -131,7 +130,7 @@ def connect(*args, **kwargs) -> "Connection[Any]":
131
130
  return Connection(*args, **kwargs)
132
131
 
133
132
 
134
- async def aio_connect(*args, **kwargs) -> "AioConnection":
133
+ async def aio_connect(*args, **kwargs) -> AioConnection:
135
134
  """Create a new async database connection to Amazon Athena.
136
135
 
137
136
  This is the async counterpart of :func:`connect`. It returns an
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '3.29.3'
32
- __version_tuple__ = version_tuple = (3, 29, 3)
31
+ __version__ = version = '3.30.0'
32
+ __version_tuple__ = version_tuple = (3, 30, 0)
33
33
 
34
34
  __commit_id__ = commit_id = None
File without changes
@@ -1,9 +1,8 @@
1
- # -*- coding: utf-8 -*-
2
1
  from __future__ import annotations
3
2
 
4
3
  import asyncio
5
4
  import logging
6
- from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union, cast
5
+ from typing import TYPE_CHECKING, Any, cast
7
6
 
8
7
  from pyathena.aio.common import WithAsyncFetch
9
8
  from pyathena.arrow.converter import (
@@ -19,7 +18,7 @@ if TYPE_CHECKING:
19
18
  import polars as pl
20
19
  from pyarrow import Table
21
20
 
22
- _logger = logging.getLogger(__name__) # type: ignore
21
+ _logger = logging.getLogger(__name__)
23
22
 
24
23
 
25
24
  class AioArrowCursor(WithAsyncFetch):
@@ -37,19 +36,19 @@ class AioArrowCursor(WithAsyncFetch):
37
36
 
38
37
  def __init__(
39
38
  self,
40
- s3_staging_dir: Optional[str] = None,
41
- schema_name: Optional[str] = None,
42
- catalog_name: Optional[str] = None,
43
- work_group: Optional[str] = None,
39
+ s3_staging_dir: str | None = None,
40
+ schema_name: str | None = None,
41
+ catalog_name: str | None = None,
42
+ work_group: str | None = None,
44
43
  poll_interval: float = 1,
45
- encryption_option: Optional[str] = None,
46
- kms_key: Optional[str] = None,
44
+ encryption_option: str | None = None,
45
+ kms_key: str | None = None,
47
46
  kill_on_interrupt: bool = True,
48
47
  unload: bool = False,
49
48
  result_reuse_enable: bool = False,
50
49
  result_reuse_minutes: int = CursorIterator.DEFAULT_RESULT_REUSE_MINUTES,
51
- connect_timeout: Optional[float] = None,
52
- request_timeout: Optional[float] = None,
50
+ connect_timeout: float | None = None,
51
+ request_timeout: float | None = None,
53
52
  **kwargs,
54
53
  ) -> None:
55
54
  super().__init__(
@@ -68,12 +67,12 @@ class AioArrowCursor(WithAsyncFetch):
68
67
  self._unload = unload
69
68
  self._connect_timeout = connect_timeout
70
69
  self._request_timeout = request_timeout
71
- self._result_set: Optional[AthenaArrowResultSet] = None
70
+ self._result_set: AthenaArrowResultSet | None = None
72
71
 
73
72
  @staticmethod
74
73
  def get_default_converter(
75
74
  unload: bool = False,
76
- ) -> Union[DefaultArrowTypeConverter, DefaultArrowUnloadTypeConverter, Any]:
75
+ ) -> DefaultArrowTypeConverter | DefaultArrowUnloadTypeConverter | Any:
77
76
  if unload:
78
77
  return DefaultArrowUnloadTypeConverter()
79
78
  return DefaultArrowTypeConverter()
@@ -81,16 +80,16 @@ class AioArrowCursor(WithAsyncFetch):
81
80
  async def execute( # type: ignore[override]
82
81
  self,
83
82
  operation: str,
84
- parameters: Optional[Union[Dict[str, Any], List[str]]] = None,
85
- work_group: Optional[str] = None,
86
- s3_staging_dir: Optional[str] = None,
87
- cache_size: Optional[int] = 0,
88
- cache_expiration_time: Optional[int] = 0,
89
- result_reuse_enable: Optional[bool] = None,
90
- result_reuse_minutes: Optional[int] = None,
91
- paramstyle: Optional[str] = None,
83
+ parameters: dict[str, Any] | list[str] | None = None,
84
+ work_group: str | None = None,
85
+ s3_staging_dir: str | None = None,
86
+ cache_size: int | None = 0,
87
+ cache_expiration_time: int | None = 0,
88
+ result_reuse_enable: bool | None = None,
89
+ result_reuse_minutes: int | None = None,
90
+ paramstyle: str | None = None,
92
91
  **kwargs,
93
- ) -> "AioArrowCursor":
92
+ ) -> AioArrowCursor:
94
93
  """Execute a SQL query asynchronously and return results as Arrow Tables.
95
94
 
96
95
  Args:
@@ -143,7 +142,7 @@ class AioArrowCursor(WithAsyncFetch):
143
142
 
144
143
  async def fetchone( # type: ignore[override]
145
144
  self,
146
- ) -> Optional[Union[Tuple[Optional[Any], ...], Dict[Any, Optional[Any]]]]:
145
+ ) -> tuple[Any | None, ...] | dict[Any, Any | None] | None:
147
146
  """Fetch the next row of the result set.
148
147
 
149
148
  Wraps the synchronous fetch in ``asyncio.to_thread`` to avoid
@@ -161,8 +160,8 @@ class AioArrowCursor(WithAsyncFetch):
161
160
  return await asyncio.to_thread(result_set.fetchone)
162
161
 
163
162
  async def fetchmany( # type: ignore[override]
164
- self, size: Optional[int] = None
165
- ) -> List[Union[Tuple[Optional[Any], ...], Dict[Any, Optional[Any]]]]:
163
+ self, size: int | None = None
164
+ ) -> list[tuple[Any | None, ...] | dict[Any, Any | None]]:
166
165
  """Fetch multiple rows from the result set.
167
166
 
168
167
  Wraps the synchronous fetch in ``asyncio.to_thread`` to avoid
@@ -184,7 +183,7 @@ class AioArrowCursor(WithAsyncFetch):
184
183
 
185
184
  async def fetchall( # type: ignore[override]
186
185
  self,
187
- ) -> List[Union[Tuple[Optional[Any], ...], Dict[Any, Optional[Any]]]]:
186
+ ) -> list[tuple[Any | None, ...] | dict[Any, Any | None]]:
188
187
  """Fetch all remaining rows from the result set.
189
188
 
190
189
  Wraps the synchronous fetch in ``asyncio.to_thread`` to avoid
@@ -207,7 +206,7 @@ class AioArrowCursor(WithAsyncFetch):
207
206
  raise StopAsyncIteration
208
207
  return row
209
208
 
210
- def as_arrow(self) -> "Table":
209
+ def as_arrow(self) -> Table:
211
210
  """Return query results as an Apache Arrow Table.
212
211
 
213
212
  Returns:
@@ -218,7 +217,7 @@ class AioArrowCursor(WithAsyncFetch):
218
217
  result_set = cast(AthenaArrowResultSet, self.result_set)
219
218
  return result_set.as_arrow()
220
219
 
221
- def as_polars(self) -> "pl.DataFrame":
220
+ def as_polars(self) -> pl.DataFrame:
222
221
  """Return query results as a Polars DataFrame.
223
222
 
224
223
  Returns:
@@ -1,11 +1,10 @@
1
- # -*- coding: utf-8 -*-
2
1
  from __future__ import annotations
3
2
 
4
3
  import asyncio
5
4
  import logging
6
5
  import sys
7
6
  from datetime import datetime, timedelta, timezone
8
- from typing import Any, Dict, List, Optional, Tuple, Union, cast
7
+ from typing import Any, cast
9
8
 
10
9
  from pyathena.aio.util import async_retry_api_call
11
10
  from pyathena.common import BaseCursor, CursorIterator
@@ -13,7 +12,7 @@ from pyathena.error import DatabaseError, OperationalError, ProgrammingError
13
12
  from pyathena.model import AthenaDatabase, AthenaQueryExecution, AthenaTableMetadata
14
13
  from pyathena.result_set import AthenaResultSet, WithResultSet
15
14
 
16
- _logger = logging.getLogger(__name__) # type: ignore
15
+ _logger = logging.getLogger(__name__)
17
16
 
18
17
 
19
18
  class AioBaseCursor(BaseCursor):
@@ -27,14 +26,14 @@ class AioBaseCursor(BaseCursor):
27
26
  async def _execute( # type: ignore[override]
28
27
  self,
29
28
  operation: str,
30
- parameters: Optional[Union[Dict[str, Any], List[str]]] = None,
31
- work_group: Optional[str] = None,
32
- s3_staging_dir: Optional[str] = None,
33
- cache_size: Optional[int] = 0,
34
- cache_expiration_time: Optional[int] = 0,
35
- result_reuse_enable: Optional[bool] = None,
36
- result_reuse_minutes: Optional[int] = None,
37
- paramstyle: Optional[str] = None,
29
+ parameters: dict[str, Any] | list[str] | None = None,
30
+ work_group: str | None = None,
31
+ s3_staging_dir: str | None = None,
32
+ cache_size: int | None = 0,
33
+ cache_expiration_time: int | None = 0,
34
+ result_reuse_enable: bool | None = None,
35
+ result_reuse_minutes: int | None = None,
36
+ paramstyle: str | None = None,
38
37
  ) -> str:
39
38
  query, execution_parameters = self._prepare_query(operation, parameters, paramstyle)
40
39
 
@@ -118,8 +117,8 @@ class AioBaseCursor(BaseCursor):
118
117
  raise OperationalError(*e.args) from e
119
118
 
120
119
  async def _batch_get_query_execution( # type: ignore[override]
121
- self, query_ids: List[str]
122
- ) -> List[AthenaQueryExecution]:
120
+ self, query_ids: list[str]
121
+ ) -> list[AthenaQueryExecution]:
123
122
  try:
124
123
  response = await async_retry_api_call(
125
124
  self.connection._client.batch_get_query_execution,
@@ -138,10 +137,10 @@ class AioBaseCursor(BaseCursor):
138
137
 
139
138
  async def _list_query_executions( # type: ignore[override]
140
139
  self,
141
- work_group: Optional[str] = None,
142
- next_token: Optional[str] = None,
143
- max_results: Optional[int] = None,
144
- ) -> Tuple[Optional[str], List[AthenaQueryExecution]]:
140
+ work_group: str | None = None,
141
+ next_token: str | None = None,
142
+ max_results: int | None = None,
143
+ ) -> tuple[str | None, list[AthenaQueryExecution]]:
145
144
  request = self._build_list_query_executions_request(
146
145
  work_group=work_group, next_token=next_token, max_results=max_results
147
146
  )
@@ -165,10 +164,10 @@ class AioBaseCursor(BaseCursor):
165
164
  async def _find_previous_query_id( # type: ignore[override]
166
165
  self,
167
166
  query: str,
168
- work_group: Optional[str],
167
+ work_group: str | None,
169
168
  cache_size: int = 0,
170
169
  cache_expiration_time: int = 0,
171
- ) -> Optional[str]:
170
+ ) -> str | None:
172
171
  query_id = None
173
172
  if cache_size == 0 and cache_expiration_time > 0:
174
173
  cache_size = sys.maxsize
@@ -191,7 +190,7 @@ class AioBaseCursor(BaseCursor):
191
190
  if e.state == AthenaQueryExecution.STATE_SUCCEEDED
192
191
  and e.statement_type == AthenaQueryExecution.STATEMENT_TYPE_DML
193
192
  ),
194
- key=lambda e: e.completion_date_time, # type: ignore
193
+ key=lambda e: e.completion_date_time, # type: ignore[arg-type, return-value]
195
194
  reverse=True,
196
195
  ):
197
196
  if (
@@ -213,10 +212,10 @@ class AioBaseCursor(BaseCursor):
213
212
 
214
213
  async def _list_databases( # type: ignore[override]
215
214
  self,
216
- catalog_name: Optional[str],
217
- next_token: Optional[str] = None,
218
- max_results: Optional[int] = None,
219
- ) -> Tuple[Optional[str], List[AthenaDatabase]]:
215
+ catalog_name: str | None,
216
+ next_token: str | None = None,
217
+ max_results: int | None = None,
218
+ ) -> tuple[str | None, list[AthenaDatabase]]:
220
219
  request = self._build_list_databases_request(
221
220
  catalog_name=catalog_name,
222
221
  next_token=next_token,
@@ -239,10 +238,10 @@ class AioBaseCursor(BaseCursor):
239
238
 
240
239
  async def list_databases( # type: ignore[override]
241
240
  self,
242
- catalog_name: Optional[str],
243
- max_results: Optional[int] = None,
244
- ) -> List[AthenaDatabase]:
245
- databases: List[AthenaDatabase] = []
241
+ catalog_name: str | None,
242
+ max_results: int | None = None,
243
+ ) -> list[AthenaDatabase]:
244
+ databases: list[AthenaDatabase] = []
246
245
  next_token = None
247
246
  while True:
248
247
  next_token, response = await self._list_databases(
@@ -258,8 +257,8 @@ class AioBaseCursor(BaseCursor):
258
257
  async def _get_table_metadata( # type: ignore[override]
259
258
  self,
260
259
  table_name: str,
261
- catalog_name: Optional[str] = None,
262
- schema_name: Optional[str] = None,
260
+ catalog_name: str | None = None,
261
+ schema_name: str | None = None,
263
262
  logging_: bool = True,
264
263
  ) -> AthenaTableMetadata:
265
264
  request = self._build_get_table_metadata_request(
@@ -284,8 +283,8 @@ class AioBaseCursor(BaseCursor):
284
283
  async def get_table_metadata( # type: ignore[override]
285
284
  self,
286
285
  table_name: str,
287
- catalog_name: Optional[str] = None,
288
- schema_name: Optional[str] = None,
286
+ catalog_name: str | None = None,
287
+ schema_name: str | None = None,
289
288
  logging_: bool = True,
290
289
  ) -> AthenaTableMetadata:
291
290
  return await self._get_table_metadata(
@@ -297,12 +296,12 @@ class AioBaseCursor(BaseCursor):
297
296
 
298
297
  async def _list_table_metadata( # type: ignore[override]
299
298
  self,
300
- catalog_name: Optional[str] = None,
301
- schema_name: Optional[str] = None,
302
- expression: Optional[str] = None,
303
- next_token: Optional[str] = None,
304
- max_results: Optional[int] = None,
305
- ) -> Tuple[Optional[str], List[AthenaTableMetadata]]:
299
+ catalog_name: str | None = None,
300
+ schema_name: str | None = None,
301
+ expression: str | None = None,
302
+ next_token: str | None = None,
303
+ max_results: int | None = None,
304
+ ) -> tuple[str | None, list[AthenaTableMetadata]]:
306
305
  request = self._build_list_table_metadata_request(
307
306
  catalog_name=catalog_name,
308
307
  schema_name=schema_name,
@@ -328,12 +327,12 @@ class AioBaseCursor(BaseCursor):
328
327
 
329
328
  async def list_table_metadata( # type: ignore[override]
330
329
  self,
331
- catalog_name: Optional[str] = None,
332
- schema_name: Optional[str] = None,
333
- expression: Optional[str] = None,
334
- max_results: Optional[int] = None,
335
- ) -> List[AthenaTableMetadata]:
336
- metadata: List[AthenaTableMetadata] = []
330
+ catalog_name: str | None = None,
331
+ schema_name: str | None = None,
332
+ expression: str | None = None,
333
+ max_results: int | None = None,
334
+ ) -> list[AthenaTableMetadata]:
335
+ metadata: list[AthenaTableMetadata] = []
337
336
  next_token = None
338
337
  while True:
339
338
  next_token, response = await self._list_table_metadata(
@@ -363,8 +362,8 @@ class WithAsyncFetch(AioBaseCursor, CursorIterator, WithResultSet):
363
362
 
364
363
  def __init__(self, **kwargs) -> None:
365
364
  super().__init__(**kwargs)
366
- self._query_id: Optional[str] = None
367
- self._result_set: Optional[AthenaResultSet] = None
365
+ self._query_id: str | None = None
366
+ self._result_set: AthenaResultSet | None = None
368
367
 
369
368
  @property
370
369
  def arraysize(self) -> int:
@@ -376,8 +375,8 @@ class WithAsyncFetch(AioBaseCursor, CursorIterator, WithResultSet):
376
375
  raise ProgrammingError("arraysize must be a positive integer value.")
377
376
  self._arraysize = value
378
377
 
379
- @property # type: ignore
380
- def result_set(self) -> Optional[AthenaResultSet]:
378
+ @property # type: ignore[override]
379
+ def result_set(self) -> AthenaResultSet | None:
381
380
  return self._result_set
382
381
 
383
382
  @result_set.setter
@@ -385,7 +384,7 @@ class WithAsyncFetch(AioBaseCursor, CursorIterator, WithResultSet):
385
384
  self._result_set = val
386
385
 
387
386
  @property
388
- def query_id(self) -> Optional[str]:
387
+ def query_id(self) -> str | None:
389
388
  return self._query_id
390
389
 
391
390
  @query_id.setter
@@ -393,7 +392,7 @@ class WithAsyncFetch(AioBaseCursor, CursorIterator, WithResultSet):
393
392
  self._query_id = val
394
393
 
395
394
  @property
396
- def rownumber(self) -> Optional[int]:
395
+ def rownumber(self) -> int | None:
397
396
  return self.result_set.rownumber if self.result_set else None
398
397
 
399
398
  @property
@@ -408,7 +407,7 @@ class WithAsyncFetch(AioBaseCursor, CursorIterator, WithResultSet):
408
407
  async def executemany( # type: ignore[override]
409
408
  self,
410
409
  operation: str,
411
- seq_of_parameters: List[Optional[Union[Dict[str, Any], List[str]]]],
410
+ seq_of_parameters: list[dict[str, Any] | list[str] | None],
412
411
  **kwargs,
413
412
  ) -> None:
414
413
  """Execute a SQL query multiple times with different parameters.
@@ -435,7 +434,7 @@ class WithAsyncFetch(AioBaseCursor, CursorIterator, WithResultSet):
435
434
 
436
435
  def fetchone(
437
436
  self,
438
- ) -> Optional[Union[Tuple[Optional[Any], ...], Dict[Any, Optional[Any]]]]:
437
+ ) -> tuple[Any | None, ...] | dict[Any, Any | None] | None:
439
438
  """Fetch the next row of the result set.
440
439
 
441
440
  Returns:
@@ -450,8 +449,8 @@ class WithAsyncFetch(AioBaseCursor, CursorIterator, WithResultSet):
450
449
  return result_set.fetchone()
451
450
 
452
451
  def fetchmany(
453
- self, size: Optional[int] = None
454
- ) -> List[Union[Tuple[Optional[Any], ...], Dict[Any, Optional[Any]]]]:
452
+ self, size: int | None = None
453
+ ) -> list[tuple[Any | None, ...] | dict[Any, Any | None]]:
455
454
  """Fetch multiple rows from the result set.
456
455
 
457
456
  Args:
@@ -470,7 +469,7 @@ class WithAsyncFetch(AioBaseCursor, CursorIterator, WithResultSet):
470
469
 
471
470
  def fetchall(
472
471
  self,
473
- ) -> List[Union[Tuple[Optional[Any], ...], Dict[Any, Optional[Any]]]]:
472
+ ) -> list[tuple[Any | None, ...] | dict[Any, Any | None]]:
474
473
  """Fetch all remaining rows from the result set.
475
474
 
476
475
  Returns:
@@ -1,4 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
1
  from __future__ import annotations
3
2
 
4
3
  import asyncio
@@ -33,7 +32,7 @@ class AioConnection(Connection[AioCursor]):
33
32
  async def create(
34
33
  cls,
35
34
  **kwargs: Any,
36
- ) -> "AioConnection":
35
+ ) -> AioConnection:
37
36
  """Async factory for creating an ``AioConnection``.
38
37
 
39
38
  Runs the (potentially blocking) ``__init__`` in a thread so that
@@ -47,7 +46,7 @@ class AioConnection(Connection[AioCursor]):
47
46
  """
48
47
  return await asyncio.to_thread(cls, **kwargs)
49
48
 
50
- async def __aenter__(self) -> "AioConnection":
49
+ async def __aenter__(self) -> AioConnection:
51
50
  return self
52
51
 
53
52
  async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
@@ -1,8 +1,7 @@
1
- # -*- coding: utf-8 -*-
2
1
  from __future__ import annotations
3
2
 
4
3
  import logging
5
- from typing import Any, Dict, List, Optional, Union, cast
4
+ from typing import Any, cast
6
5
 
7
6
  from pyathena.aio.common import WithAsyncFetch
8
7
  from pyathena.aio.result_set import AthenaAioDictResultSet, AthenaAioResultSet
@@ -10,7 +9,7 @@ from pyathena.common import CursorIterator
10
9
  from pyathena.error import OperationalError, ProgrammingError
11
10
  from pyathena.model import AthenaQueryExecution
12
11
 
13
- _logger = logging.getLogger(__name__) # type: ignore
12
+ _logger = logging.getLogger(__name__)
14
13
 
15
14
 
16
15
  class AioCursor(WithAsyncFetch):
@@ -29,13 +28,13 @@ class AioCursor(WithAsyncFetch):
29
28
 
30
29
  def __init__(
31
30
  self,
32
- s3_staging_dir: Optional[str] = None,
33
- schema_name: Optional[str] = None,
34
- catalog_name: Optional[str] = None,
35
- work_group: Optional[str] = None,
31
+ s3_staging_dir: str | None = None,
32
+ schema_name: str | None = None,
33
+ catalog_name: str | None = None,
34
+ work_group: str | None = None,
36
35
  poll_interval: float = 1,
37
- encryption_option: Optional[str] = None,
38
- kms_key: Optional[str] = None,
36
+ encryption_option: str | None = None,
37
+ kms_key: str | None = None,
39
38
  kill_on_interrupt: bool = True,
40
39
  result_reuse_enable: bool = False,
41
40
  result_reuse_minutes: int = CursorIterator.DEFAULT_RESULT_REUSE_MINUTES,
@@ -54,7 +53,7 @@ class AioCursor(WithAsyncFetch):
54
53
  result_reuse_minutes=result_reuse_minutes,
55
54
  **kwargs,
56
55
  )
57
- self._result_set: Optional[AthenaAioResultSet] = None
56
+ self._result_set: AthenaAioResultSet | None = None
58
57
  self._result_set_class = AthenaAioResultSet
59
58
 
60
59
  @property
@@ -72,16 +71,17 @@ class AioCursor(WithAsyncFetch):
72
71
  async def execute( # type: ignore[override]
73
72
  self,
74
73
  operation: str,
75
- parameters: Optional[Union[Dict[str, Any], List[str]]] = None,
76
- work_group: Optional[str] = None,
77
- s3_staging_dir: Optional[str] = None,
74
+ parameters: dict[str, Any] | list[str] | None = None,
75
+ work_group: str | None = None,
76
+ s3_staging_dir: str | None = None,
78
77
  cache_size: int = 0,
79
78
  cache_expiration_time: int = 0,
80
- result_reuse_enable: Optional[bool] = None,
81
- result_reuse_minutes: Optional[int] = None,
82
- paramstyle: Optional[str] = None,
79
+ result_reuse_enable: bool | None = None,
80
+ result_reuse_minutes: int | None = None,
81
+ paramstyle: str | None = None,
82
+ result_set_type_hints: dict[str | int, str] | None = None,
83
83
  **kwargs,
84
- ) -> "AioCursor":
84
+ ) -> AioCursor:
85
85
  """Execute a SQL query asynchronously.
86
86
 
87
87
  Args:
@@ -94,6 +94,9 @@ class AioCursor(WithAsyncFetch):
94
94
  result_reuse_enable: Enable result reuse (optional).
95
95
  result_reuse_minutes: Result reuse duration in minutes (optional).
96
96
  paramstyle: Parameter style to use (optional).
97
+ result_set_type_hints: Optional dictionary mapping column names to
98
+ Athena DDL type signatures for precise type conversion within
99
+ complex types.
97
100
  **kwargs: Additional execution parameters.
98
101
 
99
102
  Returns:
@@ -120,6 +123,7 @@ class AioCursor(WithAsyncFetch):
120
123
  query_execution,
121
124
  self.arraysize,
122
125
  self._retry_config,
126
+ result_set_type_hints=result_set_type_hints,
123
127
  )
124
128
  else:
125
129
  raise OperationalError(query_execution.state_change_reason)
@@ -127,7 +131,7 @@ class AioCursor(WithAsyncFetch):
127
131
 
128
132
  async def fetchone( # type: ignore[override]
129
133
  self,
130
- ) -> Optional[Union[Any, Dict[Any, Optional[Any]]]]:
134
+ ) -> Any | dict[Any, Any | None] | None:
131
135
  """Fetch the next row of a query result set.
132
136
 
133
137
  Returns:
@@ -143,8 +147,8 @@ class AioCursor(WithAsyncFetch):
143
147
  return await result_set.fetchone()
144
148
 
145
149
  async def fetchmany( # type: ignore[override]
146
- self, size: Optional[int] = None
147
- ) -> List[Union[Any, Dict[Any, Optional[Any]]]]:
150
+ self, size: int | None = None
151
+ ) -> list[Any | dict[Any, Any | None]]:
148
152
  """Fetch multiple rows from a query result set.
149
153
 
150
154
  Args:
@@ -164,7 +168,7 @@ class AioCursor(WithAsyncFetch):
164
168
 
165
169
  async def fetchall( # type: ignore[override]
166
170
  self,
167
- ) -> List[Union[Any, Dict[Any, Optional[Any]]]]:
171
+ ) -> list[Any | dict[Any, Any | None]]:
168
172
  """Fetch all remaining rows from a query result set.
169
173
 
170
174
  Returns:
File without changes