-
Notifications
You must be signed in to change notification settings - Fork 116
Restore WithResultSet as a mixin with sync and async sibling bases #909
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -794,14 +794,13 @@ def _get_rows( | |
| ] | ||
|
|
||
|
|
||
| class WithResultSet(BaseCursor, CursorIterator): | ||
| """Base class of the SQL cursors that keep a result set. | ||
|
|
||
| Provides the result set and its properties, fetch, ``close``, | ||
| ``executemany``, ``cancel``, and sync iteration. The sync SQL cursors | ||
| subclass it directly. For the asyncio cursors, ``WithAsyncFetch`` | ||
| overrides ``executemany`` and ``cancel`` with async versions, and its | ||
| subclasses override the fetch methods. | ||
| class WithResultSet: | ||
| """Mixin that keeps a cursor's query ID and result set. | ||
|
|
||
| Provides the query ID, the result set and its properties, ``arraysize``, | ||
| ``rownumber``, ``rowcount``, and ``close``. ``WithFetch`` and | ||
| ``WithAsyncFetch`` list it before ``BaseCursor`` / ``AioBaseCursor`` and | ||
| ``CursorIterator``, so that these members take precedence over theirs. | ||
| """ | ||
|
|
||
| def __init__(self, arraysize: int | None = None, **kwargs) -> None: | ||
|
|
@@ -811,7 +810,7 @@ def __init__(self, arraysize: int | None = None, **kwargs) -> None: | |
| arraysize: Default number of rows per ``fetchmany()`` call, | ||
| validated by the ``arraysize`` setter. If None, | ||
| ``DEFAULT_FETCH_SIZE`` is used. | ||
| **kwargs: Arguments passed to ``BaseCursor.__init__``. | ||
| **kwargs: Arguments passed to the next ``__init__`` in the MRO. | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Independent review (relayed): FINDINGS → 1 finding, rejected after verification Reviewer: Codex CLI 0.157.1, model Reviewer coverage: method resolution and initialization of the SQL cursor classes (incl. Dict variants), abstract methods, Finding (P2), Verification: rejected. |
||
|
|
||
| Raises: | ||
| ProgrammingError: If ``arraysize`` is outside the range the | ||
|
|
@@ -1107,6 +1106,23 @@ def rownumber(self) -> int | None: | |
| """ | ||
| return self.result_set.rownumber if self.result_set else None | ||
|
|
||
| def close(self) -> None: | ||
| """Close the cursor and release associated resources.""" | ||
| self._rowcount = -1 | ||
| if self.result_set and not self.result_set.is_closed: | ||
| self.result_set.close() | ||
|
|
||
|
|
||
| class WithFetch(WithResultSet, BaseCursor, CursorIterator): | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Self-review round one (behavior and implementation): CLEAN Base Covered:
No findings. |
||
| """Base class of the sync SQL cursors. | ||
|
|
||
| Combines ``WithResultSet`` with ``BaseCursor`` and ``CursorIterator``, and | ||
| provides sync fetch, ``executemany``, ``cancel``, and sync iteration. | ||
|
|
||
| Subclasses override ``execute()`` and optionally ``__init__`` and | ||
| format-specific helpers. | ||
| """ | ||
|
|
||
| def fetchone( | ||
| self, | ||
| ) -> tuple[Any | None, ...] | dict[Any, Any | None] | None: | ||
|
|
@@ -1158,12 +1174,6 @@ def fetchall( | |
| result_set = cast(AthenaResultSet, self.result_set) | ||
| return result_set.fetchall() | ||
|
|
||
| def close(self) -> None: | ||
| """Close the cursor and release associated resources.""" | ||
| self._rowcount = -1 | ||
| if self.result_set and not self.result_set.is_closed: | ||
| self.result_set.close() | ||
|
|
||
| def executemany( | ||
| self, | ||
| operation: str, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| # Copyright 2026 The PyAthena authors | ||
| # | ||
| # Licensed under the MIT License. | ||
| # See LICENSE or https://opensource.org/licenses/MIT. | ||
| # | ||
| # SPDX-License-Identifier: MIT | ||
| import pytest | ||
|
|
||
| from pyathena.aio.common import AioBaseCursor, WithAsyncFetch | ||
| from pyathena.common import BaseCursor, CursorIterator | ||
| from pyathena.result_set import WithFetch, WithResultSet | ||
|
|
||
|
|
||
| class TestWithResultSet: | ||
| def test_is_mixin(self): | ||
| assert WithResultSet.__bases__ == (object,) | ||
|
|
||
| @pytest.mark.parametrize( | ||
| ("cursor_base", "base"), | ||
| [(WithFetch, BaseCursor), (WithAsyncFetch, AioBaseCursor)], | ||
| ) | ||
| def test_precedes_cursor_bases(self, cursor_base, base): | ||
| # Listed first, so that its members take precedence over the cursor bases'. | ||
| assert cursor_base.__bases__ == (WithResultSet, base, CursorIterator) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Self-review round two (claims, callers, docs): FINDINGS, repaired
Base
809b38070ff7ed69b960f9f4318a82e03723fd2c, head7d9ba8f55b82eae282567d61aae918ff797a595b→ repaired head85f0baa6b093adfc3b262d0f9a29dbdcd71ccb78(commit message only; tree unchanged).Claims checked:
git show v3.37.0:and51532ed7:ofresult_set.pyandaio/common.pymatch the table.WithFetchandWithAsyncFetchduplicated before Share the pure cursor-base logic between the sync and asyncio cursors #883":51532ed7defines__init__,arraysize,result_set,query_id,rownumber,rowcount,closein both; all are now inWithResultSetonly.class MyCursor(BaseCursor, CursorIterator, WithResultSet)raises the MROTypeErroron master and works on this branch and on v3.37.0; aWithFetchsubclass works on this branch and v3.37.0 (itsarraysize=7result differs only by SQL cursors ignore the arraysize keyword argument #897, already release-noted). Added this evidence to the PR body.**kwargs/DEFAULT_FETCH_SIZEinWithResultSet.__init__, "sync iteration" inWithFetch(fromCursorIterator), "subclasses implement the fetch methods as coroutines" (all 5 aio cursors define asyncfetchone/fetchmany/fetchall): true.WithFetch/WithResultSetbeyond theautoclassentries;docs/api/connection.rstnow renders fewer inherited members for the mixin.just docs buildnot run (docs sources unchanged).Findings and repairs:
--force-with-lease.WithResultSet. Narrowed.