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

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

207 statements  

1# ext/asyncio/scoping.py 

2# Copyright (C) 2005-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 

7 

8from __future__ import annotations 

9 

10from typing import Any 

11from typing import Callable 

12from typing import Generic 

13from typing import Iterable 

14from typing import Iterator 

15from typing import Optional 

16from typing import overload 

17from typing import Sequence 

18from typing import Tuple 

19from typing import Type 

20from typing import TYPE_CHECKING 

21from typing import TypeVar 

22from typing import Union 

23 

24from .session import _AS 

25from .session import async_sessionmaker 

26from .session import AsyncSession 

27from ... import exc as sa_exc 

28from ... import util 

29from ...orm.session import Session 

30from ...util import create_proxy_methods 

31from ...util import ScopedRegistry 

32from ...util import warn 

33from ...util import warn_deprecated 

34 

35if TYPE_CHECKING: 

36 from .engine import AsyncConnection 

37 from .result import AsyncResult 

38 from .result import AsyncScalarResult 

39 from .session import AsyncSessionTransaction 

40 from ...engine import Connection 

41 from ...engine import Engine 

42 from ...engine import Result 

43 from ...engine import Row 

44 from ...engine import RowMapping 

45 from ...engine.interfaces import _CoreAnyExecuteParams 

46 from ...engine.interfaces import CoreExecuteOptionsParameter 

47 from ...engine.result import ScalarResult 

48 from ...orm._typing import _IdentityKeyType 

49 from ...orm._typing import _O 

50 from ...orm._typing import OrmExecuteOptionsParameter 

51 from ...orm.interfaces import ORMOption 

52 from ...orm.session import _BindArguments 

53 from ...orm.session import _EntityBindKey 

54 from ...orm.session import _PKIdentityArgument 

55 from ...orm.session import _SessionBind 

56 from ...sql.base import Executable 

57 from ...sql.elements import ClauseElement 

58 from ...sql.selectable import ForUpdateParameter 

59 from ...sql.selectable import TypedReturnsRows 

60 

61_T = TypeVar("_T", bound=Any) 

62 

63 

64@create_proxy_methods( 

65 AsyncSession, 

66 ":class:`_asyncio.AsyncSession`", 

67 ":class:`_asyncio.scoping.async_scoped_session`", 

68 classmethods=["close_all", "object_session", "identity_key"], 

69 methods=[ 

70 "__contains__", 

71 "__iter__", 

72 "aclose", 

73 "add", 

74 "add_all", 

75 "begin", 

76 "begin_nested", 

77 "close", 

78 "reset", 

79 "commit", 

80 "connection", 

81 "delete", 

82 "execute", 

83 "expire", 

84 "expire_all", 

85 "expunge", 

86 "expunge_all", 

87 "flush", 

88 "get_bind", 

89 "is_modified", 

90 "invalidate", 

91 "merge", 

92 "refresh", 

93 "rollback", 

94 "scalar", 

95 "scalars", 

96 "get", 

97 "get_one", 

98 "stream", 

99 "stream_scalars", 

100 ], 

101 attributes=[ 

102 "bind", 

103 "dirty", 

104 "deleted", 

105 "new", 

106 "identity_map", 

107 "is_active", 

108 "autoflush", 

109 "no_autoflush", 

110 "info", 

111 ], 

112 use_intermediate_variable=["get"], 

113) 

114class async_scoped_session(Generic[_AS]): 

115 """Provides scoped management of :class:`.AsyncSession` objects. 

116 

117 See the section :ref:`asyncio_scoped_session` for usage details. 

118 

119 .. versionadded:: 1.4.19 

120 

121 

122 """ 

123 

124 _support_async = True 

125 

126 session_factory: async_sessionmaker[_AS] 

127 """The `session_factory` provided to `__init__` is stored in this 

128 attribute and may be accessed at a later time. This can be useful when 

129 a new non-scoped :class:`.AsyncSession` is needed.""" 

130 

131 registry: ScopedRegistry[_AS] 

132 

133 def __init__( 

134 self, 

135 session_factory: async_sessionmaker[_AS], 

136 scopefunc: Callable[[], Any], 

137 ): 

138 """Construct a new :class:`_asyncio.async_scoped_session`. 

139 

140 :param session_factory: a factory to create new :class:`_asyncio.AsyncSession` 

141 instances. This is usually, but not necessarily, an instance 

142 of :class:`_asyncio.async_sessionmaker`. 

143 

144 :param scopefunc: function which defines 

145 the current scope. A function such as ``asyncio.current_task`` 

146 may be useful here. 

147 

148 """ # noqa: E501 

149 

150 self.session_factory = session_factory 

151 self.registry = ScopedRegistry(session_factory, scopefunc) 

152 

153 @property 

154 def _proxied(self) -> _AS: 

155 return self.registry() 

156 

157 def __call__(self, **kw: Any) -> _AS: 

158 r"""Return the current :class:`.AsyncSession`, creating it 

159 using the :attr:`.scoped_session.session_factory` if not present. 

160 

161 :param \**kw: Keyword arguments will be passed to the 

162 :attr:`.scoped_session.session_factory` callable, if an existing 

163 :class:`.AsyncSession` is not present. If the 

164 :class:`.AsyncSession` is present 

165 and keyword arguments have been passed, 

166 :exc:`~sqlalchemy.exc.InvalidRequestError` is raised. 

167 

168 """ 

169 if kw: 

170 if self.registry.has(): 

171 raise sa_exc.InvalidRequestError( 

172 "Scoped session is already present; " 

173 "no new arguments may be specified." 

174 ) 

175 else: 

176 sess = self.session_factory(**kw) 

177 self.registry.set(sess) 

178 else: 

179 sess = self.registry() 

180 if not self._support_async and sess._is_asyncio: 

181 warn_deprecated( 

182 "Using `scoped_session` with asyncio is deprecated and " 

183 "will raise an error in a future version. " 

184 "Please use `async_scoped_session` instead.", 

185 "1.4.23", 

186 ) 

187 return sess 

188 

189 def configure(self, **kwargs: Any) -> None: 

190 """reconfigure the :class:`.sessionmaker` used by this 

191 :class:`.scoped_session`. 

192 

193 See :meth:`.sessionmaker.configure`. 

194 

195 """ 

196 

197 if self.registry.has(): 

198 warn( 

199 "At least one scoped session is already present. " 

200 " configure() can not affect sessions that have " 

201 "already been created." 

202 ) 

203 

204 self.session_factory.configure(**kwargs) 

205 

206 async def remove(self) -> None: 

207 """Dispose of the current :class:`.AsyncSession`, if present. 

208 

209 Different from scoped_session's remove method, this method would use 

210 await to wait for the close method of AsyncSession. 

211 

212 """ 

213 

214 if self.registry.has(): 

215 await self.registry().close() 

216 self.registry.clear() 

217 

218 # START PROXY METHODS async_scoped_session 

219 

220 # code within this block is **programmatically, 

221 # statically generated** by tools/generate_proxy_methods.py 

222 

223 def __contains__(self, instance: object) -> bool: 

224 r"""Return True if the instance is associated with this session. 

225 

226 .. container:: class_bases 

227 

228 Proxied for the :class:`_asyncio.AsyncSession` class on 

229 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

230 

231 .. container:: class_bases 

232 

233 Proxied for the :class:`_orm.Session` class on 

234 behalf of the :class:`_asyncio.AsyncSession` class. 

235 

236 The instance may be pending or persistent within the Session for a 

237 result of True. 

238 

239 

240 

241 """ # noqa: E501 

242 

243 return self._proxied.__contains__(instance) 

244 

245 def __iter__(self) -> Iterator[object]: 

246 r"""Iterate over all pending or persistent instances within this 

247 Session. 

248 

249 .. container:: class_bases 

250 

251 Proxied for the :class:`_asyncio.AsyncSession` class on 

252 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

253 

254 .. container:: class_bases 

255 

256 Proxied for the :class:`_orm.Session` class on 

257 behalf of the :class:`_asyncio.AsyncSession` class. 

258 

259 

260 

261 """ # noqa: E501 

262 

263 return self._proxied.__iter__() 

264 

265 async def aclose(self) -> None: 

266 r"""A synonym for :meth:`_asyncio.AsyncSession.close`. 

267 

268 .. container:: class_bases 

269 

270 Proxied for the :class:`_asyncio.AsyncSession` class on 

271 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

272 

273 The :meth:`_asyncio.AsyncSession.aclose` name is specifically 

274 to support the Python standard library ``@contextlib.aclosing`` 

275 context manager function. 

276 

277 .. versionadded:: 2.0.20 

278 

279 

280 """ # noqa: E501 

281 

282 return await self._proxied.aclose() 

283 

284 def add(self, instance: object, _warn: bool = True) -> None: 

285 r"""Place an object into this :class:`_orm.Session`. 

286 

287 .. container:: class_bases 

288 

289 Proxied for the :class:`_asyncio.AsyncSession` class on 

290 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

291 

292 .. container:: class_bases 

293 

294 Proxied for the :class:`_orm.Session` class on 

295 behalf of the :class:`_asyncio.AsyncSession` class. 

296 

297 Objects that are in the :term:`transient` state when passed to the 

298 :meth:`_orm.Session.add` method will move to the 

299 :term:`pending` state, until the next flush, at which point they 

300 will move to the :term:`persistent` state. 

301 

302 Objects that are in the :term:`detached` state when passed to the 

303 :meth:`_orm.Session.add` method will move to the :term:`persistent` 

304 state directly. 

305 

306 If the transaction used by the :class:`_orm.Session` is rolled back, 

307 objects which were transient when they were passed to 

308 :meth:`_orm.Session.add` will be moved back to the 

309 :term:`transient` state, and will no longer be present within this 

310 :class:`_orm.Session`. 

311 

312 .. seealso:: 

313 

314 :meth:`_orm.Session.add_all` 

315 

316 :ref:`session_adding` - at :ref:`session_basics` 

317 

318 

319 

320 """ # noqa: E501 

321 

322 return self._proxied.add(instance, _warn=_warn) 

323 

324 def add_all(self, instances: Iterable[object]) -> None: 

325 r"""Add the given collection of instances to this :class:`_orm.Session`. 

326 

327 .. container:: class_bases 

328 

329 Proxied for the :class:`_asyncio.AsyncSession` class on 

330 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

331 

332 .. container:: class_bases 

333 

334 Proxied for the :class:`_orm.Session` class on 

335 behalf of the :class:`_asyncio.AsyncSession` class. 

336 

337 See the documentation for :meth:`_orm.Session.add` for a general 

338 behavioral description. 

339 

340 .. seealso:: 

341 

342 :meth:`_orm.Session.add` 

343 

344 :ref:`session_adding` - at :ref:`session_basics` 

345 

346 

347 

348 """ # noqa: E501 

349 

350 return self._proxied.add_all(instances) 

351 

352 def begin(self) -> AsyncSessionTransaction: 

353 r"""Return an :class:`_asyncio.AsyncSessionTransaction` object. 

354 

355 .. container:: class_bases 

356 

357 Proxied for the :class:`_asyncio.AsyncSession` class on 

358 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

359 

360 The underlying :class:`_orm.Session` will perform the 

361 "begin" action when the :class:`_asyncio.AsyncSessionTransaction` 

362 object is entered:: 

363 

364 async with async_session.begin(): 

365 ... # ORM transaction is begun 

366 

367 Note that database IO will not normally occur when the session-level 

368 transaction is begun, as database transactions begin on an 

369 on-demand basis. However, the begin block is async to accommodate 

370 for a :meth:`_orm.SessionEvents.after_transaction_create` 

371 event hook that may perform IO. 

372 

373 For a general description of ORM begin, see 

374 :meth:`_orm.Session.begin`. 

375 

376 

377 """ # noqa: E501 

378 

379 return self._proxied.begin() 

380 

381 def begin_nested(self) -> AsyncSessionTransaction: 

382 r"""Return an :class:`_asyncio.AsyncSessionTransaction` object 

383 which will begin a "nested" transaction, e.g. SAVEPOINT. 

384 

385 .. container:: class_bases 

386 

387 Proxied for the :class:`_asyncio.AsyncSession` class on 

388 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

389 

390 Behavior is the same as that of :meth:`_asyncio.AsyncSession.begin`. 

391 

392 For a general description of ORM begin nested, see 

393 :meth:`_orm.Session.begin_nested`. 

394 

395 .. seealso:: 

396 

397 :ref:`aiosqlite_serializable` - special workarounds required 

398 with the SQLite asyncio driver in order for SAVEPOINT to work 

399 correctly. 

400 

401 

402 """ # noqa: E501 

403 

404 return self._proxied.begin_nested() 

405 

406 async def close(self) -> None: 

407 r"""Close out the transactional resources and ORM objects used by this 

408 :class:`_asyncio.AsyncSession`. 

409 

410 .. container:: class_bases 

411 

412 Proxied for the :class:`_asyncio.AsyncSession` class on 

413 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

414 

415 .. seealso:: 

416 

417 :meth:`_orm.Session.close` - main documentation for 

418 "close" 

419 

420 :ref:`session_closing` - detail on the semantics of 

421 :meth:`_asyncio.AsyncSession.close` and 

422 :meth:`_asyncio.AsyncSession.reset`. 

423 

424 

425 """ # noqa: E501 

426 

427 return await self._proxied.close() 

428 

429 async def reset(self) -> None: 

430 r"""Close out the transactional resources and ORM objects used by this 

431 :class:`_orm.Session`, resetting the session to its initial state. 

432 

433 .. container:: class_bases 

434 

435 Proxied for the :class:`_asyncio.AsyncSession` class on 

436 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

437 

438 .. versionadded:: 2.0.22 

439 

440 .. seealso:: 

441 

442 :meth:`_orm.Session.reset` - main documentation for 

443 "reset" 

444 

445 :ref:`session_closing` - detail on the semantics of 

446 :meth:`_asyncio.AsyncSession.close` and 

447 :meth:`_asyncio.AsyncSession.reset`. 

448 

449 

450 """ # noqa: E501 

451 

452 return await self._proxied.reset() 

453 

454 async def commit(self) -> None: 

455 r"""Commit the current transaction in progress. 

456 

457 .. container:: class_bases 

458 

459 Proxied for the :class:`_asyncio.AsyncSession` class on 

460 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

461 

462 .. seealso:: 

463 

464 :meth:`_orm.Session.commit` - main documentation for 

465 "commit" 

466 

467 """ # noqa: E501 

468 

469 return await self._proxied.commit() 

470 

471 async def connection( 

472 self, 

473 bind_arguments: Optional[_BindArguments] = None, 

474 execution_options: Optional[CoreExecuteOptionsParameter] = None, 

475 **kw: Any, 

476 ) -> AsyncConnection: 

477 r"""Return a :class:`_asyncio.AsyncConnection` object corresponding to 

478 this :class:`.Session` object's transactional state. 

479 

480 .. container:: class_bases 

481 

482 Proxied for the :class:`_asyncio.AsyncSession` class on 

483 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

484 

485 This method may also be used to establish execution options for the 

486 database connection used by the current transaction. 

487 

488 .. versionadded:: 1.4.24 Added \**kw arguments which are passed 

489 through to the underlying :meth:`_orm.Session.connection` method. 

490 

491 .. seealso:: 

492 

493 :meth:`_orm.Session.connection` - main documentation for 

494 "connection" 

495 

496 

497 """ # noqa: E501 

498 

499 return await self._proxied.connection( 

500 bind_arguments=bind_arguments, 

501 execution_options=execution_options, 

502 **kw, 

503 ) 

504 

505 async def delete(self, instance: object) -> None: 

506 r"""Mark an instance as deleted. 

507 

508 .. container:: class_bases 

509 

510 Proxied for the :class:`_asyncio.AsyncSession` class on 

511 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

512 

513 The database delete operation occurs upon ``flush()``. 

514 

515 As this operation may need to cascade along unloaded relationships, 

516 it is awaitable to allow for those queries to take place. 

517 

518 .. seealso:: 

519 

520 :meth:`_orm.Session.delete` - main documentation for delete 

521 

522 

523 """ # noqa: E501 

524 

525 return await self._proxied.delete(instance) 

526 

527 @overload 

528 async def execute( 

529 self, 

530 statement: TypedReturnsRows[_T], 

531 params: Optional[_CoreAnyExecuteParams] = None, 

532 *, 

533 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

534 bind_arguments: Optional[_BindArguments] = None, 

535 _parent_execute_state: Optional[Any] = None, 

536 _add_event: Optional[Any] = None, 

537 ) -> Result[_T]: ... 

538 

539 @overload 

540 async def execute( 

541 self, 

542 statement: Executable, 

543 params: Optional[_CoreAnyExecuteParams] = None, 

544 *, 

545 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

546 bind_arguments: Optional[_BindArguments] = None, 

547 _parent_execute_state: Optional[Any] = None, 

548 _add_event: Optional[Any] = None, 

549 ) -> Result[Any]: ... 

550 

551 async def execute( 

552 self, 

553 statement: Executable, 

554 params: Optional[_CoreAnyExecuteParams] = None, 

555 *, 

556 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

557 bind_arguments: Optional[_BindArguments] = None, 

558 **kw: Any, 

559 ) -> Result[Any]: 

560 r"""Execute a statement and return a buffered 

561 :class:`_engine.Result` object. 

562 

563 .. container:: class_bases 

564 

565 Proxied for the :class:`_asyncio.AsyncSession` class on 

566 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

567 

568 .. seealso:: 

569 

570 :meth:`_orm.Session.execute` - main documentation for execute 

571 

572 

573 """ # noqa: E501 

574 

575 return await self._proxied.execute( 

576 statement, 

577 params=params, 

578 execution_options=execution_options, 

579 bind_arguments=bind_arguments, 

580 **kw, 

581 ) 

582 

583 def expire( 

584 self, instance: object, attribute_names: Optional[Iterable[str]] = None 

585 ) -> None: 

586 r"""Expire the attributes on an instance. 

587 

588 .. container:: class_bases 

589 

590 Proxied for the :class:`_asyncio.AsyncSession` class on 

591 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

592 

593 .. container:: class_bases 

594 

595 Proxied for the :class:`_orm.Session` class on 

596 behalf of the :class:`_asyncio.AsyncSession` class. 

597 

598 Marks the attributes of an instance as out of date. When an expired 

599 attribute is next accessed, a query will be issued to the 

600 :class:`.Session` object's current transactional context in order to 

601 load all expired attributes for the given instance. Note that 

602 a highly isolated transaction will return the same values as were 

603 previously read in that same transaction, regardless of changes 

604 in database state outside of that transaction. 

605 

606 To expire all objects in the :class:`.Session` simultaneously, 

607 use :meth:`Session.expire_all`. 

608 

609 The :class:`.Session` object's default behavior is to 

610 expire all state whenever the :meth:`Session.rollback` 

611 or :meth:`Session.commit` methods are called, so that new 

612 state can be loaded for the new transaction. For this reason, 

613 calling :meth:`Session.expire` only makes sense for the specific 

614 case that a non-ORM SQL statement was emitted in the current 

615 transaction. 

616 

617 :param instance: The instance to be refreshed. 

618 :param attribute_names: optional list of string attribute names 

619 indicating a subset of attributes to be expired. 

620 

621 .. seealso:: 

622 

623 :ref:`session_expire` - introductory material 

624 

625 :meth:`.Session.expire` 

626 

627 :meth:`.Session.refresh` 

628 

629 :meth:`_orm.Query.populate_existing` 

630 

631 

632 

633 """ # noqa: E501 

634 

635 return self._proxied.expire(instance, attribute_names=attribute_names) 

636 

637 def expire_all(self) -> None: 

638 r"""Expires all persistent instances within this Session. 

639 

640 .. container:: class_bases 

641 

642 Proxied for the :class:`_asyncio.AsyncSession` class on 

643 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

644 

645 .. container:: class_bases 

646 

647 Proxied for the :class:`_orm.Session` class on 

648 behalf of the :class:`_asyncio.AsyncSession` class. 

649 

650 When any attributes on a persistent instance is next accessed, 

651 a query will be issued using the 

652 :class:`.Session` object's current transactional context in order to 

653 load all expired attributes for the given instance. Note that 

654 a highly isolated transaction will return the same values as were 

655 previously read in that same transaction, regardless of changes 

656 in database state outside of that transaction. 

657 

658 To expire individual objects and individual attributes 

659 on those objects, use :meth:`Session.expire`. 

660 

661 The :class:`.Session` object's default behavior is to 

662 expire all state whenever the :meth:`Session.rollback` 

663 or :meth:`Session.commit` methods are called, so that new 

664 state can be loaded for the new transaction. For this reason, 

665 calling :meth:`Session.expire_all` is not usually needed, 

666 assuming the transaction is isolated. 

667 

668 .. seealso:: 

669 

670 :ref:`session_expire` - introductory material 

671 

672 :meth:`.Session.expire` 

673 

674 :meth:`.Session.refresh` 

675 

676 :meth:`_orm.Query.populate_existing` 

677 

678 

679 

680 """ # noqa: E501 

681 

682 return self._proxied.expire_all() 

683 

684 def expunge(self, instance: object) -> None: 

685 r"""Remove the `instance` from this ``Session``. 

686 

687 .. container:: class_bases 

688 

689 Proxied for the :class:`_asyncio.AsyncSession` class on 

690 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

691 

692 .. container:: class_bases 

693 

694 Proxied for the :class:`_orm.Session` class on 

695 behalf of the :class:`_asyncio.AsyncSession` class. 

696 

697 This will free all internal references to the instance. Cascading 

698 will be applied according to the *expunge* cascade rule. 

699 

700 

701 

702 """ # noqa: E501 

703 

704 return self._proxied.expunge(instance) 

705 

706 def expunge_all(self) -> None: 

707 r"""Remove all object instances from this ``Session``. 

708 

709 .. container:: class_bases 

710 

711 Proxied for the :class:`_asyncio.AsyncSession` class on 

712 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

713 

714 .. container:: class_bases 

715 

716 Proxied for the :class:`_orm.Session` class on 

717 behalf of the :class:`_asyncio.AsyncSession` class. 

718 

719 This is equivalent to calling ``expunge(obj)`` on all objects in this 

720 ``Session``. 

721 

722 

723 

724 """ # noqa: E501 

725 

726 return self._proxied.expunge_all() 

727 

728 async def flush(self, objects: Optional[Sequence[Any]] = None) -> None: 

729 r"""Flush all the object changes to the database. 

730 

731 .. container:: class_bases 

732 

733 Proxied for the :class:`_asyncio.AsyncSession` class on 

734 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

735 

736 .. seealso:: 

737 

738 :meth:`_orm.Session.flush` - main documentation for flush 

739 

740 

741 """ # noqa: E501 

742 

743 return await self._proxied.flush(objects=objects) 

744 

745 def get_bind( 

746 self, 

747 mapper: Optional[_EntityBindKey[_O]] = None, 

748 clause: Optional[ClauseElement] = None, 

749 bind: Optional[_SessionBind] = None, 

750 **kw: Any, 

751 ) -> Union[Engine, Connection]: 

752 r"""Return a "bind" to which the synchronous proxied :class:`_orm.Session` 

753 is bound. 

754 

755 .. container:: class_bases 

756 

757 Proxied for the :class:`_asyncio.AsyncSession` class on 

758 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

759 

760 Unlike the :meth:`_orm.Session.get_bind` method, this method is 

761 currently **not** used by this :class:`.AsyncSession` in any way 

762 in order to resolve engines for requests. 

763 

764 .. note:: 

765 

766 This method proxies directly to the :meth:`_orm.Session.get_bind` 

767 method, however is currently **not** useful as an override target, 

768 in contrast to that of the :meth:`_orm.Session.get_bind` method. 

769 The example below illustrates how to implement custom 

770 :meth:`_orm.Session.get_bind` schemes that work with 

771 :class:`.AsyncSession` and :class:`.AsyncEngine`. 

772 

773 The pattern introduced at :ref:`session_custom_partitioning` 

774 illustrates how to apply a custom bind-lookup scheme to a 

775 :class:`_orm.Session` given a set of :class:`_engine.Engine` objects. 

776 To apply a corresponding :meth:`_orm.Session.get_bind` implementation 

777 for use with a :class:`.AsyncSession` and :class:`.AsyncEngine` 

778 objects, continue to subclass :class:`_orm.Session` and apply it to 

779 :class:`.AsyncSession` using 

780 :paramref:`.AsyncSession.sync_session_class`. The inner method must 

781 continue to return :class:`_engine.Engine` instances, which can be 

782 acquired from a :class:`_asyncio.AsyncEngine` using the 

783 :attr:`_asyncio.AsyncEngine.sync_engine` attribute:: 

784 

785 # using example from "Custom Vertical Partitioning" 

786 

787 

788 import random 

789 

790 from sqlalchemy.ext.asyncio import AsyncSession 

791 from sqlalchemy.ext.asyncio import create_async_engine 

792 from sqlalchemy.ext.asyncio import async_sessionmaker 

793 from sqlalchemy.orm import Session 

794 

795 # construct async engines w/ async drivers 

796 engines = { 

797 "leader": create_async_engine("sqlite+aiosqlite:///leader.db"), 

798 "other": create_async_engine("sqlite+aiosqlite:///other.db"), 

799 "follower1": create_async_engine("sqlite+aiosqlite:///follower1.db"), 

800 "follower2": create_async_engine("sqlite+aiosqlite:///follower2.db"), 

801 } 

802 

803 

804 class RoutingSession(Session): 

805 def get_bind(self, mapper=None, clause=None, **kw): 

806 # within get_bind(), return sync engines 

807 if mapper and issubclass(mapper.class_, MyOtherClass): 

808 return engines["other"].sync_engine 

809 elif self._flushing or isinstance(clause, (Update, Delete)): 

810 return engines["leader"].sync_engine 

811 else: 

812 return engines[ 

813 random.choice(["follower1", "follower2"]) 

814 ].sync_engine 

815 

816 

817 # apply to AsyncSession using sync_session_class 

818 AsyncSessionMaker = async_sessionmaker(sync_session_class=RoutingSession) 

819 

820 The :meth:`_orm.Session.get_bind` method is called in a non-asyncio, 

821 implicitly non-blocking context in the same manner as ORM event hooks 

822 and functions that are invoked via :meth:`.AsyncSession.run_sync`, so 

823 routines that wish to run SQL commands inside of 

824 :meth:`_orm.Session.get_bind` can continue to do so using 

825 blocking-style code, which will be translated to implicitly async calls 

826 at the point of invoking IO on the database drivers. 

827 

828 

829 """ # noqa: E501 

830 

831 return self._proxied.get_bind( 

832 mapper=mapper, clause=clause, bind=bind, **kw 

833 ) 

834 

835 def is_modified( 

836 self, instance: object, include_collections: bool = True 

837 ) -> bool: 

838 r"""Return ``True`` if the given instance has locally 

839 modified attributes. 

840 

841 .. container:: class_bases 

842 

843 Proxied for the :class:`_asyncio.AsyncSession` class on 

844 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

845 

846 .. container:: class_bases 

847 

848 Proxied for the :class:`_orm.Session` class on 

849 behalf of the :class:`_asyncio.AsyncSession` class. 

850 

851 This method retrieves the history for each instrumented 

852 attribute on the instance and performs a comparison of the current 

853 value to its previously flushed or committed value, if any. 

854 

855 It is in effect a more expensive and accurate 

856 version of checking for the given instance in the 

857 :attr:`.Session.dirty` collection; a full test for 

858 each attribute's net "dirty" status is performed. 

859 

860 E.g.:: 

861 

862 return session.is_modified(someobject) 

863 

864 A few caveats to this method apply: 

865 

866 * Instances present in the :attr:`.Session.dirty` collection may 

867 report ``False`` when tested with this method. This is because 

868 the object may have received change events via attribute mutation, 

869 thus placing it in :attr:`.Session.dirty`, but ultimately the state 

870 is the same as that loaded from the database, resulting in no net 

871 change here. 

872 * Scalar attributes may not have recorded the previously set 

873 value when a new value was applied, if the attribute was not loaded, 

874 or was expired, at the time the new value was received - in these 

875 cases, the attribute is assumed to have a change, even if there is 

876 ultimately no net change against its database value. SQLAlchemy in 

877 most cases does not need the "old" value when a set event occurs, so 

878 it skips the expense of a SQL call if the old value isn't present, 

879 based on the assumption that an UPDATE of the scalar value is 

880 usually needed, and in those few cases where it isn't, is less 

881 expensive on average than issuing a defensive SELECT. 

882 

883 The "old" value is fetched unconditionally upon set only if the 

884 attribute container has the ``active_history`` flag set to ``True``. 

885 This flag is set typically for primary key attributes and scalar 

886 object references that are not a simple many-to-one. To set this 

887 flag for any arbitrary mapped column, use the ``active_history`` 

888 argument with :func:`.column_property`. 

889 

890 :param instance: mapped instance to be tested for pending changes. 

891 :param include_collections: Indicates if multivalued collections 

892 should be included in the operation. Setting this to ``False`` is a 

893 way to detect only local-column based properties (i.e. scalar columns 

894 or many-to-one foreign keys) that would result in an UPDATE for this 

895 instance upon flush. 

896 

897 

898 

899 """ # noqa: E501 

900 

901 return self._proxied.is_modified( 

902 instance, include_collections=include_collections 

903 ) 

904 

905 async def invalidate(self) -> None: 

906 r"""Close this Session, using connection invalidation. 

907 

908 .. container:: class_bases 

909 

910 Proxied for the :class:`_asyncio.AsyncSession` class on 

911 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

912 

913 For a complete description, see :meth:`_orm.Session.invalidate`. 

914 

915 """ # noqa: E501 

916 

917 return await self._proxied.invalidate() 

918 

919 async def merge( 

920 self, 

921 instance: _O, 

922 *, 

923 load: bool = True, 

924 options: Optional[Sequence[ORMOption]] = None, 

925 ) -> _O: 

926 r"""Copy the state of a given instance into a corresponding instance 

927 within this :class:`_asyncio.AsyncSession`. 

928 

929 .. container:: class_bases 

930 

931 Proxied for the :class:`_asyncio.AsyncSession` class on 

932 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

933 

934 .. seealso:: 

935 

936 :meth:`_orm.Session.merge` - main documentation for merge 

937 

938 

939 """ # noqa: E501 

940 

941 return await self._proxied.merge(instance, load=load, options=options) 

942 

943 async def refresh( 

944 self, 

945 instance: object, 

946 attribute_names: Optional[Iterable[str]] = None, 

947 with_for_update: ForUpdateParameter = None, 

948 ) -> None: 

949 r"""Expire and refresh the attributes on the given instance. 

950 

951 .. container:: class_bases 

952 

953 Proxied for the :class:`_asyncio.AsyncSession` class on 

954 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

955 

956 A query will be issued to the database and all attributes will be 

957 refreshed with their current database value. 

958 

959 This is the async version of the :meth:`_orm.Session.refresh` method. 

960 See that method for a complete description of all options. 

961 

962 .. seealso:: 

963 

964 :meth:`_orm.Session.refresh` - main documentation for refresh 

965 

966 

967 """ # noqa: E501 

968 

969 return await self._proxied.refresh( 

970 instance, 

971 attribute_names=attribute_names, 

972 with_for_update=with_for_update, 

973 ) 

974 

975 async def rollback(self) -> None: 

976 r"""Rollback the current transaction in progress. 

977 

978 .. container:: class_bases 

979 

980 Proxied for the :class:`_asyncio.AsyncSession` class on 

981 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

982 

983 .. seealso:: 

984 

985 :meth:`_orm.Session.rollback` - main documentation for 

986 "rollback" 

987 

988 """ # noqa: E501 

989 

990 return await self._proxied.rollback() 

991 

992 @overload 

993 async def scalar( 

994 self, 

995 statement: TypedReturnsRows[Tuple[_T]], 

996 params: Optional[_CoreAnyExecuteParams] = None, 

997 *, 

998 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

999 bind_arguments: Optional[_BindArguments] = None, 

1000 **kw: Any, 

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

1002 

1003 @overload 

1004 async def scalar( 

1005 self, 

1006 statement: Executable, 

1007 params: Optional[_CoreAnyExecuteParams] = None, 

1008 *, 

1009 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1010 bind_arguments: Optional[_BindArguments] = None, 

1011 **kw: Any, 

1012 ) -> Any: ... 

1013 

1014 async def scalar( 

1015 self, 

1016 statement: Executable, 

1017 params: Optional[_CoreAnyExecuteParams] = None, 

1018 *, 

1019 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1020 bind_arguments: Optional[_BindArguments] = None, 

1021 **kw: Any, 

1022 ) -> Any: 

1023 r"""Execute a statement and return a scalar result. 

1024 

1025 .. container:: class_bases 

1026 

1027 Proxied for the :class:`_asyncio.AsyncSession` class on 

1028 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

1029 

1030 .. seealso:: 

1031 

1032 :meth:`_orm.Session.scalar` - main documentation for scalar 

1033 

1034 

1035 """ # noqa: E501 

1036 

1037 return await self._proxied.scalar( 

1038 statement, 

1039 params=params, 

1040 execution_options=execution_options, 

1041 bind_arguments=bind_arguments, 

1042 **kw, 

1043 ) 

1044 

1045 @overload 

1046 async def scalars( 

1047 self, 

1048 statement: TypedReturnsRows[Tuple[_T]], 

1049 params: Optional[_CoreAnyExecuteParams] = None, 

1050 *, 

1051 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1052 bind_arguments: Optional[_BindArguments] = None, 

1053 **kw: Any, 

1054 ) -> ScalarResult[_T]: ... 

1055 

1056 @overload 

1057 async def scalars( 

1058 self, 

1059 statement: Executable, 

1060 params: Optional[_CoreAnyExecuteParams] = None, 

1061 *, 

1062 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1063 bind_arguments: Optional[_BindArguments] = None, 

1064 **kw: Any, 

1065 ) -> ScalarResult[Any]: ... 

1066 

1067 async def scalars( 

1068 self, 

1069 statement: Executable, 

1070 params: Optional[_CoreAnyExecuteParams] = None, 

1071 *, 

1072 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1073 bind_arguments: Optional[_BindArguments] = None, 

1074 **kw: Any, 

1075 ) -> ScalarResult[Any]: 

1076 r"""Execute a statement and return scalar results. 

1077 

1078 .. container:: class_bases 

1079 

1080 Proxied for the :class:`_asyncio.AsyncSession` class on 

1081 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

1082 

1083 :return: a :class:`_result.ScalarResult` object 

1084 

1085 .. versionadded:: 1.4.24 Added :meth:`_asyncio.AsyncSession.scalars` 

1086 

1087 .. versionadded:: 1.4.26 Added 

1088 :meth:`_asyncio.async_scoped_session.scalars` 

1089 

1090 .. seealso:: 

1091 

1092 :meth:`_orm.Session.scalars` - main documentation for scalars 

1093 

1094 :meth:`_asyncio.AsyncSession.stream_scalars` - streaming version 

1095 

1096 

1097 """ # noqa: E501 

1098 

1099 return await self._proxied.scalars( 

1100 statement, 

1101 params=params, 

1102 execution_options=execution_options, 

1103 bind_arguments=bind_arguments, 

1104 **kw, 

1105 ) 

1106 

1107 async def get( 

1108 self, 

1109 entity: _EntityBindKey[_O], 

1110 ident: _PKIdentityArgument, 

1111 *, 

1112 options: Optional[Sequence[ORMOption]] = None, 

1113 populate_existing: bool = False, 

1114 with_for_update: ForUpdateParameter = None, 

1115 identity_token: Optional[Any] = None, 

1116 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1117 ) -> Union[_O, None]: 

1118 r"""Return an instance based on the given primary key identifier, 

1119 or ``None`` if not found. 

1120 

1121 .. container:: class_bases 

1122 

1123 Proxied for the :class:`_asyncio.AsyncSession` class on 

1124 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

1125 

1126 .. seealso:: 

1127 

1128 :meth:`_orm.Session.get` - main documentation for get 

1129 

1130 

1131 

1132 """ # noqa: E501 

1133 

1134 result = await self._proxied.get( 

1135 entity, 

1136 ident, 

1137 options=options, 

1138 populate_existing=populate_existing, 

1139 with_for_update=with_for_update, 

1140 identity_token=identity_token, 

1141 execution_options=execution_options, 

1142 ) 

1143 return result 

1144 

1145 async def get_one( 

1146 self, 

1147 entity: _EntityBindKey[_O], 

1148 ident: _PKIdentityArgument, 

1149 *, 

1150 options: Optional[Sequence[ORMOption]] = None, 

1151 populate_existing: bool = False, 

1152 with_for_update: ForUpdateParameter = None, 

1153 identity_token: Optional[Any] = None, 

1154 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1155 ) -> _O: 

1156 r"""Return an instance based on the given primary key identifier, 

1157 or raise an exception if not found. 

1158 

1159 .. container:: class_bases 

1160 

1161 Proxied for the :class:`_asyncio.AsyncSession` class on 

1162 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

1163 

1164 Raises :class:`_exc.NoResultFound` if the query selects no rows. 

1165 

1166 ..versionadded: 2.0.22 

1167 

1168 .. seealso:: 

1169 

1170 :meth:`_orm.Session.get_one` - main documentation for get_one 

1171 

1172 

1173 """ # noqa: E501 

1174 

1175 return await self._proxied.get_one( 

1176 entity, 

1177 ident, 

1178 options=options, 

1179 populate_existing=populate_existing, 

1180 with_for_update=with_for_update, 

1181 identity_token=identity_token, 

1182 execution_options=execution_options, 

1183 ) 

1184 

1185 @overload 

1186 async def stream( 

1187 self, 

1188 statement: TypedReturnsRows[_T], 

1189 params: Optional[_CoreAnyExecuteParams] = None, 

1190 *, 

1191 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1192 bind_arguments: Optional[_BindArguments] = None, 

1193 **kw: Any, 

1194 ) -> AsyncResult[_T]: ... 

1195 

1196 @overload 

1197 async def stream( 

1198 self, 

1199 statement: Executable, 

1200 params: Optional[_CoreAnyExecuteParams] = None, 

1201 *, 

1202 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1203 bind_arguments: Optional[_BindArguments] = None, 

1204 **kw: Any, 

1205 ) -> AsyncResult[Any]: ... 

1206 

1207 async def stream( 

1208 self, 

1209 statement: Executable, 

1210 params: Optional[_CoreAnyExecuteParams] = None, 

1211 *, 

1212 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1213 bind_arguments: Optional[_BindArguments] = None, 

1214 **kw: Any, 

1215 ) -> AsyncResult[Any]: 

1216 r"""Execute a statement and return a streaming 

1217 :class:`_asyncio.AsyncResult` object. 

1218 

1219 .. container:: class_bases 

1220 

1221 Proxied for the :class:`_asyncio.AsyncSession` class on 

1222 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

1223 

1224 

1225 """ # noqa: E501 

1226 

1227 return await self._proxied.stream( 

1228 statement, 

1229 params=params, 

1230 execution_options=execution_options, 

1231 bind_arguments=bind_arguments, 

1232 **kw, 

1233 ) 

1234 

1235 @overload 

1236 async def stream_scalars( 

1237 self, 

1238 statement: TypedReturnsRows[Tuple[_T]], 

1239 params: Optional[_CoreAnyExecuteParams] = None, 

1240 *, 

1241 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1242 bind_arguments: Optional[_BindArguments] = None, 

1243 **kw: Any, 

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

1245 

1246 @overload 

1247 async def stream_scalars( 

1248 self, 

1249 statement: Executable, 

1250 params: Optional[_CoreAnyExecuteParams] = None, 

1251 *, 

1252 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1253 bind_arguments: Optional[_BindArguments] = None, 

1254 **kw: Any, 

1255 ) -> AsyncScalarResult[Any]: ... 

1256 

1257 async def stream_scalars( 

1258 self, 

1259 statement: Executable, 

1260 params: Optional[_CoreAnyExecuteParams] = None, 

1261 *, 

1262 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1263 bind_arguments: Optional[_BindArguments] = None, 

1264 **kw: Any, 

1265 ) -> AsyncScalarResult[Any]: 

1266 r"""Execute a statement and return a stream of scalar results. 

1267 

1268 .. container:: class_bases 

1269 

1270 Proxied for the :class:`_asyncio.AsyncSession` class on 

1271 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

1272 

1273 :return: an :class:`_asyncio.AsyncScalarResult` object 

1274 

1275 .. versionadded:: 1.4.24 

1276 

1277 .. seealso:: 

1278 

1279 :meth:`_orm.Session.scalars` - main documentation for scalars 

1280 

1281 :meth:`_asyncio.AsyncSession.scalars` - non streaming version 

1282 

1283 

1284 """ # noqa: E501 

1285 

1286 return await self._proxied.stream_scalars( 

1287 statement, 

1288 params=params, 

1289 execution_options=execution_options, 

1290 bind_arguments=bind_arguments, 

1291 **kw, 

1292 ) 

1293 

1294 @property 

1295 def bind(self) -> Any: 

1296 r"""Proxy for the :attr:`_asyncio.AsyncSession.bind` attribute 

1297 on behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

1298 

1299 """ # noqa: E501 

1300 

1301 return self._proxied.bind 

1302 

1303 @bind.setter 

1304 def bind(self, attr: Any) -> None: 

1305 self._proxied.bind = attr 

1306 

1307 @property 

1308 def dirty(self) -> Any: 

1309 r"""The set of all persistent instances considered dirty. 

1310 

1311 .. container:: class_bases 

1312 

1313 Proxied for the :class:`_asyncio.AsyncSession` class 

1314 on behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

1315 

1316 .. container:: class_bases 

1317 

1318 Proxied for the :class:`_orm.Session` class 

1319 on behalf of the :class:`_asyncio.AsyncSession` class. 

1320 

1321 E.g.:: 

1322 

1323 some_mapped_object in session.dirty 

1324 

1325 Instances are considered dirty when they were modified but not 

1326 deleted. 

1327 

1328 Note that this 'dirty' calculation is 'optimistic'; most 

1329 attribute-setting or collection modification operations will 

1330 mark an instance as 'dirty' and place it in this set, even if 

1331 there is no net change to the attribute's value. At flush 

1332 time, the value of each attribute is compared to its 

1333 previously saved value, and if there's no net change, no SQL 

1334 operation will occur (this is a more expensive operation so 

1335 it's only done at flush time). 

1336 

1337 To check if an instance has actionable net changes to its 

1338 attributes, use the :meth:`.Session.is_modified` method. 

1339 

1340 

1341 

1342 """ # noqa: E501 

1343 

1344 return self._proxied.dirty 

1345 

1346 @property 

1347 def deleted(self) -> Any: 

1348 r"""The set of all instances marked as 'deleted' within this ``Session`` 

1349 

1350 .. container:: class_bases 

1351 

1352 Proxied for the :class:`_asyncio.AsyncSession` class 

1353 on behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

1354 

1355 .. container:: class_bases 

1356 

1357 Proxied for the :class:`_orm.Session` class 

1358 on behalf of the :class:`_asyncio.AsyncSession` class. 

1359 

1360 

1361 """ # noqa: E501 

1362 

1363 return self._proxied.deleted 

1364 

1365 @property 

1366 def new(self) -> Any: 

1367 r"""The set of all instances marked as 'new' within this ``Session``. 

1368 

1369 .. container:: class_bases 

1370 

1371 Proxied for the :class:`_asyncio.AsyncSession` class 

1372 on behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

1373 

1374 .. container:: class_bases 

1375 

1376 Proxied for the :class:`_orm.Session` class 

1377 on behalf of the :class:`_asyncio.AsyncSession` class. 

1378 

1379 

1380 """ # noqa: E501 

1381 

1382 return self._proxied.new 

1383 

1384 @property 

1385 def identity_map(self) -> Any: 

1386 r"""Proxy for the :attr:`_orm.Session.identity_map` attribute 

1387 on behalf of the :class:`_asyncio.AsyncSession` class. 

1388 

1389 .. container:: class_bases 

1390 

1391 Proxied for the :class:`_asyncio.AsyncSession` class 

1392 on behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

1393 

1394 

1395 """ # noqa: E501 

1396 

1397 return self._proxied.identity_map 

1398 

1399 @identity_map.setter 

1400 def identity_map(self, attr: Any) -> None: 

1401 self._proxied.identity_map = attr 

1402 

1403 @property 

1404 def is_active(self) -> Any: 

1405 r"""True if this :class:`.Session` not in "partial rollback" state. 

1406 

1407 .. container:: class_bases 

1408 

1409 Proxied for the :class:`_asyncio.AsyncSession` class 

1410 on behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

1411 

1412 .. container:: class_bases 

1413 

1414 Proxied for the :class:`_orm.Session` class 

1415 on behalf of the :class:`_asyncio.AsyncSession` class. 

1416 

1417 .. versionchanged:: 1.4 The :class:`_orm.Session` no longer begins 

1418 a new transaction immediately, so this attribute will be False 

1419 when the :class:`_orm.Session` is first instantiated. 

1420 

1421 "partial rollback" state typically indicates that the flush process 

1422 of the :class:`_orm.Session` has failed, and that the 

1423 :meth:`_orm.Session.rollback` method must be emitted in order to 

1424 fully roll back the transaction. 

1425 

1426 If this :class:`_orm.Session` is not in a transaction at all, the 

1427 :class:`_orm.Session` will autobegin when it is first used, so in this 

1428 case :attr:`_orm.Session.is_active` will return True. 

1429 

1430 Otherwise, if this :class:`_orm.Session` is within a transaction, 

1431 and that transaction has not been rolled back internally, the 

1432 :attr:`_orm.Session.is_active` will also return True. 

1433 

1434 .. seealso:: 

1435 

1436 :ref:`faq_session_rollback` 

1437 

1438 :meth:`_orm.Session.in_transaction` 

1439 

1440 

1441 

1442 """ # noqa: E501 

1443 

1444 return self._proxied.is_active 

1445 

1446 @property 

1447 def autoflush(self) -> Any: 

1448 r"""Proxy for the :attr:`_orm.Session.autoflush` attribute 

1449 on behalf of the :class:`_asyncio.AsyncSession` class. 

1450 

1451 .. container:: class_bases 

1452 

1453 Proxied for the :class:`_asyncio.AsyncSession` class 

1454 on behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

1455 

1456 

1457 """ # noqa: E501 

1458 

1459 return self._proxied.autoflush 

1460 

1461 @autoflush.setter 

1462 def autoflush(self, attr: Any) -> None: 

1463 self._proxied.autoflush = attr 

1464 

1465 @property 

1466 def no_autoflush(self) -> Any: 

1467 r"""Return a context manager that disables autoflush. 

1468 

1469 .. container:: class_bases 

1470 

1471 Proxied for the :class:`_asyncio.AsyncSession` class 

1472 on behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

1473 

1474 .. container:: class_bases 

1475 

1476 Proxied for the :class:`_orm.Session` class 

1477 on behalf of the :class:`_asyncio.AsyncSession` class. 

1478 

1479 e.g.:: 

1480 

1481 with session.no_autoflush: 

1482 

1483 some_object = SomeClass() 

1484 session.add(some_object) 

1485 # won't autoflush 

1486 some_object.related_thing = session.query(SomeRelated).first() 

1487 

1488 Operations that proceed within the ``with:`` block 

1489 will not be subject to flushes occurring upon query 

1490 access. This is useful when initializing a series 

1491 of objects which involve existing database queries, 

1492 where the uncompleted object should not yet be flushed. 

1493 

1494 

1495 

1496 """ # noqa: E501 

1497 

1498 return self._proxied.no_autoflush 

1499 

1500 @property 

1501 def info(self) -> Any: 

1502 r"""A user-modifiable dictionary. 

1503 

1504 .. container:: class_bases 

1505 

1506 Proxied for the :class:`_asyncio.AsyncSession` class 

1507 on behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

1508 

1509 .. container:: class_bases 

1510 

1511 Proxied for the :class:`_orm.Session` class 

1512 on behalf of the :class:`_asyncio.AsyncSession` class. 

1513 

1514 The initial value of this dictionary can be populated using the 

1515 ``info`` argument to the :class:`.Session` constructor or 

1516 :class:`.sessionmaker` constructor or factory methods. The dictionary 

1517 here is always local to this :class:`.Session` and can be modified 

1518 independently of all other :class:`.Session` objects. 

1519 

1520 

1521 

1522 """ # noqa: E501 

1523 

1524 return self._proxied.info 

1525 

1526 @classmethod 

1527 async def close_all(cls) -> None: 

1528 r"""Close all :class:`_asyncio.AsyncSession` sessions. 

1529 

1530 .. container:: class_bases 

1531 

1532 Proxied for the :class:`_asyncio.AsyncSession` class on 

1533 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

1534 

1535 .. deprecated:: 2.0 The :meth:`.AsyncSession.close_all` method is deprecated and will be removed in a future release. Please refer to :func:`_asyncio.close_all_sessions`. 

1536 

1537 """ # noqa: E501 

1538 

1539 return await AsyncSession.close_all() 

1540 

1541 @classmethod 

1542 def object_session(cls, instance: object) -> Optional[Session]: 

1543 r"""Return the :class:`.Session` to which an object belongs. 

1544 

1545 .. container:: class_bases 

1546 

1547 Proxied for the :class:`_asyncio.AsyncSession` class on 

1548 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

1549 

1550 .. container:: class_bases 

1551 

1552 Proxied for the :class:`_orm.Session` class on 

1553 behalf of the :class:`_asyncio.AsyncSession` class. 

1554 

1555 This is an alias of :func:`.object_session`. 

1556 

1557 

1558 

1559 """ # noqa: E501 

1560 

1561 return AsyncSession.object_session(instance) 

1562 

1563 @classmethod 

1564 def identity_key( 

1565 cls, 

1566 class_: Optional[Type[Any]] = None, 

1567 ident: Union[Any, Tuple[Any, ...]] = None, 

1568 *, 

1569 instance: Optional[Any] = None, 

1570 row: Optional[Union[Row[Any], RowMapping]] = None, 

1571 identity_token: Optional[Any] = None, 

1572 ) -> _IdentityKeyType[Any]: 

1573 r"""Return an identity key. 

1574 

1575 .. container:: class_bases 

1576 

1577 Proxied for the :class:`_asyncio.AsyncSession` class on 

1578 behalf of the :class:`_asyncio.scoping.async_scoped_session` class. 

1579 

1580 .. container:: class_bases 

1581 

1582 Proxied for the :class:`_orm.Session` class on 

1583 behalf of the :class:`_asyncio.AsyncSession` class. 

1584 

1585 This is an alias of :func:`.util.identity_key`. 

1586 

1587 

1588 

1589 """ # noqa: E501 

1590 

1591 return AsyncSession.identity_key( 

1592 class_=class_, 

1593 ident=ident, 

1594 instance=instance, 

1595 row=row, 

1596 identity_token=identity_token, 

1597 ) 

1598 

1599 # END PROXY METHODS async_scoped_session