PyAthena 3.29.3__tar.gz → 3.30.1__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.
- {pyathena-3.29.3 → pyathena-3.30.1}/PKG-INFO +8 -7
- {pyathena-3.29.3 → pyathena-3.30.1}/README.md +7 -6
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/__init__.py +11 -12
- pyathena-3.30.1/pyathena/_version.py +24 -0
- pyathena-3.30.1/pyathena/aio/arrow/__init__.py +0 -0
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/aio/arrow/cursor.py +27 -28
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/aio/common.py +54 -55
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/aio/connection.py +2 -3
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/aio/cursor.py +25 -21
- pyathena-3.30.1/pyathena/aio/pandas/__init__.py +0 -0
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/aio/pandas/cursor.py +28 -34
- pyathena-3.30.1/pyathena/aio/polars/__init__.py +0 -0
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/aio/polars/cursor.py +28 -29
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/aio/result_set.py +26 -20
- pyathena-3.30.1/pyathena/aio/s3fs/__init__.py +0 -0
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/aio/s3fs/cursor.py +24 -25
- pyathena-3.30.1/pyathena/aio/spark/__init__.py +0 -0
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/aio/spark/cursor.py +25 -28
- pyathena-3.30.1/pyathena/aio/sqlalchemy/__init__.py +0 -0
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/aio/sqlalchemy/arrow.py +0 -1
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/aio/sqlalchemy/base.py +17 -17
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/aio/sqlalchemy/pandas.py +1 -2
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/aio/sqlalchemy/polars.py +0 -1
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/aio/sqlalchemy/rest.py +0 -1
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/aio/sqlalchemy/s3fs.py +0 -1
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/aio/util.py +3 -3
- pyathena-3.30.1/pyathena/arrow/__init__.py +0 -0
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/arrow/async_cursor.py +26 -23
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/arrow/converter.py +9 -8
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/arrow/cursor.py +29 -24
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/arrow/result_set.py +28 -32
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/arrow/util.py +3 -4
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/async_cursor.py +36 -26
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/common.py +95 -98
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/connection.py +82 -89
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/converter.py +129 -81
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/cursor.py +40 -35
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/error.py +4 -25
- pyathena-3.30.1/pyathena/filesystem/__init__.py +0 -0
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/filesystem/s3.py +94 -73
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/filesystem/s3_async.py +28 -33
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/filesystem/s3_executor.py +4 -4
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/filesystem/s3_object.py +96 -96
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/formatter.py +18 -24
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/model.py +157 -157
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/pandas/__init__.py +0 -1
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/pandas/async_cursor.py +28 -24
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/pandas/converter.py +11 -9
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/pandas/cursor.py +30 -32
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/pandas/result_set.py +77 -116
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/pandas/util.py +44 -51
- pyathena-3.30.1/pyathena/parser.py +514 -0
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/polars/__init__.py +0 -1
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/polars/async_cursor.py +29 -23
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/polars/converter.py +8 -7
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/polars/cursor.py +30 -31
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/polars/result_set.py +50 -54
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/polars/util.py +4 -5
- pyathena-3.30.1/pyathena/py.typed +0 -0
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/result_set.py +248 -150
- pyathena-3.30.1/pyathena/s3fs/__init__.py +0 -0
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/s3fs/async_cursor.py +29 -20
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/s3fs/converter.py +16 -3
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/s3fs/cursor.py +26 -21
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/s3fs/reader.py +15 -16
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/s3fs/result_set.py +46 -24
- pyathena-3.30.1/pyathena/spark/__init__.py +0 -0
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/spark/async_cursor.py +15 -16
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/spark/common.py +31 -32
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/spark/cursor.py +15 -16
- pyathena-3.30.1/pyathena/sqlalchemy/__init__.py +0 -0
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/sqlalchemy/arrow.py +0 -1
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/sqlalchemy/base.py +48 -62
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/sqlalchemy/compiler.py +83 -83
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/sqlalchemy/constants.py +3 -6
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/sqlalchemy/pandas.py +1 -2
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/sqlalchemy/polars.py +0 -1
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/sqlalchemy/preparer.py +4 -5
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/sqlalchemy/requirements.py +0 -1
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/sqlalchemy/rest.py +0 -1
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/sqlalchemy/s3fs.py +0 -1
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/sqlalchemy/types.py +13 -14
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/sqlalchemy/util.py +2 -3
- {pyathena-3.29.3 → pyathena-3.30.1}/pyathena/util.py +11 -10
- {pyathena-3.29.3 → pyathena-3.30.1}/pyproject.toml +26 -1
- pyathena-3.29.3/pyathena/_version.py +0 -34
- pyathena-3.29.3/pyathena/aio/__init__.py +0 -1
- pyathena-3.29.3/pyathena/aio/arrow/__init__.py +0 -1
- pyathena-3.29.3/pyathena/aio/pandas/__init__.py +0 -1
- pyathena-3.29.3/pyathena/aio/polars/__init__.py +0 -1
- pyathena-3.29.3/pyathena/aio/s3fs/__init__.py +0 -1
- pyathena-3.29.3/pyathena/aio/spark/__init__.py +0 -1
- pyathena-3.29.3/pyathena/aio/sqlalchemy/__init__.py +0 -1
- pyathena-3.29.3/pyathena/arrow/__init__.py +0 -1
- pyathena-3.29.3/pyathena/filesystem/__init__.py +0 -1
- pyathena-3.29.3/pyathena/s3fs/__init__.py +0 -1
- pyathena-3.29.3/pyathena/spark/__init__.py +0 -1
- pyathena-3.29.3/pyathena/sqlalchemy/__init__.py +0 -1
- {pyathena-3.29.3 → pyathena-3.30.1}/.gitignore +0 -0
- {pyathena-3.29.3 → pyathena-3.30.1}/LICENSE +0 -0
- /pyathena-3.29.3/pyathena/py.typed → /pyathena-3.30.1/pyathena/aio/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyAthena
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.30.1
|
|
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
|
|
96
|
-
|
|
97
|
-
| SQLAlchemy
|
|
98
|
-
|
|
|
99
|
-
|
|
|
100
|
-
|
|
|
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
|
|
37
|
-
|
|
38
|
-
| SQLAlchemy
|
|
39
|
-
|
|
|
40
|
-
|
|
|
41
|
-
|
|
|
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,
|
|
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(
|
|
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:
|
|
64
|
-
Time:
|
|
65
|
-
Timestamp:
|
|
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) ->
|
|
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:
|
|
75
|
-
) ->
|
|
73
|
+
*args, cursor_class: type[ConnectionCursor], **kwargs
|
|
74
|
+
) -> Connection[ConnectionCursor]: ...
|
|
76
75
|
|
|
77
76
|
|
|
78
|
-
def connect(*args, **kwargs) ->
|
|
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) ->
|
|
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
|
|
@@ -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.30.1'
|
|
22
|
+
__version_tuple__ = version_tuple = (3, 30, 1)
|
|
23
|
+
|
|
24
|
+
__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,
|
|
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__)
|
|
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:
|
|
41
|
-
schema_name:
|
|
42
|
-
catalog_name:
|
|
43
|
-
work_group:
|
|
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:
|
|
46
|
-
kms_key:
|
|
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:
|
|
52
|
-
request_timeout:
|
|
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:
|
|
70
|
+
self._result_set: AthenaArrowResultSet | None = None
|
|
72
71
|
|
|
73
72
|
@staticmethod
|
|
74
73
|
def get_default_converter(
|
|
75
74
|
unload: bool = False,
|
|
76
|
-
) ->
|
|
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:
|
|
85
|
-
work_group:
|
|
86
|
-
s3_staging_dir:
|
|
87
|
-
cache_size:
|
|
88
|
-
cache_expiration_time:
|
|
89
|
-
result_reuse_enable:
|
|
90
|
-
result_reuse_minutes:
|
|
91
|
-
paramstyle:
|
|
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
|
-
) ->
|
|
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
|
-
) ->
|
|
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:
|
|
165
|
-
) ->
|
|
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
|
-
) ->
|
|
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) ->
|
|
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) ->
|
|
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,
|
|
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__)
|
|
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:
|
|
31
|
-
work_group:
|
|
32
|
-
s3_staging_dir:
|
|
33
|
-
cache_size:
|
|
34
|
-
cache_expiration_time:
|
|
35
|
-
result_reuse_enable:
|
|
36
|
-
result_reuse_minutes:
|
|
37
|
-
paramstyle:
|
|
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:
|
|
122
|
-
) ->
|
|
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:
|
|
142
|
-
next_token:
|
|
143
|
-
max_results:
|
|
144
|
-
) ->
|
|
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:
|
|
167
|
+
work_group: str | None,
|
|
169
168
|
cache_size: int = 0,
|
|
170
169
|
cache_expiration_time: int = 0,
|
|
171
|
-
) ->
|
|
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:
|
|
217
|
-
next_token:
|
|
218
|
-
max_results:
|
|
219
|
-
) ->
|
|
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:
|
|
243
|
-
max_results:
|
|
244
|
-
) ->
|
|
245
|
-
databases:
|
|
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:
|
|
262
|
-
schema_name:
|
|
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:
|
|
288
|
-
schema_name:
|
|
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:
|
|
301
|
-
schema_name:
|
|
302
|
-
expression:
|
|
303
|
-
next_token:
|
|
304
|
-
max_results:
|
|
305
|
-
) ->
|
|
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:
|
|
332
|
-
schema_name:
|
|
333
|
-
expression:
|
|
334
|
-
max_results:
|
|
335
|
-
) ->
|
|
336
|
-
metadata:
|
|
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:
|
|
367
|
-
self._result_set:
|
|
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) ->
|
|
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) ->
|
|
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) ->
|
|
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:
|
|
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
|
-
) ->
|
|
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:
|
|
454
|
-
) ->
|
|
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
|
-
) ->
|
|
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
|
-
) ->
|
|
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) ->
|
|
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,
|
|
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__)
|
|
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:
|
|
33
|
-
schema_name:
|
|
34
|
-
catalog_name:
|
|
35
|
-
work_group:
|
|
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:
|
|
38
|
-
kms_key:
|
|
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:
|
|
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:
|
|
76
|
-
work_group:
|
|
77
|
-
s3_staging_dir:
|
|
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:
|
|
81
|
-
result_reuse_minutes:
|
|
82
|
-
paramstyle:
|
|
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
|
-
) ->
|
|
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
|
-
) ->
|
|
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:
|
|
147
|
-
) ->
|
|
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
|
-
) ->
|
|
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
|