Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/sqlalchemy/ext/asyncio/result.py: 44%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

264 statements  

1# ext/asyncio/result.py 

2# Copyright (C) 2020-2025 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._source_supports_scalars = real_result._source_supports_scalars 

97 self._post_creational_filter = None 

98 

99 # BaseCursorResult pre-generates the "_row_getter". Use that 

100 # if available rather than building a second one 

101 if "_row_getter" in real_result.__dict__: 

102 self._set_memoized_attribute( 

103 "_row_getter", real_result.__dict__["_row_getter"] 

104 ) 

105 

106 @property 

107 def t(self) -> AsyncTupleResult[_TP]: 

108 """Apply a "typed tuple" typing filter to returned rows. 

109 

110 The :attr:`_asyncio.AsyncResult.t` attribute is a synonym for 

111 calling the :meth:`_asyncio.AsyncResult.tuples` method. 

112 

113 .. versionadded:: 2.0 

114 

115 """ 

116 return self # type: ignore 

117 

118 def tuples(self) -> AsyncTupleResult[_TP]: 

119 """Apply a "typed tuple" typing filter to returned rows. 

120 

121 This method returns the same :class:`_asyncio.AsyncResult` object 

122 at runtime, 

123 however annotates as returning a :class:`_asyncio.AsyncTupleResult` 

124 object that will indicate to :pep:`484` typing tools that plain typed 

125 ``Tuple`` instances are returned rather than rows. This allows 

126 tuple unpacking and ``__getitem__`` access of :class:`_engine.Row` 

127 objects to by typed, for those cases where the statement invoked 

128 itself included typing information. 

129 

130 .. versionadded:: 2.0 

131 

132 :return: the :class:`_result.AsyncTupleResult` type at typing time. 

133 

134 .. seealso:: 

135 

136 :attr:`_asyncio.AsyncResult.t` - shorter synonym 

137 

138 :attr:`_engine.Row.t` - :class:`_engine.Row` version 

139 

140 """ 

141 

142 return self # type: ignore 

143 

144 @_generative 

145 def unique(self, strategy: Optional[_UniqueFilterType] = None) -> Self: 

146 """Apply unique filtering to the objects returned by this 

147 :class:`_asyncio.AsyncResult`. 

148 

149 Refer to :meth:`_engine.Result.unique` in the synchronous 

150 SQLAlchemy API for a complete behavioral description. 

151 

152 """ 

153 self._unique_filter_state = (set(), strategy) 

154 return self 

155 

156 def columns(self, *col_expressions: _KeyIndexType) -> Self: 

157 r"""Establish the columns that should be returned in each row. 

158 

159 Refer to :meth:`_engine.Result.columns` in the synchronous 

160 SQLAlchemy API for a complete behavioral description. 

161 

162 """ 

163 return self._column_slices(col_expressions) 

164 

165 async def partitions( 

166 self, size: Optional[int] = None 

167 ) -> AsyncIterator[Sequence[Row[_TP]]]: 

168 """Iterate through sub-lists of rows of the size given. 

169 

170 An async iterator is returned:: 

171 

172 async def scroll_results(connection): 

173 result = await connection.stream(select(users_table)) 

174 

175 async for partition in result.partitions(100): 

176 print("list of rows: %s" % partition) 

177 

178 Refer to :meth:`_engine.Result.partitions` in the synchronous 

179 SQLAlchemy API for a complete behavioral description. 

180 

181 """ 

182 

183 getter = self._manyrow_getter 

184 

185 while True: 

186 partition = await greenlet_spawn(getter, self, size) 

187 if partition: 

188 yield partition 

189 else: 

190 break 

191 

192 async def fetchall(self) -> Sequence[Row[_TP]]: 

193 """A synonym for the :meth:`_asyncio.AsyncResult.all` method. 

194 

195 .. versionadded:: 2.0 

196 

197 """ 

198 

199 return await greenlet_spawn(self._allrows) 

200 

201 async def fetchone(self) -> Optional[Row[_TP]]: 

202 """Fetch one row. 

203 

204 When all rows are exhausted, returns None. 

205 

206 This method is provided for backwards compatibility with 

207 SQLAlchemy 1.x.x. 

208 

209 To fetch the first row of a result only, use the 

210 :meth:`_asyncio.AsyncResult.first` method. To iterate through all 

211 rows, iterate the :class:`_asyncio.AsyncResult` object directly. 

212 

213 :return: a :class:`_engine.Row` object if no filters are applied, 

214 or ``None`` if no rows remain. 

215 

216 """ 

217 row = await greenlet_spawn(self._onerow_getter, self) 

218 if row is _NO_ROW: 

219 return None 

220 else: 

221 return row 

222 

223 async def fetchmany( 

224 self, size: Optional[int] = None 

225 ) -> Sequence[Row[_TP]]: 

226 """Fetch many rows. 

227 

228 When all rows are exhausted, returns an empty list. 

229 

230 This method is provided for backwards compatibility with 

231 SQLAlchemy 1.x.x. 

232 

233 To fetch rows in groups, use the 

234 :meth:`._asyncio.AsyncResult.partitions` method. 

235 

236 :return: a list of :class:`_engine.Row` objects. 

237 

238 .. seealso:: 

239 

240 :meth:`_asyncio.AsyncResult.partitions` 

241 

242 """ 

243 

244 return await greenlet_spawn(self._manyrow_getter, self, size) 

245 

246 async def all(self) -> Sequence[Row[_TP]]: 

247 """Return all rows in a list. 

248 

249 Closes the result set after invocation. Subsequent invocations 

250 will return an empty list. 

251 

252 :return: a list of :class:`_engine.Row` objects. 

253 

254 """ 

255 

256 return await greenlet_spawn(self._allrows) 

257 

258 def __aiter__(self) -> AsyncResult[_TP]: 

259 return self 

260 

261 async def __anext__(self) -> Row[_TP]: 

262 row = await greenlet_spawn(self._onerow_getter, self) 

263 if row is _NO_ROW: 

264 raise StopAsyncIteration() 

265 else: 

266 return row 

267 

268 async def first(self) -> Optional[Row[_TP]]: 

269 """Fetch the first row or ``None`` if no row is present. 

270 

271 Closes the result set and discards remaining rows. 

272 

273 .. note:: This method returns one **row**, e.g. tuple, by default. 

274 To return exactly one single scalar value, that is, the first 

275 column of the first row, use the 

276 :meth:`_asyncio.AsyncResult.scalar` method, 

277 or combine :meth:`_asyncio.AsyncResult.scalars` and 

278 :meth:`_asyncio.AsyncResult.first`. 

279 

280 Additionally, in contrast to the behavior of the legacy ORM 

281 :meth:`_orm.Query.first` method, **no limit is applied** to the 

282 SQL query which was invoked to produce this 

283 :class:`_asyncio.AsyncResult`; 

284 for a DBAPI driver that buffers results in memory before yielding 

285 rows, all rows will be sent to the Python process and all but 

286 the first row will be discarded. 

287 

288 .. seealso:: 

289 

290 :ref:`migration_20_unify_select` 

291 

292 :return: a :class:`_engine.Row` object, or None 

293 if no rows remain. 

294 

295 .. seealso:: 

296 

297 :meth:`_asyncio.AsyncResult.scalar` 

298 

299 :meth:`_asyncio.AsyncResult.one` 

300 

301 """ 

302 return await greenlet_spawn(self._only_one_row, False, False, False) 

303 

304 async def one_or_none(self) -> Optional[Row[_TP]]: 

305 """Return at most one result or raise an exception. 

306 

307 Returns ``None`` if the result has no rows. 

308 Raises :class:`.MultipleResultsFound` 

309 if multiple rows are returned. 

310 

311 .. versionadded:: 1.4 

312 

313 :return: The first :class:`_engine.Row` or ``None`` if no row 

314 is available. 

315 

316 :raises: :class:`.MultipleResultsFound` 

317 

318 .. seealso:: 

319 

320 :meth:`_asyncio.AsyncResult.first` 

321 

322 :meth:`_asyncio.AsyncResult.one` 

323 

324 """ 

325 return await greenlet_spawn(self._only_one_row, True, False, False) 

326 

327 @overload 

328 async def scalar_one(self: AsyncResult[Tuple[_T]]) -> _T: ... 

329 

330 @overload 

331 async def scalar_one(self) -> Any: ... 

332 

333 async def scalar_one(self) -> Any: 

334 """Return exactly one scalar result or raise an exception. 

335 

336 This is equivalent to calling :meth:`_asyncio.AsyncResult.scalars` and 

337 then :meth:`_asyncio.AsyncScalarResult.one`. 

338 

339 .. seealso:: 

340 

341 :meth:`_asyncio.AsyncScalarResult.one` 

342 

343 :meth:`_asyncio.AsyncResult.scalars` 

344 

345 """ 

346 return await greenlet_spawn(self._only_one_row, True, True, True) 

347 

348 @overload 

349 async def scalar_one_or_none( 

350 self: AsyncResult[Tuple[_T]], 

351 ) -> Optional[_T]: ... 

352 

353 @overload 

354 async def scalar_one_or_none(self) -> Optional[Any]: ... 

355 

356 async def scalar_one_or_none(self) -> Optional[Any]: 

357 """Return exactly one scalar result or ``None``. 

358 

359 This is equivalent to calling :meth:`_asyncio.AsyncResult.scalars` and 

360 then :meth:`_asyncio.AsyncScalarResult.one_or_none`. 

361 

362 .. seealso:: 

363 

364 :meth:`_asyncio.AsyncScalarResult.one_or_none` 

365 

366 :meth:`_asyncio.AsyncResult.scalars` 

367 

368 """ 

369 return await greenlet_spawn(self._only_one_row, True, False, True) 

370 

371 async def one(self) -> Row[_TP]: 

372 """Return exactly one row or raise an exception. 

373 

374 Raises :class:`.NoResultFound` if the result returns no 

375 rows, or :class:`.MultipleResultsFound` if multiple rows 

376 would be returned. 

377 

378 .. note:: This method returns one **row**, e.g. tuple, by default. 

379 To return exactly one single scalar value, that is, the first 

380 column of the first row, use the 

381 :meth:`_asyncio.AsyncResult.scalar_one` method, or combine 

382 :meth:`_asyncio.AsyncResult.scalars` and 

383 :meth:`_asyncio.AsyncResult.one`. 

384 

385 .. versionadded:: 1.4 

386 

387 :return: The first :class:`_engine.Row`. 

388 

389 :raises: :class:`.MultipleResultsFound`, :class:`.NoResultFound` 

390 

391 .. seealso:: 

392 

393 :meth:`_asyncio.AsyncResult.first` 

394 

395 :meth:`_asyncio.AsyncResult.one_or_none` 

396 

397 :meth:`_asyncio.AsyncResult.scalar_one` 

398 

399 """ 

400 return await greenlet_spawn(self._only_one_row, True, True, False) 

401 

402 @overload 

403 async def scalar(self: AsyncResult[Tuple[_T]]) -> Optional[_T]: ... 

404 

405 @overload 

406 async def scalar(self) -> Any: ... 

407 

408 async def scalar(self) -> Any: 

409 """Fetch the first column of the first row, and close the result set. 

410 

411 Returns ``None`` if there are no rows to fetch. 

412 

413 No validation is performed to test if additional rows remain. 

414 

415 After calling this method, the object is fully closed, 

416 e.g. the :meth:`_engine.CursorResult.close` 

417 method will have been called. 

418 

419 :return: a Python scalar value, or ``None`` if no rows remain. 

420 

421 """ 

422 return await greenlet_spawn(self._only_one_row, False, False, True) 

423 

424 async def freeze(self) -> FrozenResult[_TP]: 

425 """Return a callable object that will produce copies of this 

426 :class:`_asyncio.AsyncResult` when invoked. 

427 

428 The callable object returned is an instance of 

429 :class:`_engine.FrozenResult`. 

430 

431 This is used for result set caching. The method must be called 

432 on the result when it has been unconsumed, and calling the method 

433 will consume the result fully. When the :class:`_engine.FrozenResult` 

434 is retrieved from a cache, it can be called any number of times where 

435 it will produce a new :class:`_engine.Result` object each time 

436 against its stored set of rows. 

437 

438 .. seealso:: 

439 

440 :ref:`do_orm_execute_re_executing` - example usage within the 

441 ORM to implement a result-set cache. 

442 

443 """ 

444 

445 return await greenlet_spawn(FrozenResult, self) 

446 

447 @overload 

448 def scalars( 

449 self: AsyncResult[Tuple[_T]], index: Literal[0] 

450 ) -> AsyncScalarResult[_T]: ... 

451 

452 @overload 

453 def scalars(self: AsyncResult[Tuple[_T]]) -> AsyncScalarResult[_T]: ... 

454 

455 @overload 

456 def scalars(self, index: _KeyIndexType = 0) -> AsyncScalarResult[Any]: ... 

457 

458 def scalars(self, index: _KeyIndexType = 0) -> AsyncScalarResult[Any]: 

459 """Return an :class:`_asyncio.AsyncScalarResult` filtering object which 

460 will return single elements rather than :class:`_row.Row` objects. 

461 

462 Refer to :meth:`_result.Result.scalars` in the synchronous 

463 SQLAlchemy API for a complete behavioral description. 

464 

465 :param index: integer or row key indicating the column to be fetched 

466 from each row, defaults to ``0`` indicating the first column. 

467 

468 :return: a new :class:`_asyncio.AsyncScalarResult` filtering object 

469 referring to this :class:`_asyncio.AsyncResult` object. 

470 

471 """ 

472 return AsyncScalarResult(self._real_result, index) 

473 

474 def mappings(self) -> AsyncMappingResult: 

475 """Apply a mappings filter to returned rows, returning an instance of 

476 :class:`_asyncio.AsyncMappingResult`. 

477 

478 When this filter is applied, fetching rows will return 

479 :class:`_engine.RowMapping` objects instead of :class:`_engine.Row` 

480 objects. 

481 

482 :return: a new :class:`_asyncio.AsyncMappingResult` filtering object 

483 referring to the underlying :class:`_result.Result` object. 

484 

485 """ 

486 

487 return AsyncMappingResult(self._real_result) 

488 

489 

490class AsyncScalarResult(AsyncCommon[_R]): 

491 """A wrapper for a :class:`_asyncio.AsyncResult` that returns scalar values 

492 rather than :class:`_row.Row` values. 

493 

494 The :class:`_asyncio.AsyncScalarResult` object is acquired by calling the 

495 :meth:`_asyncio.AsyncResult.scalars` method. 

496 

497 Refer to the :class:`_result.ScalarResult` object in the synchronous 

498 SQLAlchemy API for a complete behavioral description. 

499 

500 .. versionadded:: 1.4 

501 

502 """ 

503 

504 __slots__ = () 

505 

506 _generate_rows = False 

507 

508 def __init__(self, real_result: Result[Any], index: _KeyIndexType): 

509 self._real_result = real_result 

510 

511 if real_result._source_supports_scalars: 

512 self._metadata = real_result._metadata 

513 self._post_creational_filter = None 

514 else: 

515 self._metadata = real_result._metadata._reduce([index]) 

516 self._post_creational_filter = operator.itemgetter(0) 

517 

518 self._unique_filter_state = real_result._unique_filter_state 

519 

520 def unique( 

521 self, 

522 strategy: Optional[_UniqueFilterType] = None, 

523 ) -> Self: 

524 """Apply unique filtering to the objects returned by this 

525 :class:`_asyncio.AsyncScalarResult`. 

526 

527 See :meth:`_asyncio.AsyncResult.unique` for usage details. 

528 

529 """ 

530 self._unique_filter_state = (set(), strategy) 

531 return self 

532 

533 async def partitions( 

534 self, size: Optional[int] = None 

535 ) -> AsyncIterator[Sequence[_R]]: 

536 """Iterate through sub-lists of elements of the size given. 

537 

538 Equivalent to :meth:`_asyncio.AsyncResult.partitions` except that 

539 scalar values, rather than :class:`_engine.Row` objects, 

540 are returned. 

541 

542 """ 

543 

544 getter = self._manyrow_getter 

545 

546 while True: 

547 partition = await greenlet_spawn(getter, self, size) 

548 if partition: 

549 yield partition 

550 else: 

551 break 

552 

553 async def fetchall(self) -> Sequence[_R]: 

554 """A synonym for the :meth:`_asyncio.AsyncScalarResult.all` method.""" 

555 

556 return await greenlet_spawn(self._allrows) 

557 

558 async def fetchmany(self, size: Optional[int] = None) -> Sequence[_R]: 

559 """Fetch many objects. 

560 

561 Equivalent to :meth:`_asyncio.AsyncResult.fetchmany` except that 

562 scalar values, rather than :class:`_engine.Row` objects, 

563 are returned. 

564 

565 """ 

566 return await greenlet_spawn(self._manyrow_getter, self, size) 

567 

568 async def all(self) -> Sequence[_R]: 

569 """Return all scalar values in a list. 

570 

571 Equivalent to :meth:`_asyncio.AsyncResult.all` except that 

572 scalar values, rather than :class:`_engine.Row` objects, 

573 are returned. 

574 

575 """ 

576 return await greenlet_spawn(self._allrows) 

577 

578 def __aiter__(self) -> AsyncScalarResult[_R]: 

579 return self 

580 

581 async def __anext__(self) -> _R: 

582 row = await greenlet_spawn(self._onerow_getter, self) 

583 if row is _NO_ROW: 

584 raise StopAsyncIteration() 

585 else: 

586 return row 

587 

588 async def first(self) -> Optional[_R]: 

589 """Fetch the first object or ``None`` if no object is present. 

590 

591 Equivalent to :meth:`_asyncio.AsyncResult.first` except that 

592 scalar values, rather than :class:`_engine.Row` objects, 

593 are returned. 

594 

595 """ 

596 return await greenlet_spawn(self._only_one_row, False, False, False) 

597 

598 async def one_or_none(self) -> Optional[_R]: 

599 """Return at most one object or raise an exception. 

600 

601 Equivalent to :meth:`_asyncio.AsyncResult.one_or_none` except that 

602 scalar values, rather than :class:`_engine.Row` objects, 

603 are returned. 

604 

605 """ 

606 return await greenlet_spawn(self._only_one_row, True, False, False) 

607 

608 async def one(self) -> _R: 

609 """Return exactly one object or raise an exception. 

610 

611 Equivalent to :meth:`_asyncio.AsyncResult.one` except that 

612 scalar values, rather than :class:`_engine.Row` objects, 

613 are returned. 

614 

615 """ 

616 return await greenlet_spawn(self._only_one_row, True, True, False) 

617 

618 

619class AsyncMappingResult(_WithKeys, AsyncCommon[RowMapping]): 

620 """A wrapper for a :class:`_asyncio.AsyncResult` that returns dictionary 

621 values rather than :class:`_engine.Row` values. 

622 

623 The :class:`_asyncio.AsyncMappingResult` object is acquired by calling the 

624 :meth:`_asyncio.AsyncResult.mappings` method. 

625 

626 Refer to the :class:`_result.MappingResult` object in the synchronous 

627 SQLAlchemy API for a complete behavioral description. 

628 

629 .. versionadded:: 1.4 

630 

631 """ 

632 

633 __slots__ = () 

634 

635 _generate_rows = True 

636 

637 _post_creational_filter = operator.attrgetter("_mapping") 

638 

639 def __init__(self, result: Result[Any]): 

640 self._real_result = result 

641 self._unique_filter_state = result._unique_filter_state 

642 self._metadata = result._metadata 

643 if result._source_supports_scalars: 

644 self._metadata = self._metadata._reduce([0]) 

645 

646 def unique( 

647 self, 

648 strategy: Optional[_UniqueFilterType] = None, 

649 ) -> Self: 

650 """Apply unique filtering to the objects returned by this 

651 :class:`_asyncio.AsyncMappingResult`. 

652 

653 See :meth:`_asyncio.AsyncResult.unique` for usage details. 

654 

655 """ 

656 self._unique_filter_state = (set(), strategy) 

657 return self 

658 

659 def columns(self, *col_expressions: _KeyIndexType) -> Self: 

660 r"""Establish the columns that should be returned in each row.""" 

661 return self._column_slices(col_expressions) 

662 

663 async def partitions( 

664 self, size: Optional[int] = None 

665 ) -> AsyncIterator[Sequence[RowMapping]]: 

666 """Iterate through sub-lists of elements of the size given. 

667 

668 Equivalent to :meth:`_asyncio.AsyncResult.partitions` except that 

669 :class:`_engine.RowMapping` values, rather than :class:`_engine.Row` 

670 objects, are returned. 

671 

672 """ 

673 

674 getter = self._manyrow_getter 

675 

676 while True: 

677 partition = await greenlet_spawn(getter, self, size) 

678 if partition: 

679 yield partition 

680 else: 

681 break 

682 

683 async def fetchall(self) -> Sequence[RowMapping]: 

684 """A synonym for the :meth:`_asyncio.AsyncMappingResult.all` method.""" 

685 

686 return await greenlet_spawn(self._allrows) 

687 

688 async def fetchone(self) -> Optional[RowMapping]: 

689 """Fetch one object. 

690 

691 Equivalent to :meth:`_asyncio.AsyncResult.fetchone` except that 

692 :class:`_engine.RowMapping` values, rather than :class:`_engine.Row` 

693 objects, are returned. 

694 

695 """ 

696 

697 row = await greenlet_spawn(self._onerow_getter, self) 

698 if row is _NO_ROW: 

699 return None 

700 else: 

701 return row 

702 

703 async def fetchmany( 

704 self, size: Optional[int] = None 

705 ) -> Sequence[RowMapping]: 

706 """Fetch many rows. 

707 

708 Equivalent to :meth:`_asyncio.AsyncResult.fetchmany` except that 

709 :class:`_engine.RowMapping` values, rather than :class:`_engine.Row` 

710 objects, are returned. 

711 

712 """ 

713 

714 return await greenlet_spawn(self._manyrow_getter, self, size) 

715 

716 async def all(self) -> Sequence[RowMapping]: 

717 """Return all rows in a list. 

718 

719 Equivalent to :meth:`_asyncio.AsyncResult.all` except that 

720 :class:`_engine.RowMapping` values, rather than :class:`_engine.Row` 

721 objects, are returned. 

722 

723 """ 

724 

725 return await greenlet_spawn(self._allrows) 

726 

727 def __aiter__(self) -> AsyncMappingResult: 

728 return self 

729 

730 async def __anext__(self) -> RowMapping: 

731 row = await greenlet_spawn(self._onerow_getter, self) 

732 if row is _NO_ROW: 

733 raise StopAsyncIteration() 

734 else: 

735 return row 

736 

737 async def first(self) -> Optional[RowMapping]: 

738 """Fetch the first object or ``None`` if no object is present. 

739 

740 Equivalent to :meth:`_asyncio.AsyncResult.first` except that 

741 :class:`_engine.RowMapping` values, rather than :class:`_engine.Row` 

742 objects, are returned. 

743 

744 """ 

745 return await greenlet_spawn(self._only_one_row, False, False, False) 

746 

747 async def one_or_none(self) -> Optional[RowMapping]: 

748 """Return at most one object or raise an exception. 

749 

750 Equivalent to :meth:`_asyncio.AsyncResult.one_or_none` except that 

751 :class:`_engine.RowMapping` values, rather than :class:`_engine.Row` 

752 objects, are returned. 

753 

754 """ 

755 return await greenlet_spawn(self._only_one_row, True, False, False) 

756 

757 async def one(self) -> RowMapping: 

758 """Return exactly one object or raise an exception. 

759 

760 Equivalent to :meth:`_asyncio.AsyncResult.one` except that 

761 :class:`_engine.RowMapping` values, rather than :class:`_engine.Row` 

762 objects, are returned. 

763 

764 """ 

765 return await greenlet_spawn(self._only_one_row, True, True, False) 

766 

767 

768class AsyncTupleResult(AsyncCommon[_R], util.TypingOnly): 

769 """A :class:`_asyncio.AsyncResult` that's typed as returning plain 

770 Python tuples instead of rows. 

771 

772 Since :class:`_engine.Row` acts like a tuple in every way already, 

773 this class is a typing only class, regular :class:`_asyncio.AsyncResult` is 

774 still used at runtime. 

775 

776 """ 

777 

778 __slots__ = () 

779 

780 if TYPE_CHECKING: 

781 

782 async def partitions( 

783 self, size: Optional[int] = None 

784 ) -> AsyncIterator[Sequence[_R]]: 

785 """Iterate through sub-lists of elements of the size given. 

786 

787 Equivalent to :meth:`_result.Result.partitions` except that 

788 tuple values, rather than :class:`_engine.Row` objects, 

789 are returned. 

790 

791 """ 

792 ... 

793 

794 async def fetchone(self) -> Optional[_R]: 

795 """Fetch one tuple. 

796 

797 Equivalent to :meth:`_result.Result.fetchone` except that 

798 tuple values, rather than :class:`_engine.Row` 

799 objects, are returned. 

800 

801 """ 

802 ... 

803 

804 async def fetchall(self) -> Sequence[_R]: 

805 """A synonym for the :meth:`_engine.ScalarResult.all` method.""" 

806 ... 

807 

808 async def fetchmany(self, size: Optional[int] = None) -> Sequence[_R]: 

809 """Fetch many objects. 

810 

811 Equivalent to :meth:`_result.Result.fetchmany` except that 

812 tuple values, rather than :class:`_engine.Row` objects, 

813 are returned. 

814 

815 """ 

816 ... 

817 

818 async def all(self) -> Sequence[_R]: # noqa: A001 

819 """Return all scalar values in a list. 

820 

821 Equivalent to :meth:`_result.Result.all` except that 

822 tuple values, rather than :class:`_engine.Row` objects, 

823 are returned. 

824 

825 """ 

826 ... 

827 

828 def __aiter__(self) -> AsyncIterator[_R]: ... 

829 

830 async def __anext__(self) -> _R: ... 

831 

832 async def first(self) -> Optional[_R]: 

833 """Fetch the first object or ``None`` if no object is present. 

834 

835 Equivalent to :meth:`_result.Result.first` except that 

836 tuple values, rather than :class:`_engine.Row` objects, 

837 are returned. 

838 

839 

840 """ 

841 ... 

842 

843 async def one_or_none(self) -> Optional[_R]: 

844 """Return at most one object or raise an exception. 

845 

846 Equivalent to :meth:`_result.Result.one_or_none` except that 

847 tuple values, rather than :class:`_engine.Row` objects, 

848 are returned. 

849 

850 """ 

851 ... 

852 

853 async def one(self) -> _R: 

854 """Return exactly one object or raise an exception. 

855 

856 Equivalent to :meth:`_result.Result.one` except that 

857 tuple values, rather than :class:`_engine.Row` objects, 

858 are returned. 

859 

860 """ 

861 ... 

862 

863 @overload 

864 async def scalar_one(self: AsyncTupleResult[Tuple[_T]]) -> _T: ... 

865 

866 @overload 

867 async def scalar_one(self) -> Any: ... 

868 

869 async def scalar_one(self) -> Any: 

870 """Return exactly one scalar result or raise an exception. 

871 

872 This is equivalent to calling :meth:`_engine.Result.scalars` 

873 and then :meth:`_engine.AsyncScalarResult.one`. 

874 

875 .. seealso:: 

876 

877 :meth:`_engine.AsyncScalarResult.one` 

878 

879 :meth:`_engine.Result.scalars` 

880 

881 """ 

882 ... 

883 

884 @overload 

885 async def scalar_one_or_none( 

886 self: AsyncTupleResult[Tuple[_T]], 

887 ) -> Optional[_T]: ... 

888 

889 @overload 

890 async def scalar_one_or_none(self) -> Optional[Any]: ... 

891 

892 async def scalar_one_or_none(self) -> Optional[Any]: 

893 """Return exactly one or no scalar result. 

894 

895 This is equivalent to calling :meth:`_engine.Result.scalars` 

896 and then :meth:`_engine.AsyncScalarResult.one_or_none`. 

897 

898 .. seealso:: 

899 

900 :meth:`_engine.AsyncScalarResult.one_or_none` 

901 

902 :meth:`_engine.Result.scalars` 

903 

904 """ 

905 ... 

906 

907 @overload 

908 async def scalar( 

909 self: AsyncTupleResult[Tuple[_T]], 

910 ) -> Optional[_T]: ... 

911 

912 @overload 

913 async def scalar(self) -> Any: ... 

914 

915 async def scalar(self) -> Any: 

916 """Fetch the first column of the first row, and close the result 

917 set. 

918 

919 Returns ``None`` if there are no rows to fetch. 

920 

921 No validation is performed to test if additional rows remain. 

922 

923 After calling this method, the object is fully closed, 

924 e.g. the :meth:`_engine.CursorResult.close` 

925 method will have been called. 

926 

927 :return: a Python scalar value , or ``None`` if no rows remain. 

928 

929 """ 

930 ... 

931 

932 

933_RT = TypeVar("_RT", bound="Result[Any]") 

934 

935 

936async def _ensure_sync_result(result: _RT, calling_method: Any) -> _RT: 

937 cursor_result: CursorResult[Any] 

938 

939 try: 

940 is_cursor = result._is_cursor 

941 except AttributeError: 

942 # legacy execute(DefaultGenerator) case 

943 return result 

944 

945 if not is_cursor: 

946 cursor_result = getattr(result, "raw", None) # type: ignore 

947 else: 

948 cursor_result = result # type: ignore 

949 if cursor_result and cursor_result.context._is_server_side: 

950 await greenlet_spawn(cursor_result.close) 

951 raise async_exc.AsyncMethodRequired( 

952 "Can't use the %s.%s() method with a " 

953 "server-side cursor. " 

954 "Use the %s.stream() method for an async " 

955 "streaming result set." 

956 % ( 

957 calling_method.__self__.__class__.__name__, 

958 calling_method.__name__, 

959 calling_method.__self__.__class__.__name__, 

960 ) 

961 ) 

962 

963 if is_cursor and cursor_result.cursor is not None: 

964 await cursor_result.cursor._async_soft_close() 

965 return result