Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
result.py962 linesDownload Raw Back to asyncio
1# ext/asyncio/result.py
2# Copyright (C) 2020-2024 the SQLAlchemy authors and contributors
3# <see AUTHORS file>
4#
5# This module is part of SQLAlchemy and is released under
6# the MIT License: https://www.opensource.org/licenses/mit-license.php
7from __future__ import annotations
8
9import operator
10from typing import Any
11from typing import AsyncIterator
12from typing import Optional
13from typing import overload
14from typing import Sequence
15from typing import Tuple
16from typing import TYPE_CHECKING
17from typing import TypeVar
18
19from . import exc as async_exc
20from ... import util
21from ...engine import Result
22from ...engine.result import _NO_ROW
23from ...engine.result import _R
24from ...engine.result import _WithKeys
25from ...engine.result import FilterResult
26from ...engine.result import FrozenResult
27from ...engine.result import ResultMetaData
28from ...engine.row import Row
29from ...engine.row import RowMapping
30from ...sql.base import _generative
31from ...util.concurrency import greenlet_spawn
32from ...util.typing import Literal
33from ...util.typing import Self
34
35if TYPE_CHECKING:
36    from ...engine import CursorResult
37    from ...engine.result import _KeyIndexType
38    from ...engine.result import _UniqueFilterType
39
40_T = TypeVar("_T", bound=Any)
41_TP = TypeVar("_TP", bound=Tuple[Any, ...])
42
43
44class AsyncCommon(FilterResult[_R]):
45    __slots__ = ()
46
47    _real_result: Result[Any]
48    _metadata: ResultMetaData
49
50    async def close(self) -> None:  # type: ignore[override]
51        """Close this result."""
52
53        await greenlet_spawn(self._real_result.close)
54
55    @property
56    def closed(self) -> bool:
57        """proxies the .closed attribute of the underlying result object,
58        if any, else raises ``AttributeError``.
59
60        .. versionadded:: 2.0.0b3
61
62        """
63        return self._real_result.closed
64
65
66class AsyncResult(_WithKeys, AsyncCommon[Row[_TP]]):
67    """An asyncio wrapper around a :class:`_result.Result` object.
68
69    The :class:`_asyncio.AsyncResult` only applies to statement executions that
70    use a server-side cursor.  It is returned only from the
71    :meth:`_asyncio.AsyncConnection.stream` and
72    :meth:`_asyncio.AsyncSession.stream` methods.
73
74    .. note:: As is the case with :class:`_engine.Result`, this object is
75       used for ORM results returned by :meth:`_asyncio.AsyncSession.execute`,
76       which can yield instances of ORM mapped objects either individually or
77       within tuple-like rows.  Note that these result objects do not
78       deduplicate instances or rows automatically as is the case with the
79       legacy :class:`_orm.Query` object. For in-Python de-duplication of
80       instances or rows, use the :meth:`_asyncio.AsyncResult.unique` modifier
81       method.
82
83    .. versionadded:: 1.4
84
85    """
86
87    __slots__ = ()
88
89    _real_result: Result[_TP]
90
91    def __init__(self, real_result: Result[_TP]):
92        self._real_result = real_result
93
94        self._metadata = real_result._metadata
95        self._unique_filter_state = real_result._unique_filter_state
96        self._post_creational_filter = None
97
98        # BaseCursorResult pre-generates the "_row_getter".  Use that
99        # if available rather than building a second one
100        if "_row_getter" in real_result.__dict__:
101            self._set_memoized_attribute(
102                "_row_getter", real_result.__dict__["_row_getter"]
103            )
104
105    @property
106    def t(self) -> AsyncTupleResult[_TP]:
107        """Apply a "typed tuple" typing filter to returned rows.
108
109        The :attr:`_asyncio.AsyncResult.t` attribute is a synonym for
110        calling the :meth:`_asyncio.AsyncResult.tuples` method.
111
112        .. versionadded:: 2.0
113
114        """
115        return self  # type: ignore
116
117    def tuples(self) -> AsyncTupleResult[_TP]:
118        """Apply a "typed tuple" typing filter to returned rows.
119
120        This method returns the same :class:`_asyncio.AsyncResult` object
121        at runtime,
122        however annotates as returning a :class:`_asyncio.AsyncTupleResult`
123        object that will indicate to :pep:`484` typing tools that plain typed
124        ``Tuple`` instances are returned rather than rows.  This allows
125        tuple unpacking and ``__getitem__`` access of :class:`_engine.Row`
126        objects to by typed, for those cases where the statement invoked
127        itself included typing information.
128
129        .. versionadded:: 2.0
130
131        :return: the :class:`_result.AsyncTupleResult` type at typing time.
132
133        .. seealso::
134
135            :attr:`_asyncio.AsyncResult.t` - shorter synonym
136
137            :attr:`_engine.Row.t` - :class:`_engine.Row` version
138
139        """
140
141        return self  # type: ignore
142
143    @_generative
144    def unique(self, strategy: Optional[_UniqueFilterType] = None) -> Self:
145        """Apply unique filtering to the objects returned by this
146        :class:`_asyncio.AsyncResult`.
147
148        Refer to :meth:`_engine.Result.unique` in the synchronous
149        SQLAlchemy API for a complete behavioral description.
150
151        """
152        self._unique_filter_state = (set(), strategy)
153        return self
154
155    def columns(self, *col_expressions: _KeyIndexType) -> Self:
156        r"""Establish the columns that should be returned in each row.
157
158        Refer to :meth:`_engine.Result.columns` in the synchronous
159        SQLAlchemy API for a complete behavioral description.
160
161        """
162        return self._column_slices(col_expressions)
163
164    async def partitions(
165        self, size: Optional[int] = None
166    ) -> AsyncIterator[Sequence[Row[_TP]]]:
167        """Iterate through sub-lists of rows of the size given.
168
169        An async iterator is returned::
170
171            async def scroll_results(connection):
172                result = await connection.stream(select(users_table))
173
174                async for partition in result.partitions(100):
175                    print("list of rows: %s" % partition)
176
177        Refer to :meth:`_engine.Result.partitions` in the synchronous
178        SQLAlchemy API for a complete behavioral description.
179
180        """
181
182        getter = self._manyrow_getter
183
184        while True:
185            partition = await greenlet_spawn(getter, self, size)
186            if partition:
187                yield partition
188            else:
189                break
190
191    async def fetchall(self) -> Sequence[Row[_TP]]:
192        """A synonym for the :meth:`_asyncio.AsyncResult.all` method.
193
194        .. versionadded:: 2.0
195
196        """
197
198        return await greenlet_spawn(self._allrows)
199
200    async def fetchone(self) -> Optional[Row[_TP]]:
201        """Fetch one row.
202
203        When all rows are exhausted, returns None.
204
205        This method is provided for backwards compatibility with
206        SQLAlchemy 1.x.x.
207
208        To fetch the first row of a result only, use the
209        :meth:`_asyncio.AsyncResult.first` method.  To iterate through all
210        rows, iterate the :class:`_asyncio.AsyncResult` object directly.
211
212        :return: a :class:`_engine.Row` object if no filters are applied,
213         or ``None`` if no rows remain.
214
215        """
216        row = await greenlet_spawn(self._onerow_getter, self)
217        if row is _NO_ROW:
218            return None
219        else:
220            return row
221
222    async def fetchmany(
223        self, size: Optional[int] = None
224    ) -> Sequence[Row[_TP]]:
225        """Fetch many rows.
226
227        When all rows are exhausted, returns an empty list.
228
229        This method is provided for backwards compatibility with
230        SQLAlchemy 1.x.x.
231
232        To fetch rows in groups, use the
233        :meth:`._asyncio.AsyncResult.partitions` method.
234
235        :return: a list of :class:`_engine.Row` objects.
236
237        .. seealso::
238
239            :meth:`_asyncio.AsyncResult.partitions`
240
241        """
242
243        return await greenlet_spawn(self._manyrow_getter, self, size)
244
245    async def all(self) -> Sequence[Row[_TP]]:
246        """Return all rows in a list.
247
248        Closes the result set after invocation.   Subsequent invocations
249        will return an empty list.
250
251        :return: a list of :class:`_engine.Row` objects.
252
253        """
254
255        return await greenlet_spawn(self._allrows)
256
257    def __aiter__(self) -> AsyncResult[_TP]:
258        return self
259
260    async def __anext__(self) -> Row[_TP]:
261        row = await greenlet_spawn(self._onerow_getter, self)
262        if row is _NO_ROW:
263            raise StopAsyncIteration()
264        else:
265            return row
266
267    async def first(self) -> Optional[Row[_TP]]:
268        """Fetch the first row or ``None`` if no row is present.
269
270        Closes the result set and discards remaining rows.
271
272        .. note::  This method returns one **row**, e.g. tuple, by default.
273           To return exactly one single scalar value, that is, the first
274           column of the first row, use the
275           :meth:`_asyncio.AsyncResult.scalar` method,
276           or combine :meth:`_asyncio.AsyncResult.scalars` and
277           :meth:`_asyncio.AsyncResult.first`.
278
279           Additionally, in contrast to the behavior of the legacy  ORM
280           :meth:`_orm.Query.first` method, **no limit is applied** to the
281           SQL query which was invoked to produce this
282           :class:`_asyncio.AsyncResult`;
283           for a DBAPI driver that buffers results in memory before yielding
284           rows, all rows will be sent to the Python process and all but
285           the first row will be discarded.
286
287           .. seealso::
288
289                :ref:`migration_20_unify_select`
290
291        :return: a :class:`_engine.Row` object, or None
292         if no rows remain.
293
294        .. seealso::
295
296            :meth:`_asyncio.AsyncResult.scalar`
297
298            :meth:`_asyncio.AsyncResult.one`
299
300        """
301        return await greenlet_spawn(self._only_one_row, False, False, False)
302
303    async def one_or_none(self) -> Optional[Row[_TP]]:
304        """Return at most one result or raise an exception.
305
306        Returns ``None`` if the result has no rows.
307        Raises :class:`.MultipleResultsFound`
308        if multiple rows are returned.
309
310        .. versionadded:: 1.4
311
312        :return: The first :class:`_engine.Row` or ``None`` if no row
313         is available.
314
315        :raises: :class:`.MultipleResultsFound`
316
317        .. seealso::
318
319            :meth:`_asyncio.AsyncResult.first`
320
321            :meth:`_asyncio.AsyncResult.one`
322
323        """
324        return await greenlet_spawn(self._only_one_row, True, False, False)
325
326    @overload
327    async def scalar_one(self: AsyncResult[Tuple[_T]]) -> _T: ...
328
329    @overload
330    async def scalar_one(self) -> Any: ...
331
332    async def scalar_one(self) -> Any:
333        """Return exactly one scalar result or raise an exception.
334
335        This is equivalent to calling :meth:`_asyncio.AsyncResult.scalars` and
336        then :meth:`_asyncio.AsyncResult.one`.
337
338        .. seealso::
339
340            :meth:`_asyncio.AsyncResult.one`
341
342            :meth:`_asyncio.AsyncResult.scalars`
343
344        """
345        return await greenlet_spawn(self._only_one_row, True, True, True)
346
347    @overload
348    async def scalar_one_or_none(
349        self: AsyncResult[Tuple[_T]],
350    ) -> Optional[_T]: ...
351
352    @overload
353    async def scalar_one_or_none(self) -> Optional[Any]: ...
354
355    async def scalar_one_or_none(self) -> Optional[Any]:
356        """Return exactly one scalar result or ``None``.
357
358        This is equivalent to calling :meth:`_asyncio.AsyncResult.scalars` and
359        then :meth:`_asyncio.AsyncResult.one_or_none`.
360
361        .. seealso::
362
363            :meth:`_asyncio.AsyncResult.one_or_none`
364
365            :meth:`_asyncio.AsyncResult.scalars`
366
367        """
368        return await greenlet_spawn(self._only_one_row, True, False, True)
369
370    async def one(self) -> Row[_TP]:
371        """Return exactly one row or raise an exception.
372
373        Raises :class:`.NoResultFound` if the result returns no
374        rows, or :class:`.MultipleResultsFound` if multiple rows
375        would be returned.
376
377        .. note::  This method returns one **row**, e.g. tuple, by default.
378           To return exactly one single scalar value, that is, the first
379           column of the first row, use the
380           :meth:`_asyncio.AsyncResult.scalar_one` method, or combine
381           :meth:`_asyncio.AsyncResult.scalars` and
382           :meth:`_asyncio.AsyncResult.one`.
383
384        .. versionadded:: 1.4
385
386        :return: The first :class:`_engine.Row`.
387
388        :raises: :class:`.MultipleResultsFound`, :class:`.NoResultFound`
389
390        .. seealso::
391
392            :meth:`_asyncio.AsyncResult.first`
393
394            :meth:`_asyncio.AsyncResult.one_or_none`
395
396            :meth:`_asyncio.AsyncResult.scalar_one`
397
398        """
399        return await greenlet_spawn(self._only_one_row, True, True, False)
400
401    @overload
402    async def scalar(self: AsyncResult[Tuple[_T]]) -> Optional[_T]: ...
403
404    @overload
405    async def scalar(self) -> Any: ...
406
407    async def scalar(self) -> Any:
408        """Fetch the first column of the first row, and close the result set.
409
410        Returns ``None`` if there are no rows to fetch.
411
412        No validation is performed to test if additional rows remain.
413
414        After calling this method, the object is fully closed,
415        e.g. the :meth:`_engine.CursorResult.close`
416        method will have been called.
417
418        :return: a Python scalar value, or ``None`` if no rows remain.
419
420        """
421        return await greenlet_spawn(self._only_one_row, False, False, True)
422
423    async def freeze(self) -> FrozenResult[_TP]:
424        """Return a callable object that will produce copies of this
425        :class:`_asyncio.AsyncResult` when invoked.
426
427        The callable object returned is an instance of
428        :class:`_engine.FrozenResult`.
429
430        This is used for result set caching.  The method must be called
431        on the result when it has been unconsumed, and calling the method
432        will consume the result fully.   When the :class:`_engine.FrozenResult`
433        is retrieved from a cache, it can be called any number of times where
434        it will produce a new :class:`_engine.Result` object each time
435        against its stored set of rows.
436
437        .. seealso::
438
439            :ref:`do_orm_execute_re_executing` - example usage within the
440            ORM to implement a result-set cache.
441
442        """
443
444        return await greenlet_spawn(FrozenResult, self)
445
446    @overload
447    def scalars(
448        self: AsyncResult[Tuple[_T]], index: Literal[0]
449    ) -> AsyncScalarResult[_T]: ...
450
451    @overload
452    def scalars(self: AsyncResult[Tuple[_T]]) -> AsyncScalarResult[_T]: ...
453
454    @overload
455    def scalars(self, index: _KeyIndexType = 0) -> AsyncScalarResult[Any]: ...
456
457    def scalars(self, index: _KeyIndexType = 0) -> AsyncScalarResult[Any]:
458        """Return an :class:`_asyncio.AsyncScalarResult` filtering object which
459        will return single elements rather than :class:`_row.Row` objects.
460
461        Refer to :meth:`_result.Result.scalars` in the synchronous
462        SQLAlchemy API for a complete behavioral description.
463
464        :param index: integer or row key indicating the column to be fetched
465         from each row, defaults to ``0`` indicating the first column.
466
467        :return: a new :class:`_asyncio.AsyncScalarResult` filtering object
468         referring to this :class:`_asyncio.AsyncResult` object.
469
470        """
471        return AsyncScalarResult(self._real_result, index)
472
473    def mappings(self) -> AsyncMappingResult:
474        """Apply a mappings filter to returned rows, returning an instance of
475        :class:`_asyncio.AsyncMappingResult`.
476
477        When this filter is applied, fetching rows will return
478        :class:`_engine.RowMapping` objects instead of :class:`_engine.Row`
479        objects.
480
481        :return: a new :class:`_asyncio.AsyncMappingResult` filtering object
482         referring to the underlying :class:`_result.Result` object.
483
484        """
485
486        return AsyncMappingResult(self._real_result)
487
488
489class AsyncScalarResult(AsyncCommon[_R]):
490    """A wrapper for a :class:`_asyncio.AsyncResult` that returns scalar values
491    rather than :class:`_row.Row` values.
492
493    The :class:`_asyncio.AsyncScalarResult` object is acquired by calling the
494    :meth:`_asyncio.AsyncResult.scalars` method.
495
496    Refer to the :class:`_result.ScalarResult` object in the synchronous
497    SQLAlchemy API for a complete behavioral description.
498
499    .. versionadded:: 1.4
500
501    """
502
503    __slots__ = ()
504
505    _generate_rows = False
506
507    def __init__(self, real_result: Result[Any], index: _KeyIndexType):
508        self._real_result = real_result
509
510        if real_result._source_supports_scalars:
511            self._metadata = real_result._metadata
512            self._post_creational_filter = None
513        else:
514            self._metadata = real_result._metadata._reduce([index])
515            self._post_creational_filter = operator.itemgetter(0)
516
517        self._unique_filter_state = real_result._unique_filter_state
518
519    def unique(
520        self,
521        strategy: Optional[_UniqueFilterType] = None,
522    ) -> Self:
523        """Apply unique filtering to the objects returned by this
524        :class:`_asyncio.AsyncScalarResult`.
525
526        See :meth:`_asyncio.AsyncResult.unique` for usage details.
527
528        """
529        self._unique_filter_state = (set(), strategy)
530        return self
531
532    async def partitions(
533        self, size: Optional[int] = None
534    ) -> AsyncIterator[Sequence[_R]]:
535        """Iterate through sub-lists of elements of the size given.
536
537        Equivalent to :meth:`_asyncio.AsyncResult.partitions` except that
538        scalar values, rather than :class:`_engine.Row` objects,
539        are returned.
540
541        """
542
543        getter = self._manyrow_getter
544
545        while True:
546            partition = await greenlet_spawn(getter, self, size)
547            if partition:
548                yield partition
549            else:
550                break
551
552    async def fetchall(self) -> Sequence[_R]:
553        """A synonym for the :meth:`_asyncio.AsyncScalarResult.all` method."""
554
555        return await greenlet_spawn(self._allrows)
556
557    async def fetchmany(self, size: Optional[int] = None) -> Sequence[_R]:
558        """Fetch many objects.
559
560        Equivalent to :meth:`_asyncio.AsyncResult.fetchmany` except that
561        scalar values, rather than :class:`_engine.Row` objects,
562        are returned.
563
564        """
565        return await greenlet_spawn(self._manyrow_getter, self, size)
566
567    async def all(self) -> Sequence[_R]:
568        """Return all scalar values in a list.
569
570        Equivalent to :meth:`_asyncio.AsyncResult.all` except that
571        scalar values, rather than :class:`_engine.Row` objects,
572        are returned.
573
574        """
575        return await greenlet_spawn(self._allrows)
576
577    def __aiter__(self) -> AsyncScalarResult[_R]:
578        return self
579
580    async def __anext__(self) -> _R:
581        row = await greenlet_spawn(self._onerow_getter, self)
582        if row is _NO_ROW:
583            raise StopAsyncIteration()
584        else:
585            return row
586
587    async def first(self) -> Optional[_R]:
588        """Fetch the first object or ``None`` if no object is present.
589
590        Equivalent to :meth:`_asyncio.AsyncResult.first` except that
591        scalar values, rather than :class:`_engine.Row` objects,
592        are returned.
593
594        """
595        return await greenlet_spawn(self._only_one_row, False, False, False)
596
597    async def one_or_none(self) -> Optional[_R]:
598        """Return at most one object or raise an exception.
599
600        Equivalent to :meth:`_asyncio.AsyncResult.one_or_none` except that
601        scalar values, rather than :class:`_engine.Row` objects,
602        are returned.
603
604        """
605        return await greenlet_spawn(self._only_one_row, True, False, False)
606
607    async def one(self) -> _R:
608        """Return exactly one object or raise an exception.
609
610        Equivalent to :meth:`_asyncio.AsyncResult.one` except that
611        scalar values, rather than :class:`_engine.Row` objects,
612        are returned.
613
614        """
615        return await greenlet_spawn(self._only_one_row, True, True, False)
616
617
618class AsyncMappingResult(_WithKeys, AsyncCommon[RowMapping]):
619    """A wrapper for a :class:`_asyncio.AsyncResult` that returns dictionary
620    values rather than :class:`_engine.Row` values.
621
622    The :class:`_asyncio.AsyncMappingResult` object is acquired by calling the
623    :meth:`_asyncio.AsyncResult.mappings` method.
624
625    Refer to the :class:`_result.MappingResult` object in the synchronous
626    SQLAlchemy API for a complete behavioral description.
627
628    .. versionadded:: 1.4
629
630    """
631
632    __slots__ = ()
633
634    _generate_rows = True
635
636    _post_creational_filter = operator.attrgetter("_mapping")
637
638    def __init__(self, result: Result[Any]):
639        self._real_result = result
640        self._unique_filter_state = result._unique_filter_state
641        self._metadata = result._metadata
642        if result._source_supports_scalars:
643            self._metadata = self._metadata._reduce([0])
644
645    def unique(
646        self,
647        strategy: Optional[_UniqueFilterType] = None,
648    ) -> Self:
649        """Apply unique filtering to the objects returned by this
650        :class:`_asyncio.AsyncMappingResult`.
651
652        See :meth:`_asyncio.AsyncResult.unique` for usage details.
653
654        """
655        self._unique_filter_state = (set(), strategy)
656        return self
657
658    def columns(self, *col_expressions: _KeyIndexType) -> Self:
659        r"""Establish the columns that should be returned in each row."""
660        return self._column_slices(col_expressions)
661
662    async def partitions(
663        self, size: Optional[int] = None
664    ) -> AsyncIterator[Sequence[RowMapping]]:
665        """Iterate through sub-lists of elements of the size given.
666
667        Equivalent to :meth:`_asyncio.AsyncResult.partitions` except that
668        :class:`_engine.RowMapping` values, rather than :class:`_engine.Row`
669        objects, are returned.
670
671        """
672
673        getter = self._manyrow_getter
674
675        while True:
676            partition = await greenlet_spawn(getter, self, size)
677            if partition:
678                yield partition
679            else:
680                break
681
682    async def fetchall(self) -> Sequence[RowMapping]:
683        """A synonym for the :meth:`_asyncio.AsyncMappingResult.all` method."""
684
685        return await greenlet_spawn(self._allrows)
686
687    async def fetchone(self) -> Optional[RowMapping]:
688        """Fetch one object.
689
690        Equivalent to :meth:`_asyncio.AsyncResult.fetchone` except that
691        :class:`_engine.RowMapping` values, rather than :class:`_engine.Row`
692        objects, are returned.
693
694        """
695
696        row = await greenlet_spawn(self._onerow_getter, self)
697        if row is _NO_ROW:
698            return None
699        else:
700            return row
701
702    async def fetchmany(
703        self, size: Optional[int] = None
704    ) -> Sequence[RowMapping]:
705        """Fetch many rows.
706
707        Equivalent to :meth:`_asyncio.AsyncResult.fetchmany` except that
708        :class:`_engine.RowMapping` values, rather than :class:`_engine.Row`
709        objects, are returned.
710
711        """
712
713        return await greenlet_spawn(self._manyrow_getter, self, size)
714
715    async def all(self) -> Sequence[RowMapping]:
716        """Return all rows in a list.
717
718        Equivalent to :meth:`_asyncio.AsyncResult.all` except that
719        :class:`_engine.RowMapping` values, rather than :class:`_engine.Row`
720        objects, are returned.
721
722        """
723
724        return await greenlet_spawn(self._allrows)
725
726    def __aiter__(self) -> AsyncMappingResult:
727        return self
728
729    async def __anext__(self) -> RowMapping:
730        row = await greenlet_spawn(self._onerow_getter, self)
731        if row is _NO_ROW:
732            raise StopAsyncIteration()
733        else:
734            return row
735
736    async def first(self) -> Optional[RowMapping]:
737        """Fetch the first object or ``None`` if no object is present.
738
739        Equivalent to :meth:`_asyncio.AsyncResult.first` except that
740        :class:`_engine.RowMapping` values, rather than :class:`_engine.Row`
741        objects, are returned.
742
743        """
744        return await greenlet_spawn(self._only_one_row, False, False, False)
745
746    async def one_or_none(self) -> Optional[RowMapping]:
747        """Return at most one object or raise an exception.
748
749        Equivalent to :meth:`_asyncio.AsyncResult.one_or_none` except that
750        :class:`_engine.RowMapping` values, rather than :class:`_engine.Row`
751        objects, are returned.
752
753        """
754        return await greenlet_spawn(self._only_one_row, True, False, False)
755
756    async def one(self) -> RowMapping:
757        """Return exactly one object or raise an exception.
758
759        Equivalent to :meth:`_asyncio.AsyncResult.one` except that
760        :class:`_engine.RowMapping` values, rather than :class:`_engine.Row`
761        objects, are returned.
762
763        """
764        return await greenlet_spawn(self._only_one_row, True, True, False)
765
766
767class AsyncTupleResult(AsyncCommon[_R], util.TypingOnly):
768    """A :class:`_asyncio.AsyncResult` that's typed as returning plain
769    Python tuples instead of rows.
770
771    Since :class:`_engine.Row` acts like a tuple in every way already,
772    this class is a typing only class, regular :class:`_asyncio.AsyncResult` is
773    still used at runtime.
774
775    """
776
777    __slots__ = ()
778
779    if TYPE_CHECKING:
780
781        async def partitions(
782            self, size: Optional[int] = None
783        ) -> AsyncIterator[Sequence[_R]]:
784            """Iterate through sub-lists of elements of the size given.
785
786            Equivalent to :meth:`_result.Result.partitions` except that
787            tuple values, rather than :class:`_engine.Row` objects,
788            are returned.
789
790            """
791            ...
792
793        async def fetchone(self) -> Optional[_R]:
794            """Fetch one tuple.
795
796            Equivalent to :meth:`_result.Result.fetchone` except that
797            tuple values, rather than :class:`_engine.Row`
798            objects, are returned.
799
800            """
801            ...
802
803        async def fetchall(self) -> Sequence[_R]:
804            """A synonym for the :meth:`_engine.ScalarResult.all` method."""
805            ...
806
807        async def fetchmany(self, size: Optional[int] = None) -> Sequence[_R]:
808            """Fetch many objects.
809
810            Equivalent to :meth:`_result.Result.fetchmany` except that
811            tuple values, rather than :class:`_engine.Row` objects,
812            are returned.
813
814            """
815            ...
816
817        async def all(self) -> Sequence[_R]:  # noqa: A001
818            """Return all scalar values in a list.
819
820            Equivalent to :meth:`_result.Result.all` except that
821            tuple values, rather than :class:`_engine.Row` objects,
822            are returned.
823
824            """
825            ...
826
827        async def __aiter__(self) -> AsyncIterator[_R]: ...
828
829        async def __anext__(self) -> _R: ...
830
831        async def first(self) -> Optional[_R]:
832            """Fetch the first object or ``None`` if no object is present.
833
834            Equivalent to :meth:`_result.Result.first` except that
835            tuple values, rather than :class:`_engine.Row` objects,
836            are returned.
837
838
839            """
840            ...
841
842        async def one_or_none(self) -> Optional[_R]:
843            """Return at most one object or raise an exception.
844
845            Equivalent to :meth:`_result.Result.one_or_none` except that
846            tuple values, rather than :class:`_engine.Row` objects,
847            are returned.
848
849            """
850            ...
851
852        async def one(self) -> _R:
853            """Return exactly one object or raise an exception.
854
855            Equivalent to :meth:`_result.Result.one` except that
856            tuple values, rather than :class:`_engine.Row` objects,
857            are returned.
858
859            """
860            ...
861
862        @overload
863        async def scalar_one(self: AsyncTupleResult[Tuple[_T]]) -> _T: ...
864
865        @overload
866        async def scalar_one(self) -> Any: ...
867
868        async def scalar_one(self) -> Any:
869            """Return exactly one scalar result or raise an exception.
870
871            This is equivalent to calling :meth:`_engine.Result.scalars`
872            and then :meth:`_engine.Result.one`.
873
874            .. seealso::
875
876                :meth:`_engine.Result.one`
877
878                :meth:`_engine.Result.scalars`
879
880            """
881            ...
882
883        @overload
884        async def scalar_one_or_none(
885            self: AsyncTupleResult[Tuple[_T]],
886        ) -> Optional[_T]: ...
887
888        @overload
889        async def scalar_one_or_none(self) -> Optional[Any]: ...
890
891        async def scalar_one_or_none(self) -> Optional[Any]:
892            """Return exactly one or no scalar result.
893
894            This is equivalent to calling :meth:`_engine.Result.scalars`
895            and then :meth:`_engine.Result.one_or_none`.
896
897            .. seealso::
898
899                :meth:`_engine.Result.one_or_none`
900
901                :meth:`_engine.Result.scalars`
902
903            """
904            ...
905
906        @overload
907        async def scalar(
908            self: AsyncTupleResult[Tuple[_T]],
909        ) -> Optional[_T]: ...
910
911        @overload
912        async def scalar(self) -> Any: ...
913
914        async def scalar(self) -> Any:
915            """Fetch the first column of the first row, and close the result
916            set.
917
918            Returns ``None`` if there are no rows to fetch.
919
920            No validation is performed to test if additional rows remain.
921
922            After calling this method, the object is fully closed,
923            e.g. the :meth:`_engine.CursorResult.close`
924            method will have been called.
925
926            :return: a Python scalar value , or ``None`` if no rows remain.
927
928            """
929            ...
930
931
932_RT = TypeVar("_RT", bound="Result[Any]")
933
934
935async def _ensure_sync_result(result: _RT, calling_method: Any) -> _RT:
936    cursor_result: CursorResult[Any]
937
938    try:
939        is_cursor = result._is_cursor
940    except AttributeError:
941        # legacy execute(DefaultGenerator) case
942        return result
943
944    if not is_cursor:
945        cursor_result = getattr(result, "raw", None)  # type: ignore
946    else:
947        cursor_result = result  # type: ignore
948    if cursor_result and cursor_result.context._is_server_side:
949        await greenlet_spawn(cursor_result.close)
950        raise async_exc.AsyncMethodRequired(
951            "Can't use the %s.%s() method with a "
952            "server-side cursor. "
953            "Use the %s.stream() method for an async "
954            "streaming result set."
955            % (
956                calling_method.__self__.__class__.__name__,
957                calling_method.__name__,
958                calling_method.__self__.__class__.__name__,
959            )
960        )
961    return result
962 
codekingpro/portable-devtools · Team Ai