Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/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

262 statements  

1# orm/scoping.py 

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

13from typing import Generic 

14from typing import Iterable 

15from typing import Iterator 

16from typing import Optional 

17from typing import overload 

18from typing import Protocol 

19from typing import Sequence 

20from typing import Tuple 

21from typing import Type 

22from typing import TYPE_CHECKING 

23from typing import TypeVar 

24from typing import Union 

25 

26from .session import _S 

27from .session import Session 

28from .. import exc as sa_exc 

29from .. import util 

30from ..util import create_proxy_methods 

31from ..util import ScopedRegistry 

32from ..util import ThreadLocalRegistry 

33from ..util import warn 

34from ..util import warn_deprecated 

35from ..util.typing import Never 

36from ..util.typing import TupleAny 

37from ..util.typing import TypeVarTuple 

38from ..util.typing import Unpack 

39 

40if TYPE_CHECKING: 

41 from ._typing import _EntityType 

42 from ._typing import _IdentityKeyType 

43 from ._typing import OrmExecuteOptionsParameter 

44 from .identity import IdentityMap 

45 from .interfaces import ORMOption 

46 from .query import Query 

47 from .query import RowReturningQuery 

48 from .session import _BindArguments 

49 from .session import _EntityBindKey 

50 from .session import _PKIdentityArgument 

51 from .session import _SessionBind 

52 from .session import sessionmaker 

53 from .session import SessionTransaction 

54 from ..engine import Connection 

55 from ..engine import Engine 

56 from ..engine import Result 

57 from ..engine import Row 

58 from ..engine import RowMapping 

59 from ..engine.interfaces import _CoreAnyExecuteParams 

60 from ..engine.interfaces import _CoreSingleExecuteParams 

61 from ..engine.interfaces import _ExecuteOptions 

62 from ..engine.interfaces import CoreExecuteOptionsParameter 

63 from ..engine.result import ScalarResult 

64 from ..sql._typing import _ColumnsClauseArgument 

65 from ..sql._typing import _T0 

66 from ..sql._typing import _T1 

67 from ..sql._typing import _T2 

68 from ..sql._typing import _T3 

69 from ..sql._typing import _T4 

70 from ..sql._typing import _T5 

71 from ..sql._typing import _T6 

72 from ..sql._typing import _T7 

73 from ..sql._typing import _TypedColumnClauseArgument as _TCCA 

74 from ..sql.base import Executable 

75 from ..sql.elements import ClauseElement 

76 from ..sql.roles import TypedColumnsClauseRole 

77 from ..sql.selectable import ForUpdateParameter 

78 from ..sql.selectable import TypedReturnsRows 

79 

80 

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

82_Ts = TypeVarTuple("_Ts") 

83 

84 

85class QueryPropertyDescriptor(Protocol): 

86 """Describes the type applied to a class-level 

87 :meth:`_orm.scoped_session.query_property` attribute. 

88 

89 .. versionadded:: 2.0.5 

90 

91 """ 

92 

93 def __get__(self, instance: Any, owner: Type[_T]) -> Query[_T]: ... 

94 

95 

96_O = TypeVar("_O", bound=object) 

97 

98__all__ = ["scoped_session"] 

99 

100 

101@create_proxy_methods( 

102 Session, 

103 ":class:`_orm.Session`", 

104 ":class:`_orm.scoping.scoped_session`", 

105 classmethods=["object_session", "identity_key"], 

106 methods=[ 

107 "__contains__", 

108 "__iter__", 

109 "add", 

110 "add_all", 

111 "begin", 

112 "begin_nested", 

113 "close", 

114 "reset", 

115 "commit", 

116 "connection", 

117 "delete", 

118 "delete_all", 

119 "execute", 

120 "expire", 

121 "expire_all", 

122 "expunge", 

123 "expunge_all", 

124 "flush", 

125 "get", 

126 "get_one", 

127 "get_bind", 

128 "is_modified", 

129 "bulk_save_objects", 

130 "bulk_insert_mappings", 

131 "bulk_update_mappings", 

132 "merge", 

133 "merge_all", 

134 "query", 

135 "refresh", 

136 "rollback", 

137 "scalar", 

138 "scalars", 

139 ], 

140 attributes=[ 

141 "bind", 

142 "dirty", 

143 "deleted", 

144 "new", 

145 "identity_map", 

146 "is_active", 

147 "autoflush", 

148 "no_autoflush", 

149 "info", 

150 "execution_options", 

151 ], 

152) 

153class scoped_session(Generic[_S]): 

154 """Provides scoped management of :class:`.Session` objects. 

155 

156 See :ref:`unitofwork_contextual` for a tutorial. 

157 

158 .. note:: 

159 

160 When using :ref:`asyncio_toplevel`, the async-compatible 

161 :class:`_asyncio.async_scoped_session` class should be 

162 used in place of :class:`.scoped_session`. 

163 

164 """ 

165 

166 _support_async: bool = False 

167 

168 session_factory: sessionmaker[_S] 

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

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

171 a new non-scoped :class:`.Session` is needed.""" 

172 

173 registry: ScopedRegistry[_S] 

174 

175 def __init__( 

176 self, 

177 session_factory: sessionmaker[_S], 

178 scopefunc: Optional[Callable[[], Any]] = None, 

179 ): 

180 """Construct a new :class:`.scoped_session`. 

181 

182 :param session_factory: a factory to create new :class:`.Session` 

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

184 of :class:`.sessionmaker`. 

185 :param scopefunc: optional function which defines 

186 the current scope. If not passed, the :class:`.scoped_session` 

187 object assumes "thread-local" scope, and will use 

188 a Python ``threading.local()`` in order to maintain the current 

189 :class:`.Session`. If passed, the function should return 

190 a hashable token; this token will be used as the key in a 

191 dictionary in order to store and retrieve the current 

192 :class:`.Session`. 

193 

194 """ 

195 self.session_factory = session_factory 

196 

197 if scopefunc: 

198 self.registry = ScopedRegistry(session_factory, scopefunc) 

199 else: 

200 self.registry = ThreadLocalRegistry(session_factory) 

201 

202 @property 

203 def _proxied(self) -> _S: 

204 return self.registry() 

205 

206 def __call__(self, **kw: Any) -> _S: 

207 r"""Return the current :class:`.Session`, creating it 

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

209 

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

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

212 :class:`.Session` is not present. If the :class:`.Session` is present 

213 and keyword arguments have been passed, 

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

215 

216 """ 

217 if kw: 

218 if self.registry.has(): 

219 raise sa_exc.InvalidRequestError( 

220 "Scoped session is already present; " 

221 "no new arguments may be specified." 

222 ) 

223 else: 

224 sess = self.session_factory(**kw) 

225 self.registry.set(sess) 

226 else: 

227 sess = self.registry() 

228 if not self._support_async and sess._is_asyncio: 

229 warn_deprecated( 

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

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

232 "Please use `async_scoped_session` instead.", 

233 "1.4.23", 

234 ) 

235 return sess 

236 

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

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

239 :class:`.scoped_session`. 

240 

241 See :meth:`.sessionmaker.configure`. 

242 

243 """ 

244 

245 if self.registry.has(): 

246 warn( 

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

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

249 "already been created." 

250 ) 

251 

252 self.session_factory.configure(**kwargs) 

253 

254 def remove(self) -> None: 

255 """Dispose of the current :class:`.Session`, if present. 

256 

257 This will first call :meth:`.Session.close` method 

258 on the current :class:`.Session`, which releases any existing 

259 transactional/connection resources still being held; transactions 

260 specifically are rolled back. The :class:`.Session` is then 

261 discarded. Upon next usage within the same scope, 

262 the :class:`.scoped_session` will produce a new 

263 :class:`.Session` object. 

264 

265 """ 

266 

267 if self.registry.has(): 

268 self.registry().close() 

269 self.registry.clear() 

270 

271 def query_property( 

272 self, query_cls: Optional[Type[Query[_T]]] = None 

273 ) -> QueryPropertyDescriptor: 

274 """return a class property which produces a legacy 

275 :class:`_query.Query` object against the class and the current 

276 :class:`.Session` when called. 

277 

278 .. legacy:: The :meth:`_orm.scoped_session.query_property` accessor 

279 is specific to the legacy :class:`.Query` object and is not 

280 considered to be part of :term:`2.0-style` ORM use. 

281 

282 e.g.:: 

283 

284 from sqlalchemy.orm import QueryPropertyDescriptor 

285 from sqlalchemy.orm import scoped_session 

286 from sqlalchemy.orm import sessionmaker 

287 

288 Session = scoped_session(sessionmaker()) 

289 

290 

291 class MyClass: 

292 query: QueryPropertyDescriptor = Session.query_property() 

293 

294 

295 # after mappers are defined 

296 result = MyClass.query.filter(MyClass.name == "foo").all() 

297 

298 Produces instances of the session's configured query class by 

299 default. To override and use a custom implementation, provide 

300 a ``query_cls`` callable. The callable will be invoked with 

301 the class's mapper as a positional argument and a session 

302 keyword argument. 

303 

304 There is no limit to the number of query properties placed on 

305 a class. 

306 

307 """ 

308 

309 class query: 

310 def __get__(s, instance: Any, owner: Type[_O]) -> Query[_O]: 

311 if query_cls: 

312 # custom query class 

313 return query_cls(owner, session=self.registry()) # type: ignore # noqa: E501 

314 else: 

315 # session's configured query class 

316 return self.registry().query(owner) 

317 

318 return query() 

319 

320 # START PROXY METHODS scoped_session 

321 

322 # code within this block is **programmatically, 

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

324 

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

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

327 

328 .. container:: class_bases 

329 

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

331 behalf of the :class:`_orm.scoping.scoped_session` class. 

332 

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

334 result of True. 

335 

336 

337 """ # noqa: E501 

338 

339 return self._proxied.__contains__(instance) 

340 

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

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

343 Session. 

344 

345 .. container:: class_bases 

346 

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

348 behalf of the :class:`_orm.scoping.scoped_session` class. 

349 

350 

351 """ # noqa: E501 

352 

353 return self._proxied.__iter__() 

354 

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

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

357 

358 .. container:: class_bases 

359 

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

361 behalf of the :class:`_orm.scoping.scoped_session` class. 

362 

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

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

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

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

367 

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

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

370 state directly. 

371 

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

373 objects which were transient when they were passed to 

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

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

376 :class:`_orm.Session`. 

377 

378 .. seealso:: 

379 

380 :meth:`_orm.Session.add_all` 

381 

382 :ref:`session_adding` - at :ref:`session_basics` 

383 

384 

385 """ # noqa: E501 

386 

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

388 

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

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

391 

392 .. container:: class_bases 

393 

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

395 behalf of the :class:`_orm.scoping.scoped_session` class. 

396 

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

398 behavioral description. 

399 

400 .. seealso:: 

401 

402 :meth:`_orm.Session.add` 

403 

404 :ref:`session_adding` - at :ref:`session_basics` 

405 

406 

407 """ # noqa: E501 

408 

409 return self._proxied.add_all(instances) 

410 

411 def begin(self, nested: bool = False) -> SessionTransaction: 

412 r"""Begin a transaction, or nested transaction, 

413 on this :class:`.Session`, if one is not already begun. 

414 

415 .. container:: class_bases 

416 

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

418 behalf of the :class:`_orm.scoping.scoped_session` class. 

419 

420 The :class:`_orm.Session` object features **autobegin** behavior, 

421 so that normally it is not necessary to call the 

422 :meth:`_orm.Session.begin` 

423 method explicitly. However, it may be used in order to control 

424 the scope of when the transactional state is begun. 

425 

426 When used to begin the outermost transaction, an error is raised 

427 if this :class:`.Session` is already inside of a transaction. 

428 

429 :param nested: if True, begins a SAVEPOINT transaction and is 

430 equivalent to calling :meth:`~.Session.begin_nested`. For 

431 documentation on SAVEPOINT transactions, please see 

432 :ref:`session_begin_nested`. 

433 

434 :return: the :class:`.SessionTransaction` object. Note that 

435 :class:`.SessionTransaction` 

436 acts as a Python context manager, allowing :meth:`.Session.begin` 

437 to be used in a "with" block. See :ref:`session_explicit_begin` for 

438 an example. 

439 

440 .. seealso:: 

441 

442 :ref:`session_autobegin` 

443 

444 :ref:`unitofwork_transaction` 

445 

446 :meth:`.Session.begin_nested` 

447 

448 

449 

450 """ # noqa: E501 

451 

452 return self._proxied.begin(nested=nested) 

453 

454 def begin_nested(self) -> SessionTransaction: 

455 r"""Begin a "nested" transaction on this Session, e.g. SAVEPOINT. 

456 

457 .. container:: class_bases 

458 

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

460 behalf of the :class:`_orm.scoping.scoped_session` class. 

461 

462 The target database(s) and associated drivers must support SQL 

463 SAVEPOINT for this method to function correctly. 

464 

465 For documentation on SAVEPOINT 

466 transactions, please see :ref:`session_begin_nested`. 

467 

468 :return: the :class:`.SessionTransaction` object. Note that 

469 :class:`.SessionTransaction` acts as a context manager, allowing 

470 :meth:`.Session.begin_nested` to be used in a "with" block. 

471 See :ref:`session_begin_nested` for a usage example. 

472 

473 .. seealso:: 

474 

475 :ref:`session_begin_nested` 

476 

477 :ref:`pysqlite_serializable` - special workarounds required 

478 with the SQLite driver in order for SAVEPOINT to work 

479 correctly. For asyncio use cases, see the section 

480 :ref:`aiosqlite_serializable`. 

481 

482 

483 """ # noqa: E501 

484 

485 return self._proxied.begin_nested() 

486 

487 def close(self) -> None: 

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

489 :class:`_orm.Session`. 

490 

491 .. container:: class_bases 

492 

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

494 behalf of the :class:`_orm.scoping.scoped_session` class. 

495 

496 This expunges all ORM objects associated with this 

497 :class:`_orm.Session`, ends any transaction in progress and 

498 :term:`releases` any :class:`_engine.Connection` objects which this 

499 :class:`_orm.Session` itself has checked out from associated 

500 :class:`_engine.Engine` objects. The operation then leaves the 

501 :class:`_orm.Session` in a state which it may be used again. 

502 

503 .. tip:: 

504 

505 In the default running mode the :meth:`_orm.Session.close` 

506 method **does not prevent the Session from being used again**. 

507 The :class:`_orm.Session` itself does not actually have a 

508 distinct "closed" state; it merely means 

509 the :class:`_orm.Session` will release all database connections 

510 and ORM objects. 

511 

512 Setting the parameter :paramref:`_orm.Session.close_resets_only` 

513 to ``False`` will instead make the ``close`` final, meaning that 

514 any further action on the session will be forbidden. 

515 

516 .. versionchanged:: 1.4 The :meth:`.Session.close` method does not 

517 immediately create a new :class:`.SessionTransaction` object; 

518 instead, the new :class:`.SessionTransaction` is created only if 

519 the :class:`.Session` is used again for a database operation. 

520 

521 .. seealso:: 

522 

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

524 :meth:`_orm.Session.close` and :meth:`_orm.Session.reset`. 

525 

526 :meth:`_orm.Session.reset` - a similar method that behaves like 

527 ``close()`` with the parameter 

528 :paramref:`_orm.Session.close_resets_only` set to ``True``. 

529 

530 

531 """ # noqa: E501 

532 

533 return self._proxied.close() 

534 

535 def reset(self) -> None: 

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

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

538 

539 .. container:: class_bases 

540 

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

542 behalf of the :class:`_orm.scoping.scoped_session` class. 

543 

544 This method provides for same "reset-only" behavior that the 

545 :meth:`_orm.Session.close` method has provided historically, where the 

546 state of the :class:`_orm.Session` is reset as though the object were 

547 brand new, and ready to be used again. 

548 This method may then be useful for :class:`_orm.Session` objects 

549 which set :paramref:`_orm.Session.close_resets_only` to ``False``, 

550 so that "reset only" behavior is still available. 

551 

552 .. versionadded:: 2.0.22 

553 

554 .. seealso:: 

555 

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

557 :meth:`_orm.Session.close` and :meth:`_orm.Session.reset`. 

558 

559 :meth:`_orm.Session.close` - a similar method will additionally 

560 prevent reuse of the Session when the parameter 

561 :paramref:`_orm.Session.close_resets_only` is set to ``False``. 

562 

563 """ # noqa: E501 

564 

565 return self._proxied.reset() 

566 

567 def commit(self) -> None: 

568 r"""Flush pending changes and commit the current transaction. 

569 

570 .. container:: class_bases 

571 

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

573 behalf of the :class:`_orm.scoping.scoped_session` class. 

574 

575 When the COMMIT operation is complete, all objects are fully 

576 :term:`expired`, erasing their internal contents, which will be 

577 automatically re-loaded when the objects are next accessed. In the 

578 interim, these objects are in an expired state and will not function if 

579 they are :term:`detached` from the :class:`.Session`. Additionally, 

580 this re-load operation is not supported when using asyncio-oriented 

581 APIs. The :paramref:`.Session.expire_on_commit` parameter may be used 

582 to disable this behavior. 

583 

584 When there is no transaction in place for the :class:`.Session`, 

585 indicating that no operations were invoked on this :class:`.Session` 

586 since the previous call to :meth:`.Session.commit`, the method will 

587 begin and commit an internal-only "logical" transaction, that does not 

588 normally affect the database unless pending flush changes were 

589 detected, but will still invoke event handlers and object expiration 

590 rules. 

591 

592 The outermost database transaction is committed unconditionally, 

593 automatically releasing any SAVEPOINTs in effect. 

594 

595 .. seealso:: 

596 

597 :ref:`session_committing` 

598 

599 :ref:`unitofwork_transaction` 

600 

601 :ref:`asyncio_orm_avoid_lazyloads` 

602 

603 

604 """ # noqa: E501 

605 

606 return self._proxied.commit() 

607 

608 def connection( 

609 self, 

610 bind_arguments: Optional[_BindArguments] = None, 

611 execution_options: Optional[CoreExecuteOptionsParameter] = None, 

612 ) -> Connection: 

613 r"""Return a :class:`_engine.Connection` object corresponding to this 

614 :class:`.Session` object's transactional state. 

615 

616 .. container:: class_bases 

617 

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

619 behalf of the :class:`_orm.scoping.scoped_session` class. 

620 

621 Either the :class:`_engine.Connection` corresponding to the current 

622 transaction is returned, or if no transaction is in progress, a new 

623 one is begun and the :class:`_engine.Connection` 

624 returned (note that no 

625 transactional state is established with the DBAPI until the first 

626 SQL statement is emitted). 

627 

628 Ambiguity in multi-bind or unbound :class:`.Session` objects can be 

629 resolved through any of the optional keyword arguments. This 

630 ultimately makes usage of the :meth:`.get_bind` method for resolution. 

631 

632 :param bind_arguments: dictionary of bind arguments. May include 

633 "mapper", "bind", "clause", other custom arguments that are passed 

634 to :meth:`.Session.get_bind`. 

635 

636 :param execution_options: a dictionary of execution options that will 

637 be passed to :meth:`_engine.Connection.execution_options`, **when the 

638 connection is first procured only**. If the connection is already 

639 present within the :class:`.Session`, a warning is emitted and 

640 the arguments are ignored. 

641 

642 .. seealso:: 

643 

644 :ref:`session_transaction_isolation` 

645 

646 

647 """ # noqa: E501 

648 

649 return self._proxied.connection( 

650 bind_arguments=bind_arguments, execution_options=execution_options 

651 ) 

652 

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

654 r"""Mark an instance as deleted. 

655 

656 .. container:: class_bases 

657 

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

659 behalf of the :class:`_orm.scoping.scoped_session` class. 

660 

661 The object is assumed to be either :term:`persistent` or 

662 :term:`detached` when passed; after the method is called, the 

663 object will remain in the :term:`persistent` state until the next 

664 flush proceeds. During this time, the object will also be a member 

665 of the :attr:`_orm.Session.deleted` collection. 

666 

667 When the next flush proceeds, the object will move to the 

668 :term:`deleted` state, indicating a ``DELETE`` statement was emitted 

669 for its row within the current transaction. When the transaction 

670 is successfully committed, 

671 the deleted object is moved to the :term:`detached` state and is 

672 no longer present within this :class:`_orm.Session`. 

673 

674 .. seealso:: 

675 

676 :ref:`session_deleting` - at :ref:`session_basics` 

677 

678 :meth:`.Session.delete_all` - multiple instance version 

679 

680 

681 """ # noqa: E501 

682 

683 return self._proxied.delete(instance) 

684 

685 def delete_all(self, instances: Iterable[object]) -> None: 

686 r"""Calls :meth:`.Session.delete` on multiple instances. 

687 

688 .. container:: class_bases 

689 

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

691 behalf of the :class:`_orm.scoping.scoped_session` class. 

692 

693 .. seealso:: 

694 

695 :meth:`.Session.delete` - main documentation on delete 

696 

697 .. versionadded:: 2.1 

698 

699 

700 """ # noqa: E501 

701 

702 return self._proxied.delete_all(instances) 

703 

704 @overload 

705 def execute( 

706 self, 

707 statement: TypedReturnsRows[Unpack[_Ts]], 

708 params: Optional[_CoreAnyExecuteParams] = None, 

709 *, 

710 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

711 bind_arguments: Optional[_BindArguments] = None, 

712 _parent_execute_state: Optional[Any] = None, 

713 _add_event: Optional[Any] = None, 

714 ) -> Result[Unpack[_Ts]]: ... 

715 

716 @overload 

717 def execute( 

718 self, 

719 statement: Executable, 

720 params: Optional[_CoreAnyExecuteParams] = None, 

721 *, 

722 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

723 bind_arguments: Optional[_BindArguments] = None, 

724 _parent_execute_state: Optional[Any] = None, 

725 _add_event: Optional[Any] = None, 

726 ) -> Result[Unpack[TupleAny]]: ... 

727 

728 def execute( 

729 self, 

730 statement: Executable, 

731 params: Optional[_CoreAnyExecuteParams] = None, 

732 *, 

733 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

734 bind_arguments: Optional[_BindArguments] = None, 

735 _parent_execute_state: Optional[Any] = None, 

736 _add_event: Optional[Any] = None, 

737 ) -> Result[Unpack[TupleAny]]: 

738 r"""Execute a SQL expression construct. 

739 

740 .. container:: class_bases 

741 

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

743 behalf of the :class:`_orm.scoping.scoped_session` class. 

744 

745 Returns a :class:`_engine.Result` object representing 

746 results of the statement execution. 

747 

748 E.g.:: 

749 

750 from sqlalchemy import select 

751 

752 result = session.execute(select(User).where(User.id == 5)) 

753 

754 The API contract of :meth:`_orm.Session.execute` is similar to that 

755 of :meth:`_engine.Connection.execute`, the :term:`2.0 style` version 

756 of :class:`_engine.Connection`. 

757 

758 .. versionchanged:: 1.4 the :meth:`_orm.Session.execute` method is 

759 now the primary point of ORM statement execution when using 

760 :term:`2.0 style` ORM usage. 

761 

762 :param statement: 

763 An executable statement (i.e. an :class:`.Executable` expression 

764 such as :func:`_expression.select`). 

765 

766 :param params: 

767 Optional dictionary, or list of dictionaries, containing 

768 bound parameter values. If a single dictionary, single-row 

769 execution occurs; if a list of dictionaries, an 

770 "executemany" will be invoked. The keys in each dictionary 

771 must correspond to parameter names present in the statement. 

772 

773 :param execution_options: optional dictionary of execution options, 

774 which will be associated with the statement execution. This 

775 dictionary can provide a subset of the options that are accepted 

776 by :meth:`_engine.Connection.execution_options`, and may also 

777 provide additional options understood only in an ORM context. 

778 

779 The execution_options are passed along to methods like 

780 :meth:`.Connection.execute` on :class:`.Connection` giving the 

781 highest priority to execution_options that are passed to this 

782 method explicitly, then the options that are present on the 

783 statement object if any, and finally those options present 

784 session-wide. 

785 

786 .. seealso:: 

787 

788 :ref:`orm_queryguide_execution_options` - ORM-specific execution 

789 options 

790 

791 :param bind_arguments: dictionary of additional arguments to determine 

792 the bind. May include "mapper", "bind", or other custom arguments. 

793 Contents of this dictionary are passed to the 

794 :meth:`.Session.get_bind` method. 

795 

796 :return: a :class:`_engine.Result` object. 

797 

798 

799 

800 """ # noqa: E501 

801 

802 return self._proxied.execute( 

803 statement, 

804 params=params, 

805 execution_options=execution_options, 

806 bind_arguments=bind_arguments, 

807 _parent_execute_state=_parent_execute_state, 

808 _add_event=_add_event, 

809 ) 

810 

811 def expire( 

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

813 ) -> None: 

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

815 

816 .. container:: class_bases 

817 

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

819 behalf of the :class:`_orm.scoping.scoped_session` class. 

820 

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

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

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

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

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

826 previously read in that same transaction, regardless of changes 

827 in database state outside of that transaction. 

828 

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

830 use :meth:`Session.expire_all`. 

831 

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

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

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

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

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

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

838 transaction. 

839 

840 :param instance: The instance to be refreshed. 

841 :param attribute_names: optional list of string attribute names 

842 indicating a subset of attributes to be expired. 

843 

844 .. seealso:: 

845 

846 :ref:`session_expire` - introductory material 

847 

848 :meth:`.Session.expire` 

849 

850 :meth:`.Session.refresh` 

851 

852 :meth:`_orm.Query.populate_existing` 

853 

854 

855 """ # noqa: E501 

856 

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

858 

859 def expire_all(self) -> None: 

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

861 

862 .. container:: class_bases 

863 

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

865 behalf of the :class:`_orm.scoping.scoped_session` class. 

866 

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

868 a query will be issued using the 

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

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

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

872 previously read in that same transaction, regardless of changes 

873 in database state outside of that transaction. 

874 

875 To expire individual objects and individual attributes 

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

877 

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

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

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

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

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

883 assuming the transaction is isolated. 

884 

885 .. seealso:: 

886 

887 :ref:`session_expire` - introductory material 

888 

889 :meth:`.Session.expire` 

890 

891 :meth:`.Session.refresh` 

892 

893 :meth:`_orm.Query.populate_existing` 

894 

895 

896 """ # noqa: E501 

897 

898 return self._proxied.expire_all() 

899 

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

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

902 

903 .. container:: class_bases 

904 

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

906 behalf of the :class:`_orm.scoping.scoped_session` class. 

907 

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

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

910 

911 

912 """ # noqa: E501 

913 

914 return self._proxied.expunge(instance) 

915 

916 def expunge_all(self) -> None: 

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

918 

919 .. container:: class_bases 

920 

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

922 behalf of the :class:`_orm.scoping.scoped_session` class. 

923 

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

925 ``Session``. 

926 

927 

928 """ # noqa: E501 

929 

930 return self._proxied.expunge_all() 

931 

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

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

934 

935 .. container:: class_bases 

936 

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

938 behalf of the :class:`_orm.scoping.scoped_session` class. 

939 

940 Writes out all pending object creations, deletions and modifications 

941 to the database as INSERTs, DELETEs, UPDATEs, etc. Operations are 

942 automatically ordered by the Session's unit of work dependency 

943 solver. 

944 

945 Database operations will be issued in the current transactional 

946 context and do not affect the state of the transaction, unless an 

947 error occurs, in which case the entire transaction is rolled back. 

948 You may flush() as often as you like within a transaction to move 

949 changes from Python to the database's transaction buffer. 

950 

951 :param objects: Optional; restricts the flush operation to operate 

952 only on elements that are in the given collection. 

953 

954 This feature is for an extremely narrow set of use cases where 

955 particular objects may need to be operated upon before the 

956 full flush() occurs. It is not intended for general use. 

957 

958 .. deprecated:: 2.1 

959 

960 

961 """ # noqa: E501 

962 

963 return self._proxied.flush(objects=objects) 

964 

965 def get( 

966 self, 

967 entity: _EntityBindKey[_O], 

968 ident: _PKIdentityArgument, 

969 *, 

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

971 populate_existing: bool | None = None, 

972 with_for_update: ForUpdateParameter = None, 

973 identity_token: Optional[Any] = None, 

974 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

975 bind_arguments: Optional[_BindArguments] = None, 

976 ) -> Optional[_O]: 

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

978 or ``None`` if not found. 

979 

980 .. container:: class_bases 

981 

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

983 behalf of the :class:`_orm.scoping.scoped_session` class. 

984 

985 E.g.:: 

986 

987 my_user = session.get(User, 5) 

988 

989 some_object = session.get(VersionedFoo, (5, 10)) 

990 

991 some_object = session.get(VersionedFoo, {"id": 5, "version_id": 10}) 

992 

993 .. versionadded:: 1.4 Added :meth:`_orm.Session.get`, which is moved 

994 from the now legacy :meth:`_orm.Query.get` method. 

995 

996 :meth:`_orm.Session.get` is special in that it provides direct 

997 access to the identity map of the :class:`.Session`. 

998 If the given primary key identifier is present 

999 in the local identity map, the object is returned 

1000 directly from this collection and no SQL is emitted, 

1001 unless the object has been marked fully expired. 

1002 If not present, 

1003 a SELECT is performed in order to locate the object. 

1004 

1005 :meth:`_orm.Session.get` also will perform a check if 

1006 the object is present in the identity map and 

1007 marked as expired - a SELECT 

1008 is emitted to refresh the object as well as to 

1009 ensure that the row is still present. 

1010 If not, :class:`~sqlalchemy.orm.exc.ObjectDeletedError` is raised. 

1011 

1012 :param entity: a mapped class or :class:`.Mapper` indicating the 

1013 type of entity to be loaded. 

1014 

1015 :param ident: A scalar, tuple, or dictionary representing the 

1016 primary key. For a composite (e.g. multiple column) primary key, 

1017 a tuple or dictionary should be passed. 

1018 

1019 For a single-column primary key, the scalar calling form is typically 

1020 the most expedient. If the primary key of a row is the value "5", 

1021 the call looks like:: 

1022 

1023 my_object = session.get(SomeClass, 5) 

1024 

1025 The tuple form contains primary key values typically in 

1026 the order in which they correspond to the mapped 

1027 :class:`_schema.Table` 

1028 object's primary key columns, or if the 

1029 :paramref:`_orm.Mapper.primary_key` configuration parameter were 

1030 used, in 

1031 the order used for that parameter. For example, if the primary key 

1032 of a row is represented by the integer 

1033 digits "5, 10" the call would look like:: 

1034 

1035 my_object = session.get(SomeClass, (5, 10)) 

1036 

1037 The dictionary form should include as keys the mapped attribute names 

1038 corresponding to each element of the primary key. If the mapped class 

1039 has the attributes ``id``, ``version_id`` as the attributes which 

1040 store the object's primary key value, the call would look like:: 

1041 

1042 my_object = session.get(SomeClass, {"id": 5, "version_id": 10}) 

1043 

1044 :param options: optional sequence of loader options which will be 

1045 applied to the query, if one is emitted. 

1046 

1047 :param populate_existing: causes the method to unconditionally emit 

1048 a SQL query and refresh the object with the newly loaded data, 

1049 regardless of whether or not the object is already present. 

1050 Setting this flag takes precedence over passing it as an 

1051 execution option. 

1052 

1053 :param with_for_update: optional boolean ``True`` indicating FOR UPDATE 

1054 should be used, or may be a dictionary containing flags to 

1055 indicate a more specific set of FOR UPDATE flags for the SELECT; 

1056 flags should match the parameters of 

1057 :meth:`_query.Query.with_for_update`. 

1058 Supersedes the :paramref:`.Session.refresh.lockmode` parameter. 

1059 

1060 :param execution_options: optional dictionary of execution options, 

1061 which will be associated with the query execution if one is emitted. 

1062 This dictionary can provide a subset of the options that are 

1063 accepted by :meth:`_engine.Connection.execution_options`, and may 

1064 also provide additional options understood only in an ORM context. 

1065 

1066 .. versionadded:: 1.4.29 

1067 

1068 .. seealso:: 

1069 

1070 :ref:`orm_queryguide_execution_options` - ORM-specific execution 

1071 options 

1072 

1073 :param bind_arguments: dictionary of additional arguments to determine 

1074 the bind. May include "mapper", "bind", or other custom arguments. 

1075 Contents of this dictionary are passed to the 

1076 :meth:`.Session.get_bind` method. 

1077 

1078 .. versionadded:: 2.0.0rc1 

1079 

1080 :return: The object instance, or ``None``. 

1081 

1082 

1083 """ # noqa: E501 

1084 

1085 return self._proxied.get( 

1086 entity, 

1087 ident, 

1088 options=options, 

1089 populate_existing=populate_existing, 

1090 with_for_update=with_for_update, 

1091 identity_token=identity_token, 

1092 execution_options=execution_options, 

1093 bind_arguments=bind_arguments, 

1094 ) 

1095 

1096 def get_one( 

1097 self, 

1098 entity: _EntityBindKey[_O], 

1099 ident: _PKIdentityArgument, 

1100 *, 

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

1102 populate_existing: bool | None = None, 

1103 with_for_update: ForUpdateParameter = None, 

1104 identity_token: Optional[Any] = None, 

1105 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1106 bind_arguments: Optional[_BindArguments] = None, 

1107 ) -> _O: 

1108 r"""Return exactly one instance based on the given primary key 

1109 identifier, or raise an exception if not found. 

1110 

1111 .. container:: class_bases 

1112 

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

1114 behalf of the :class:`_orm.scoping.scoped_session` class. 

1115 

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

1117 

1118 For a detailed documentation of the arguments see the 

1119 method :meth:`.Session.get`. 

1120 

1121 .. versionadded:: 2.0.22 

1122 

1123 :return: The object instance. 

1124 

1125 .. seealso:: 

1126 

1127 :meth:`.Session.get` - equivalent method that instead 

1128 returns ``None`` if no row was found with the provided primary 

1129 key 

1130 

1131 

1132 """ # noqa: E501 

1133 

1134 return self._proxied.get_one( 

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 bind_arguments=bind_arguments, 

1143 ) 

1144 

1145 def get_bind( 

1146 self, 

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

1148 *, 

1149 clause: Optional[ClauseElement] = None, 

1150 bind: Optional[_SessionBind] = None, 

1151 _sa_skip_events: Optional[bool] = None, 

1152 _sa_skip_for_implicit_returning: bool = False, 

1153 **kw: Any, 

1154 ) -> Union[Engine, Connection]: 

1155 r"""Return a "bind" to which this :class:`.Session` is bound. 

1156 

1157 .. container:: class_bases 

1158 

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

1160 behalf of the :class:`_orm.scoping.scoped_session` class. 

1161 

1162 The "bind" is usually an instance of :class:`_engine.Engine`, 

1163 except in the case where the :class:`.Session` has been 

1164 explicitly bound directly to a :class:`_engine.Connection`. 

1165 

1166 For a multiply-bound or unbound :class:`.Session`, the 

1167 ``mapper`` or ``clause`` arguments are used to determine the 

1168 appropriate bind to return. 

1169 

1170 Note that the "mapper" argument is usually present 

1171 when :meth:`.Session.get_bind` is called via an ORM 

1172 operation such as a :meth:`.Session.query`, each 

1173 individual INSERT/UPDATE/DELETE operation within a 

1174 :meth:`.Session.flush`, call, etc. 

1175 

1176 The order of resolution is: 

1177 

1178 1. if mapper given and :paramref:`.Session.binds` is present, 

1179 locate a bind based first on the mapper in use, then 

1180 on the mapped class in use, then on any base classes that are 

1181 present in the ``__mro__`` of the mapped class, from more specific 

1182 superclasses to more general. 

1183 2. if clause given and ``Session.binds`` is present, 

1184 locate a bind based on :class:`_schema.Table` objects 

1185 found in the given clause present in ``Session.binds``. 

1186 3. if ``Session.binds`` is present, return that. 

1187 4. if clause given, attempt to return a bind 

1188 linked to the :class:`_schema.MetaData` ultimately 

1189 associated with the clause. 

1190 5. if mapper given, attempt to return a bind 

1191 linked to the :class:`_schema.MetaData` ultimately 

1192 associated with the :class:`_schema.Table` or other 

1193 selectable to which the mapper is mapped. 

1194 6. No bind can be found, :exc:`~sqlalchemy.exc.UnboundExecutionError` 

1195 is raised. 

1196 

1197 Note that the :meth:`.Session.get_bind` method can be overridden on 

1198 a user-defined subclass of :class:`.Session` to provide any kind 

1199 of bind resolution scheme. See the example at 

1200 :ref:`session_custom_partitioning`. 

1201 

1202 :param mapper: 

1203 Optional mapped class or corresponding :class:`_orm.Mapper` instance. 

1204 The bind can be derived from a :class:`_orm.Mapper` first by 

1205 consulting the "binds" map associated with this :class:`.Session`, 

1206 and secondly by consulting the :class:`_schema.MetaData` associated 

1207 with the :class:`_schema.Table` to which the :class:`_orm.Mapper` is 

1208 mapped for a bind. 

1209 

1210 :param clause: 

1211 A :class:`_expression.ClauseElement` (i.e. 

1212 :func:`_expression.select`, 

1213 :func:`_expression.text`, 

1214 etc.). If the ``mapper`` argument is not present or could not 

1215 produce a bind, the given expression construct will be searched 

1216 for a bound element, typically a :class:`_schema.Table` 

1217 associated with 

1218 bound :class:`_schema.MetaData`. 

1219 

1220 .. seealso:: 

1221 

1222 :ref:`session_partitioning` 

1223 

1224 :paramref:`.Session.binds` 

1225 

1226 :meth:`.Session.bind_mapper` 

1227 

1228 :meth:`.Session.bind_table` 

1229 

1230 

1231 """ # noqa: E501 

1232 

1233 return self._proxied.get_bind( 

1234 mapper=mapper, 

1235 clause=clause, 

1236 bind=bind, 

1237 _sa_skip_events=_sa_skip_events, 

1238 _sa_skip_for_implicit_returning=_sa_skip_for_implicit_returning, 

1239 **kw, 

1240 ) 

1241 

1242 def is_modified( 

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

1244 ) -> bool: 

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

1246 modified attributes. 

1247 

1248 .. container:: class_bases 

1249 

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

1251 behalf of the :class:`_orm.scoping.scoped_session` class. 

1252 

1253 This method retrieves the history for each instrumented 

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

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

1256 

1257 It is in effect a more expensive and accurate 

1258 version of checking for the given instance in the 

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

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

1261 

1262 E.g.:: 

1263 

1264 return session.is_modified(someobject) 

1265 

1266 A few caveats to this method apply: 

1267 

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

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

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

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

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

1273 change here. 

1274 * Scalar attributes may not have recorded the previously set 

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

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

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

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

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

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

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

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

1283 expensive on average than issuing a defensive SELECT. 

1284 

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

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

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

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

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

1290 argument with :func:`.column_property`. 

1291 

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

1293 :param include_collections: Indicates if multivalued collections 

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

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

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

1297 instance upon flush. 

1298 

1299 

1300 """ # noqa: E501 

1301 

1302 return self._proxied.is_modified( 

1303 instance, include_collections=include_collections 

1304 ) 

1305 

1306 def bulk_save_objects( 

1307 self, 

1308 objects: Iterable[object], 

1309 return_defaults: bool = False, 

1310 update_changed_only: bool = True, 

1311 preserve_order: bool = True, 

1312 ) -> None: 

1313 r"""Perform a bulk save of the given list of objects. 

1314 

1315 .. container:: class_bases 

1316 

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

1318 behalf of the :class:`_orm.scoping.scoped_session` class. 

1319 

1320 .. legacy:: 

1321 

1322 This method is a legacy feature as of the 2.0 series of 

1323 SQLAlchemy. For modern bulk INSERT and UPDATE, see 

1324 the sections :ref:`orm_queryguide_bulk_insert` and 

1325 :ref:`orm_queryguide_bulk_update`. 

1326 

1327 For general INSERT and UPDATE of existing ORM mapped objects, 

1328 prefer standard :term:`unit of work` data management patterns, 

1329 introduced in the :ref:`unified_tutorial` at 

1330 :ref:`tutorial_orm_data_manipulation`. SQLAlchemy 2.0 

1331 now uses :ref:`engine_insertmanyvalues` with modern dialects 

1332 which solves previous issues of bulk INSERT slowness. 

1333 

1334 :param objects: a sequence of mapped object instances. The mapped 

1335 objects are persisted as is, and are **not** associated with the 

1336 :class:`.Session` afterwards. 

1337 

1338 For each object, whether the object is sent as an INSERT or an 

1339 UPDATE is dependent on the same rules used by the :class:`.Session` 

1340 in traditional operation; if the object has the 

1341 :attr:`.InstanceState.key` 

1342 attribute set, then the object is assumed to be "detached" and 

1343 will result in an UPDATE. Otherwise, an INSERT is used. 

1344 

1345 In the case of an UPDATE, statements are grouped based on which 

1346 attributes have changed, and are thus to be the subject of each 

1347 SET clause. If ``update_changed_only`` is False, then all 

1348 attributes present within each object are applied to the UPDATE 

1349 statement, which may help in allowing the statements to be grouped 

1350 together into a larger executemany(), and will also reduce the 

1351 overhead of checking history on attributes. 

1352 

1353 :param return_defaults: when True, rows that are missing values which 

1354 generate defaults, namely integer primary key defaults and sequences, 

1355 will be inserted **one at a time**, so that the primary key value 

1356 is available. In particular this will allow joined-inheritance 

1357 and other multi-table mappings to insert correctly without the need 

1358 to provide primary key values ahead of time; however, 

1359 :paramref:`.Session.bulk_save_objects.return_defaults` **greatly 

1360 reduces the performance gains** of the method overall. It is strongly 

1361 advised to please use the standard :meth:`_orm.Session.add_all` 

1362 approach. 

1363 

1364 :param update_changed_only: when True, UPDATE statements are rendered 

1365 based on those attributes in each state that have logged changes. 

1366 When False, all attributes present are rendered into the SET clause 

1367 with the exception of primary key attributes. 

1368 

1369 :param preserve_order: when True, the order of inserts and updates 

1370 matches exactly the order in which the objects are given. When 

1371 False, common types of objects are grouped into inserts 

1372 and updates, to allow for more batching opportunities. 

1373 

1374 .. seealso:: 

1375 

1376 :doc:`queryguide/dml` 

1377 

1378 :meth:`.Session.bulk_insert_mappings` 

1379 

1380 :meth:`.Session.bulk_update_mappings` 

1381 

1382 

1383 """ # noqa: E501 

1384 

1385 return self._proxied.bulk_save_objects( 

1386 objects, 

1387 return_defaults=return_defaults, 

1388 update_changed_only=update_changed_only, 

1389 preserve_order=preserve_order, 

1390 ) 

1391 

1392 def bulk_insert_mappings( 

1393 self, 

1394 mapper: _EntityBindKey[Any], 

1395 mappings: Iterable[Dict[str, Any]], 

1396 return_defaults: bool = False, 

1397 render_nulls: bool = False, 

1398 ) -> None: 

1399 r"""Perform a bulk insert of the given list of mapping dictionaries. 

1400 

1401 .. container:: class_bases 

1402 

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

1404 behalf of the :class:`_orm.scoping.scoped_session` class. 

1405 

1406 .. legacy:: 

1407 

1408 This method is a legacy feature as of the 2.0 series of 

1409 SQLAlchemy. For modern bulk INSERT and UPDATE, see 

1410 the sections :ref:`orm_queryguide_bulk_insert` and 

1411 :ref:`orm_queryguide_bulk_update`. The 2.0 API shares 

1412 implementation details with this method and adds new features 

1413 as well. 

1414 

1415 :param mapper: a mapped class, or the actual :class:`_orm.Mapper` 

1416 object, 

1417 representing the single kind of object represented within the mapping 

1418 list. 

1419 

1420 :param mappings: a sequence of dictionaries, each one containing the 

1421 state of the mapped row to be inserted, in terms of the attribute 

1422 names on the mapped class. If the mapping refers to multiple tables, 

1423 such as a joined-inheritance mapping, each dictionary must contain all 

1424 keys to be populated into all tables. 

1425 

1426 :param return_defaults: when True, the INSERT process will be altered 

1427 to ensure that newly generated primary key values will be fetched. 

1428 The rationale for this parameter is typically to enable 

1429 :ref:`Joined Table Inheritance <joined_inheritance>` mappings to 

1430 be bulk inserted. 

1431 

1432 .. note:: for backends that don't support RETURNING, the 

1433 :paramref:`_orm.Session.bulk_insert_mappings.return_defaults` 

1434 parameter can significantly decrease performance as INSERT 

1435 statements can no longer be batched. See 

1436 :ref:`engine_insertmanyvalues` 

1437 for background on which backends are affected. 

1438 

1439 :param render_nulls: When True, a value of ``None`` will result 

1440 in a NULL value being included in the INSERT statement, rather 

1441 than the column being omitted from the INSERT. This allows all 

1442 the rows being INSERTed to have the identical set of columns which 

1443 allows the full set of rows to be batched to the DBAPI. Normally, 

1444 each column-set that contains a different combination of NULL values 

1445 than the previous row must omit a different series of columns from 

1446 the rendered INSERT statement, which means it must be emitted as a 

1447 separate statement. By passing this flag, the full set of rows 

1448 are guaranteed to be batchable into one batch; the cost however is 

1449 that server-side defaults which are invoked by an omitted column will 

1450 be skipped, so care must be taken to ensure that these are not 

1451 necessary. 

1452 

1453 .. warning:: 

1454 

1455 When this flag is set, **server side default SQL values will 

1456 not be invoked** for those columns that are inserted as NULL; 

1457 the NULL value will be sent explicitly. Care must be taken 

1458 to ensure that no server-side default functions need to be 

1459 invoked for the operation as a whole. 

1460 

1461 .. seealso:: 

1462 

1463 :doc:`queryguide/dml` 

1464 

1465 :meth:`.Session.bulk_save_objects` 

1466 

1467 :meth:`.Session.bulk_update_mappings` 

1468 

1469 

1470 """ # noqa: E501 

1471 

1472 return self._proxied.bulk_insert_mappings( 

1473 mapper, 

1474 mappings, 

1475 return_defaults=return_defaults, 

1476 render_nulls=render_nulls, 

1477 ) 

1478 

1479 def bulk_update_mappings( 

1480 self, mapper: _EntityBindKey[Any], mappings: Iterable[Dict[str, Any]] 

1481 ) -> None: 

1482 r"""Perform a bulk update of the given list of mapping dictionaries. 

1483 

1484 .. container:: class_bases 

1485 

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

1487 behalf of the :class:`_orm.scoping.scoped_session` class. 

1488 

1489 .. legacy:: 

1490 

1491 This method is a legacy feature as of the 2.0 series of 

1492 SQLAlchemy. For modern bulk INSERT and UPDATE, see 

1493 the sections :ref:`orm_queryguide_bulk_insert` and 

1494 :ref:`orm_queryguide_bulk_update`. The 2.0 API shares 

1495 implementation details with this method and adds new features 

1496 as well. 

1497 

1498 :param mapper: a mapped class, or the actual :class:`_orm.Mapper` 

1499 object, 

1500 representing the single kind of object represented within the mapping 

1501 list. 

1502 

1503 :param mappings: a sequence of dictionaries, each one containing the 

1504 state of the mapped row to be updated, in terms of the attribute names 

1505 on the mapped class. If the mapping refers to multiple tables, such 

1506 as a joined-inheritance mapping, each dictionary may contain keys 

1507 corresponding to all tables. All those keys which are present and 

1508 are not part of the primary key are applied to the SET clause of the 

1509 UPDATE statement; the primary key values, which are required, are 

1510 applied to the WHERE clause. 

1511 

1512 

1513 .. seealso:: 

1514 

1515 :doc:`queryguide/dml` 

1516 

1517 :meth:`.Session.bulk_insert_mappings` 

1518 

1519 :meth:`.Session.bulk_save_objects` 

1520 

1521 

1522 """ # noqa: E501 

1523 

1524 return self._proxied.bulk_update_mappings(mapper, mappings) 

1525 

1526 def merge( 

1527 self, 

1528 instance: _O, 

1529 *, 

1530 load: bool = True, 

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

1532 ) -> _O: 

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

1534 within this :class:`.Session`. 

1535 

1536 .. container:: class_bases 

1537 

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

1539 behalf of the :class:`_orm.scoping.scoped_session` class. 

1540 

1541 :meth:`.Session.merge` examines the primary key attributes of the 

1542 source instance, and attempts to reconcile it with an instance of the 

1543 same primary key in the session. If not found locally, it attempts 

1544 to load the object from the database based on primary key, and if 

1545 none can be located, creates a new instance. The state of each 

1546 attribute on the source instance is then copied to the target 

1547 instance. The resulting target instance is then returned by the 

1548 method; the original source instance is left unmodified, and 

1549 un-associated with the :class:`.Session` if not already. 

1550 

1551 This operation cascades to associated instances if the association is 

1552 mapped with ``cascade="merge"``. 

1553 

1554 See :ref:`unitofwork_merging` for a detailed discussion of merging. 

1555 

1556 :param instance: Instance to be merged. 

1557 :param load: Boolean, when False, :meth:`.merge` switches into 

1558 a "high performance" mode which causes it to forego emitting history 

1559 events as well as all database access. This flag is used for 

1560 cases such as transferring graphs of objects into a :class:`.Session` 

1561 from a second level cache, or to transfer just-loaded objects 

1562 into the :class:`.Session` owned by a worker thread or process 

1563 without re-querying the database. 

1564 

1565 The ``load=False`` use case adds the caveat that the given 

1566 object has to be in a "clean" state, that is, has no pending changes 

1567 to be flushed - even if the incoming object is detached from any 

1568 :class:`.Session`. This is so that when 

1569 the merge operation populates local attributes and 

1570 cascades to related objects and 

1571 collections, the values can be "stamped" onto the 

1572 target object as is, without generating any history or attribute 

1573 events, and without the need to reconcile the incoming data with 

1574 any existing related objects or collections that might not 

1575 be loaded. The resulting objects from ``load=False`` are always 

1576 produced as "clean", so it is only appropriate that the given objects 

1577 should be "clean" as well, else this suggests a mis-use of the 

1578 method. 

1579 :param options: optional sequence of loader options which will be 

1580 applied to the :meth:`_orm.Session.get` method when the merge 

1581 operation loads the existing version of the object from the database. 

1582 

1583 .. versionadded:: 1.4.24 

1584 

1585 

1586 .. seealso:: 

1587 

1588 :func:`.make_transient_to_detached` - provides for an alternative 

1589 means of "merging" a single object into the :class:`.Session` 

1590 

1591 :meth:`.Session.merge_all` - multiple instance version 

1592 

1593 

1594 """ # noqa: E501 

1595 

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

1597 

1598 def merge_all( 

1599 self, 

1600 instances: Iterable[_O], 

1601 *, 

1602 load: bool = True, 

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

1604 ) -> Sequence[_O]: 

1605 r"""Calls :meth:`.Session.merge` on multiple instances. 

1606 

1607 .. container:: class_bases 

1608 

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

1610 behalf of the :class:`_orm.scoping.scoped_session` class. 

1611 

1612 .. seealso:: 

1613 

1614 :meth:`.Session.merge` - main documentation on merge 

1615 

1616 .. versionadded:: 2.1 

1617 

1618 

1619 """ # noqa: E501 

1620 

1621 return self._proxied.merge_all(instances, load=load, options=options) 

1622 

1623 @overload 

1624 def query(self, _entity: _EntityType[_O]) -> Query[_O]: ... 

1625 

1626 @overload 

1627 def query( 

1628 self, _colexpr: TypedColumnsClauseRole[_T] 

1629 ) -> RowReturningQuery[_T]: ... 

1630 

1631 # START OVERLOADED FUNCTIONS self.query RowReturningQuery 2-8 

1632 

1633 # code within this block is **programmatically, 

1634 # statically generated** by tools/generate_tuple_map_overloads.py 

1635 

1636 @overload 

1637 def query( 

1638 self, __ent0: _TCCA[_T0], __ent1: _TCCA[_T1], / 

1639 ) -> RowReturningQuery[_T0, _T1]: ... 

1640 

1641 @overload 

1642 def query( 

1643 self, __ent0: _TCCA[_T0], __ent1: _TCCA[_T1], __ent2: _TCCA[_T2], / 

1644 ) -> RowReturningQuery[_T0, _T1, _T2]: ... 

1645 

1646 @overload 

1647 def query( 

1648 self, 

1649 __ent0: _TCCA[_T0], 

1650 __ent1: _TCCA[_T1], 

1651 __ent2: _TCCA[_T2], 

1652 __ent3: _TCCA[_T3], 

1653 /, 

1654 ) -> RowReturningQuery[_T0, _T1, _T2, _T3]: ... 

1655 

1656 @overload 

1657 def query( 

1658 self, 

1659 __ent0: _TCCA[_T0], 

1660 __ent1: _TCCA[_T1], 

1661 __ent2: _TCCA[_T2], 

1662 __ent3: _TCCA[_T3], 

1663 __ent4: _TCCA[_T4], 

1664 /, 

1665 ) -> RowReturningQuery[_T0, _T1, _T2, _T3, _T4]: ... 

1666 

1667 @overload 

1668 def query( 

1669 self, 

1670 __ent0: _TCCA[_T0], 

1671 __ent1: _TCCA[_T1], 

1672 __ent2: _TCCA[_T2], 

1673 __ent3: _TCCA[_T3], 

1674 __ent4: _TCCA[_T4], 

1675 __ent5: _TCCA[_T5], 

1676 /, 

1677 ) -> RowReturningQuery[_T0, _T1, _T2, _T3, _T4, _T5]: ... 

1678 

1679 @overload 

1680 def query( 

1681 self, 

1682 __ent0: _TCCA[_T0], 

1683 __ent1: _TCCA[_T1], 

1684 __ent2: _TCCA[_T2], 

1685 __ent3: _TCCA[_T3], 

1686 __ent4: _TCCA[_T4], 

1687 __ent5: _TCCA[_T5], 

1688 __ent6: _TCCA[_T6], 

1689 /, 

1690 ) -> RowReturningQuery[_T0, _T1, _T2, _T3, _T4, _T5, _T6]: ... 

1691 

1692 @overload 

1693 def query( 

1694 self, 

1695 __ent0: _TCCA[_T0], 

1696 __ent1: _TCCA[_T1], 

1697 __ent2: _TCCA[_T2], 

1698 __ent3: _TCCA[_T3], 

1699 __ent4: _TCCA[_T4], 

1700 __ent5: _TCCA[_T5], 

1701 __ent6: _TCCA[_T6], 

1702 __ent7: _TCCA[_T7], 

1703 /, 

1704 *entities: _ColumnsClauseArgument[Any], 

1705 ) -> RowReturningQuery[ 

1706 _T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7, Unpack[TupleAny] 

1707 ]: ... 

1708 

1709 # END OVERLOADED FUNCTIONS self.query 

1710 

1711 @overload 

1712 def query( 

1713 self, *entities: _ColumnsClauseArgument[Any], **kwargs: Any 

1714 ) -> Query[Any]: ... 

1715 

1716 def query( 

1717 self, *entities: _ColumnsClauseArgument[Any], **kwargs: Any 

1718 ) -> Query[Any]: 

1719 r"""Return a new :class:`_query.Query` object corresponding to this 

1720 :class:`_orm.Session`. 

1721 

1722 .. container:: class_bases 

1723 

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

1725 behalf of the :class:`_orm.scoping.scoped_session` class. 

1726 

1727 Note that the :class:`_query.Query` object is legacy as of 

1728 SQLAlchemy 2.0; the :func:`_sql.select` construct is now used 

1729 to construct ORM queries. 

1730 

1731 .. seealso:: 

1732 

1733 :ref:`unified_tutorial` 

1734 

1735 :ref:`queryguide_toplevel` 

1736 

1737 :ref:`query_api_toplevel` - legacy API doc 

1738 

1739 

1740 """ # noqa: E501 

1741 

1742 return self._proxied.query(*entities, **kwargs) 

1743 

1744 def refresh( 

1745 self, 

1746 instance: object, 

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

1748 with_for_update: ForUpdateParameter = None, 

1749 ) -> None: 

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

1751 

1752 .. container:: class_bases 

1753 

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

1755 behalf of the :class:`_orm.scoping.scoped_session` class. 

1756 

1757 The selected attributes will first be expired as they would when using 

1758 :meth:`_orm.Session.expire`; then a SELECT statement will be issued to 

1759 the database to refresh column-oriented attributes with the current 

1760 value available in the current transaction. 

1761 

1762 :func:`_orm.relationship` oriented attributes will also be immediately 

1763 loaded if they were already eagerly loaded on the object, using the 

1764 same eager loading strategy that they were loaded with originally. 

1765 

1766 .. versionadded:: 1.4 - the :meth:`_orm.Session.refresh` method 

1767 can also refresh eagerly loaded attributes. 

1768 

1769 :func:`_orm.relationship` oriented attributes that would normally 

1770 load using the ``select`` (or "lazy") loader strategy will also 

1771 load **if they are named explicitly in the attribute_names 

1772 collection**, emitting a SELECT statement for the attribute using the 

1773 ``immediate`` loader strategy. If lazy-loaded relationships are not 

1774 named in :paramref:`_orm.Session.refresh.attribute_names`, then 

1775 they remain as "lazy loaded" attributes and are not implicitly 

1776 refreshed. 

1777 

1778 .. versionchanged:: 2.0.4 The :meth:`_orm.Session.refresh` method 

1779 will now refresh lazy-loaded :func:`_orm.relationship` oriented 

1780 attributes for those which are named explicitly in the 

1781 :paramref:`_orm.Session.refresh.attribute_names` collection. 

1782 

1783 .. tip:: 

1784 

1785 While the :meth:`_orm.Session.refresh` method is capable of 

1786 refreshing both column and relationship oriented attributes, its 

1787 primary focus is on refreshing of local column-oriented attributes 

1788 on a single instance. For more open ended "refresh" functionality, 

1789 including the ability to refresh the attributes on many objects at 

1790 once while having explicit control over relationship loader 

1791 strategies, use the 

1792 :ref:`populate existing <orm_queryguide_populate_existing>` feature 

1793 instead. 

1794 

1795 Note that a highly isolated transaction will return the same values as 

1796 were previously read in that same transaction, regardless of changes 

1797 in database state outside of that transaction. Refreshing 

1798 attributes usually only makes sense at the start of a transaction 

1799 where database rows have not yet been accessed. 

1800 

1801 :param attribute_names: optional. An iterable collection of 

1802 string attribute names indicating a subset of attributes to 

1803 be refreshed. 

1804 

1805 :param with_for_update: optional boolean ``True`` indicating FOR UPDATE 

1806 should be used, or may be a dictionary containing flags to 

1807 indicate a more specific set of FOR UPDATE flags for the SELECT; 

1808 flags should match the parameters of 

1809 :meth:`_query.Query.with_for_update`. 

1810 Supersedes the :paramref:`.Session.refresh.lockmode` parameter. 

1811 

1812 .. seealso:: 

1813 

1814 :ref:`session_expire` - introductory material 

1815 

1816 :meth:`.Session.expire` 

1817 

1818 :meth:`.Session.expire_all` 

1819 

1820 :ref:`orm_queryguide_populate_existing` - allows any ORM query 

1821 to refresh objects as they would be loaded normally. 

1822 

1823 

1824 """ # noqa: E501 

1825 

1826 return self._proxied.refresh( 

1827 instance, 

1828 attribute_names=attribute_names, 

1829 with_for_update=with_for_update, 

1830 ) 

1831 

1832 def rollback(self) -> None: 

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

1834 

1835 .. container:: class_bases 

1836 

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

1838 behalf of the :class:`_orm.scoping.scoped_session` class. 

1839 

1840 If no transaction is in progress, this method is a pass-through. 

1841 

1842 The method always rolls back 

1843 the topmost database transaction, discarding any nested 

1844 transactions that may be in progress. 

1845 

1846 .. seealso:: 

1847 

1848 :ref:`session_rollback` 

1849 

1850 :ref:`unitofwork_transaction` 

1851 

1852 

1853 """ # noqa: E501 

1854 

1855 return self._proxied.rollback() 

1856 

1857 @overload 

1858 def scalar( 

1859 self, 

1860 statement: TypedReturnsRows[Never], 

1861 params: Optional[_CoreSingleExecuteParams] = None, 

1862 *, 

1863 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1864 bind_arguments: Optional[_BindArguments] = None, 

1865 **kw: Any, 

1866 ) -> Optional[Any]: ... 

1867 

1868 @overload 

1869 def scalar( 

1870 self, 

1871 statement: TypedReturnsRows[_T], 

1872 params: Optional[_CoreSingleExecuteParams] = None, 

1873 *, 

1874 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1875 bind_arguments: Optional[_BindArguments] = None, 

1876 **kw: Any, 

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

1878 

1879 @overload 

1880 def scalar( 

1881 self, 

1882 statement: Executable, 

1883 params: Optional[_CoreSingleExecuteParams] = None, 

1884 *, 

1885 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1886 bind_arguments: Optional[_BindArguments] = None, 

1887 **kw: Any, 

1888 ) -> Any: ... 

1889 

1890 def scalar( 

1891 self, 

1892 statement: Executable, 

1893 params: Optional[_CoreSingleExecuteParams] = None, 

1894 *, 

1895 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1896 bind_arguments: Optional[_BindArguments] = None, 

1897 **kw: Any, 

1898 ) -> Any: 

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

1900 

1901 .. container:: class_bases 

1902 

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

1904 behalf of the :class:`_orm.scoping.scoped_session` class. 

1905 

1906 Usage and parameters are the same as that of 

1907 :meth:`_orm.Session.execute`; the return result is a scalar Python 

1908 value. 

1909 

1910 

1911 """ # noqa: E501 

1912 

1913 return self._proxied.scalar( 

1914 statement, 

1915 params=params, 

1916 execution_options=execution_options, 

1917 bind_arguments=bind_arguments, 

1918 **kw, 

1919 ) 

1920 

1921 @overload 

1922 def scalars( 

1923 self, 

1924 statement: TypedReturnsRows[_T], 

1925 params: Optional[_CoreAnyExecuteParams] = None, 

1926 *, 

1927 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1928 bind_arguments: Optional[_BindArguments] = None, 

1929 **kw: Any, 

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

1931 

1932 @overload 

1933 def scalars( 

1934 self, 

1935 statement: Executable, 

1936 params: Optional[_CoreAnyExecuteParams] = None, 

1937 *, 

1938 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1939 bind_arguments: Optional[_BindArguments] = None, 

1940 **kw: Any, 

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

1942 

1943 def scalars( 

1944 self, 

1945 statement: Executable, 

1946 params: Optional[_CoreAnyExecuteParams] = None, 

1947 *, 

1948 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1949 bind_arguments: Optional[_BindArguments] = None, 

1950 **kw: Any, 

1951 ) -> ScalarResult[Any]: 

1952 r"""Execute a statement and return the results as scalars. 

1953 

1954 .. container:: class_bases 

1955 

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

1957 behalf of the :class:`_orm.scoping.scoped_session` class. 

1958 

1959 Usage and parameters are the same as that of 

1960 :meth:`_orm.Session.execute`; the return result is a 

1961 :class:`_result.ScalarResult` filtering object which 

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

1963 

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

1965 

1966 .. versionadded:: 1.4.24 Added :meth:`_orm.Session.scalars` 

1967 

1968 .. versionadded:: 1.4.26 Added :meth:`_orm.scoped_session.scalars` 

1969 

1970 .. seealso:: 

1971 

1972 :ref:`orm_queryguide_select_orm_entities` - contrasts the behavior 

1973 of :meth:`_orm.Session.execute` to :meth:`_orm.Session.scalars` 

1974 

1975 

1976 """ # noqa: E501 

1977 

1978 return self._proxied.scalars( 

1979 statement, 

1980 params=params, 

1981 execution_options=execution_options, 

1982 bind_arguments=bind_arguments, 

1983 **kw, 

1984 ) 

1985 

1986 @property 

1987 def bind(self) -> Optional[Union[Engine, Connection]]: 

1988 r"""Proxy for the :attr:`_orm.Session.bind` attribute 

1989 on behalf of the :class:`_orm.scoping.scoped_session` class. 

1990 

1991 """ # noqa: E501 

1992 

1993 return self._proxied.bind 

1994 

1995 @bind.setter 

1996 def bind(self, attr: Optional[Union[Engine, Connection]]) -> None: 

1997 self._proxied.bind = attr 

1998 

1999 @property 

2000 def dirty(self) -> Any: 

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

2002 

2003 .. container:: class_bases 

2004 

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

2006 on behalf of the :class:`_orm.scoping.scoped_session` class. 

2007 

2008 E.g.:: 

2009 

2010 some_mapped_object in session.dirty 

2011 

2012 Instances are considered dirty when they were modified but not 

2013 deleted. 

2014 

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

2016 attribute-setting or collection modification operations will 

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

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

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

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

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

2022 it's only done at flush time). 

2023 

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

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

2026 

2027 

2028 """ # noqa: E501 

2029 

2030 return self._proxied.dirty 

2031 

2032 @property 

2033 def deleted(self) -> Any: 

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

2035 

2036 .. container:: class_bases 

2037 

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

2039 on behalf of the :class:`_orm.scoping.scoped_session` class. 

2040 

2041 """ # noqa: E501 

2042 

2043 return self._proxied.deleted 

2044 

2045 @property 

2046 def new(self) -> Any: 

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

2048 

2049 .. container:: class_bases 

2050 

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

2052 on behalf of the :class:`_orm.scoping.scoped_session` class. 

2053 

2054 """ # noqa: E501 

2055 

2056 return self._proxied.new 

2057 

2058 @property 

2059 def identity_map(self) -> IdentityMap: 

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

2061 on behalf of the :class:`_orm.scoping.scoped_session` class. 

2062 

2063 """ # noqa: E501 

2064 

2065 return self._proxied.identity_map 

2066 

2067 @identity_map.setter 

2068 def identity_map(self, attr: IdentityMap) -> None: 

2069 self._proxied.identity_map = attr 

2070 

2071 @property 

2072 def is_active(self) -> Any: 

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

2074 

2075 .. container:: class_bases 

2076 

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

2078 on behalf of the :class:`_orm.scoping.scoped_session` class. 

2079 

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

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

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

2083 

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

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

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

2087 fully roll back the transaction. 

2088 

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

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

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

2092 

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

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

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

2096 

2097 .. seealso:: 

2098 

2099 :ref:`faq_session_rollback` 

2100 

2101 :meth:`_orm.Session.in_transaction` 

2102 

2103 

2104 """ # noqa: E501 

2105 

2106 return self._proxied.is_active 

2107 

2108 @property 

2109 def autoflush(self) -> bool: 

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

2111 on behalf of the :class:`_orm.scoping.scoped_session` class. 

2112 

2113 """ # noqa: E501 

2114 

2115 return self._proxied.autoflush 

2116 

2117 @autoflush.setter 

2118 def autoflush(self, attr: bool) -> None: 

2119 self._proxied.autoflush = attr 

2120 

2121 @property 

2122 def no_autoflush(self) -> Any: 

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

2124 

2125 .. container:: class_bases 

2126 

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

2128 on behalf of the :class:`_orm.scoping.scoped_session` class. 

2129 

2130 e.g.:: 

2131 

2132 with session.no_autoflush: 

2133 

2134 some_object = SomeClass() 

2135 session.add(some_object) 

2136 # won't autoflush 

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

2138 

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

2140 will not be subject to flushes occurring upon query 

2141 access. This is useful when initializing a series 

2142 of objects which involve existing database queries, 

2143 where the uncompleted object should not yet be flushed. 

2144 

2145 

2146 """ # noqa: E501 

2147 

2148 return self._proxied.no_autoflush 

2149 

2150 @property 

2151 def info(self) -> Any: 

2152 r"""A user-modifiable dictionary. 

2153 

2154 .. container:: class_bases 

2155 

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

2157 on behalf of the :class:`_orm.scoping.scoped_session` class. 

2158 

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

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

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

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

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

2164 

2165 

2166 """ # noqa: E501 

2167 

2168 return self._proxied.info 

2169 

2170 @property 

2171 def execution_options(self) -> _ExecuteOptions: 

2172 r"""Proxy for the :attr:`_orm.Session.execution_options` attribute 

2173 on behalf of the :class:`_orm.scoping.scoped_session` class. 

2174 

2175 """ # noqa: E501 

2176 

2177 return self._proxied.execution_options 

2178 

2179 @execution_options.setter 

2180 def execution_options(self, attr: _ExecuteOptions) -> None: 

2181 self._proxied.execution_options = attr 

2182 

2183 @classmethod 

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

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

2186 

2187 .. container:: class_bases 

2188 

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

2190 behalf of the :class:`_orm.scoping.scoped_session` class. 

2191 

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

2193 

2194 

2195 """ # noqa: E501 

2196 

2197 return Session.object_session(instance) 

2198 

2199 @classmethod 

2200 def identity_key( 

2201 cls, 

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

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

2204 *, 

2205 instance: Optional[Any] = None, 

2206 row: Optional[Union[Row[Unpack[TupleAny]], RowMapping]] = None, 

2207 identity_token: Optional[Any] = None, 

2208 ) -> _IdentityKeyType[Any]: 

2209 r"""Return an identity key. 

2210 

2211 .. container:: class_bases 

2212 

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

2214 behalf of the :class:`_orm.scoping.scoped_session` class. 

2215 

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

2217 

2218 

2219 """ # noqa: E501 

2220 

2221 return Session.identity_key( 

2222 class_=class_, 

2223 ident=ident, 

2224 instance=instance, 

2225 row=row, 

2226 identity_token=identity_token, 

2227 ) 

2228 

2229 # END PROXY METHODS scoped_session 

2230 

2231 

2232ScopedSession = scoped_session 

2233"""Old name for backwards compatibility."""