Skip to content

Comments

Add native asyncio specialized cursors and DRY refactors (Phase 2)#667

Merged
laughingman7743 merged 7 commits intomasterfrom
feature/native-asyncio-cursor-phase2
Feb 20, 2026
Merged

Add native asyncio specialized cursors and DRY refactors (Phase 2)#667
laughingman7743 merged 7 commits intomasterfrom
feature/native-asyncio-cursor-phase2

Conversation

@laughingman7743
Copy link
Member

@laughingman7743 laughingman7743 commented Feb 20, 2026

Summary

Phase 2 of native asyncio cursor support (follows #666).

Tracks #662 — S3FS/Spark cursors, boilerplate deduplication, and documentation remain for Phase 3.

DRY refactors

  • Add _pre_fetch flag to AthenaResultSet.__init__ to eliminate ~25 lines of duplicated field initialization in AthenaAioResultSet
  • Extract _prepare_query() helper shared by sync/async _execute
  • Extract _build_get_table_metadata_request() helper shared by sync/async _get_table_metadata

Async metadata operations

  • Add list_databases, get_table_metadata, list_table_metadata to AioBaseCursor

Specialized async cursors

  • AioPandasCursor, AioArrowCursor, AioPolarsCursor using asyncio.to_thread() for result set creation
  • No new result set classes needed since fetch/as_pandas/as_arrow/as_polars are pure in-memory operations
  • All cursors placed under pyathena/aio/ package hierarchy for clear separation

Files changed

Action File
Modify pyathena/result_set.py — add _pre_fetch param
Modify pyathena/common.py — extract _prepare_query(), _build_get_table_metadata_request()
Modify pyathena/aio/result_set.py — simplify __init__ via super()
Modify pyathena/aio/common.py — use _prepare_query() / _build_get_table_metadata_request(), add metadata ops
Create pyathena/aio/pandas/__init__.py, cursor.py
Create pyathena/aio/arrow/__init__.py, cursor.py
Create pyathena/aio/polars/__init__.py, cursor.py
Modify tests/pyathena/aio/conftest.py — centralized fixtures for all aio cursors
Modify tests/pyathena/aio/test_cursor.py — add metadata tests
Create tests/pyathena/aio/pandas/__init__.py, test_cursor.py
Create tests/pyathena/aio/arrow/__init__.py, test_cursor.py
Create tests/pyathena/aio/polars/__init__.py, test_cursor.py

Test plan

  • make fmt && make chk passes (lint, format, mypy)
  • Existing tests/pyathena/aio/test_cursor.py tests still pass
  • New metadata operation tests pass (test_list_databases, test_get_table_metadata, test_list_table_metadata)
  • New AioPandasCursor tests pass (fetch, as_pandas, description, cancel, executemany, unload, context manager)
  • New AioArrowCursor tests pass (fetch, as_arrow, as_polars, description, cancel, executemany, unload, context manager)
  • New AioPolarsCursor tests pass (fetch, as_polars, as_arrow, description, cancel, executemany, unload, context manager)

🤖 Generated with Claude Code

laughingman7743 and others added 7 commits February 20, 2026 21:29
Phase 2 of native asyncio cursor support:

- DRY: Add _pre_fetch flag to AthenaResultSet.__init__ to eliminate
  duplicated field initialization in AthenaAioResultSet
- DRY: Extract _prepare_query() from BaseCursor._execute so both
  sync and async _execute share non-I/O query preparation logic
- Add async metadata operations (list_databases, get_table_metadata,
  list_table_metadata) to AioBaseCursor
- Add AioPandasCursor, AioArrowCursor, AioPolarsCursor using
  asyncio.to_thread() for result set creation (no new result set
  classes needed since fetch methods are in-memory only)
- Add comprehensive tests for all new cursors and metadata ops

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move aio_pandas_cursor, aio_arrow_cursor, aio_polars_cursor fixtures
from inline test definitions to tests/pyathena/aio/conftest.py, and
re-export them via conftest.py in each test subpackage so pytest can
discover them across directory boundaries.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Relocate specialized aio cursors from pyathena/{pandas,arrow,polars}/
to pyathena/aio/{pandas,arrow,polars}/ to keep all asyncio code
isolated under the aio package. This provides clearer separation
between sync and async implementations.

- pyathena/pandas/aio_cursor.py -> pyathena/aio/pandas/cursor.py
- pyathena/arrow/aio_cursor.py  -> pyathena/aio/arrow/cursor.py
- pyathena/polars/aio_cursor.py -> pyathena/aio/polars/cursor.py

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move aio cursor tests from tests/pyathena/{pandas,arrow,polars}/ to
tests/pyathena/aio/{pandas,arrow,polars}/ to mirror the source package
structure. This also removes the re-export conftest.py files since the
fixtures in tests/pyathena/aio/conftest.py are now naturally in scope.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Google-style docstrings to close, executemany, cancel, fetchone,
fetchmany, and fetchall methods in AioPandasCursor, AioArrowCursor,
and AioPolarsCursor, matching the level of documentation in AioCursor.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract `_build_get_table_metadata_request` in BaseCursor for
  consistent request construction between sync and async
- Update async `_get_table_metadata` to use the new builder
- Add test_description and test_description_initial to all aio
  specialized cursors (pandas, arrow, polars)
- Add test_cancel_initial to verify ProgrammingError on fresh cursor
- Add test_executemany_fetch to verify state reset after executemany

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…init__.py

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@laughingman7743 laughingman7743 marked this pull request as ready for review February 20, 2026 13:29
@laughingman7743 laughingman7743 merged commit 5238436 into master Feb 20, 2026
5 checks passed
@laughingman7743 laughingman7743 deleted the feature/native-asyncio-cursor-phase2 branch February 20, 2026 13:48
laughingman7743 added a commit that referenced this pull request Feb 21, 2026
Add comprehensive documentation for the native asyncio cursor
implementations added in PRs #666, #667, #668. This includes a new
docs/aio.md overview page, AioCursor sections in each specialized
cursor page, API reference for the aio module, and an async example
in the README.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant