Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/scoping.py: 56%

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

257 statements  

1# orm/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 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 TupleAny 

36from ..util.typing import TypeVarTuple 

37from ..util.typing import Unpack 

38 

39if TYPE_CHECKING: 

40 from ._typing import _EntityType 

41 from ._typing import _IdentityKeyType 

42 from ._typing import OrmExecuteOptionsParameter 

43 from .identity import IdentityMap 

44 from .interfaces import ORMOption 

45 from .mapper import Mapper 

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 CursorResult 

56 from ..engine import Engine 

57 from ..engine import Result 

58 from ..engine import Row 

59 from ..engine import RowMapping 

60 from ..engine.interfaces import _CoreAnyExecuteParams 

61 from ..engine.interfaces import _CoreSingleExecuteParams 

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.dml import UpdateBase 

76 from ..sql.elements import ClauseElement 

77 from ..sql.roles import TypedColumnsClauseRole 

78 from ..sql.selectable import ForUpdateParameter 

79 from ..sql.selectable import TypedReturnsRows 

80 

81 

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

83_Ts = TypeVarTuple("_Ts") 

84 

85 

86class QueryPropertyDescriptor(Protocol): 

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

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

89 

90 .. versionadded:: 2.0.5 

91 

92 """ 

93 

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

95 

96 

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

98 

99__all__ = ["scoped_session"] 

100 

101 

102@create_proxy_methods( 

103 Session, 

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

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

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

107 methods=[ 

108 "__contains__", 

109 "__iter__", 

110 "add", 

111 "add_all", 

112 "begin", 

113 "begin_nested", 

114 "close", 

115 "reset", 

116 "commit", 

117 "connection", 

118 "delete", 

119 "delete_all", 

120 "execute", 

121 "expire", 

122 "expire_all", 

123 "expunge", 

124 "expunge_all", 

125 "flush", 

126 "get", 

127 "get_one", 

128 "get_bind", 

129 "is_modified", 

130 "bulk_save_objects", 

131 "bulk_insert_mappings", 

132 "bulk_update_mappings", 

133 "merge", 

134 "merge_all", 

135 "query", 

136 "refresh", 

137 "rollback", 

138 "scalar", 

139 "scalars", 

140 ], 

141 attributes=[ 

142 "bind", 

143 "dirty", 

144 "deleted", 

145 "new", 

146 "identity_map", 

147 "is_active", 

148 "autoflush", 

149 "no_autoflush", 

150 "info", 

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 re-use 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: UpdateBase, 

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 ) -> CursorResult[Unpack[TupleAny]]: ... 

727 

728 @overload 

729 def execute( 

730 self, 

731 statement: Executable, 

732 params: Optional[_CoreAnyExecuteParams] = None, 

733 *, 

734 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

735 bind_arguments: Optional[_BindArguments] = None, 

736 _parent_execute_state: Optional[Any] = None, 

737 _add_event: Optional[Any] = None, 

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

739 

740 def execute( 

741 self, 

742 statement: Executable, 

743 params: Optional[_CoreAnyExecuteParams] = None, 

744 *, 

745 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

746 bind_arguments: Optional[_BindArguments] = None, 

747 _parent_execute_state: Optional[Any] = None, 

748 _add_event: Optional[Any] = None, 

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

750 r"""Execute a SQL expression construct. 

751 

752 .. container:: class_bases 

753 

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

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

756 

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

758 results of the statement execution. 

759 

760 E.g.:: 

761 

762 from sqlalchemy import select 

763 

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

765 

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

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

768 of :class:`_engine.Connection`. 

769 

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

771 now the primary point of ORM statement execution when using 

772 :term:`2.0 style` ORM usage. 

773 

774 :param statement: 

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

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

777 

778 :param params: 

779 Optional dictionary, or list of dictionaries, containing 

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

781 execution occurs; if a list of dictionaries, an 

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

783 must correspond to parameter names present in the statement. 

784 

785 :param execution_options: optional dictionary of execution options, 

786 which will be associated with the statement execution. This 

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

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

789 provide additional options understood only in an ORM context. 

790 

791 .. seealso:: 

792 

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

794 options 

795 

796 :param bind_arguments: dictionary of additional arguments to determine 

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

798 Contents of this dictionary are passed to the 

799 :meth:`.Session.get_bind` method. 

800 

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

802 

803 

804 

805 """ # noqa: E501 

806 

807 return self._proxied.execute( 

808 statement, 

809 params=params, 

810 execution_options=execution_options, 

811 bind_arguments=bind_arguments, 

812 _parent_execute_state=_parent_execute_state, 

813 _add_event=_add_event, 

814 ) 

815 

816 def expire( 

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

818 ) -> None: 

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

820 

821 .. container:: class_bases 

822 

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

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

825 

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

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

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

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

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

831 previously read in that same transaction, regardless of changes 

832 in database state outside of that transaction. 

833 

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

835 use :meth:`Session.expire_all`. 

836 

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

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

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

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

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

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

843 transaction. 

844 

845 :param instance: The instance to be refreshed. 

846 :param attribute_names: optional list of string attribute names 

847 indicating a subset of attributes to be expired. 

848 

849 .. seealso:: 

850 

851 :ref:`session_expire` - introductory material 

852 

853 :meth:`.Session.expire` 

854 

855 :meth:`.Session.refresh` 

856 

857 :meth:`_orm.Query.populate_existing` 

858 

859 

860 """ # noqa: E501 

861 

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

863 

864 def expire_all(self) -> None: 

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

866 

867 .. container:: class_bases 

868 

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

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

871 

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

873 a query will be issued using the 

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

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

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

877 previously read in that same transaction, regardless of changes 

878 in database state outside of that transaction. 

879 

880 To expire individual objects and individual attributes 

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

882 

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

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

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

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

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

888 assuming the transaction is isolated. 

889 

890 .. seealso:: 

891 

892 :ref:`session_expire` - introductory material 

893 

894 :meth:`.Session.expire` 

895 

896 :meth:`.Session.refresh` 

897 

898 :meth:`_orm.Query.populate_existing` 

899 

900 

901 """ # noqa: E501 

902 

903 return self._proxied.expire_all() 

904 

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

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

907 

908 .. container:: class_bases 

909 

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

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

912 

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

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

915 

916 

917 """ # noqa: E501 

918 

919 return self._proxied.expunge(instance) 

920 

921 def expunge_all(self) -> None: 

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

923 

924 .. container:: class_bases 

925 

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

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

928 

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

930 ``Session``. 

931 

932 

933 """ # noqa: E501 

934 

935 return self._proxied.expunge_all() 

936 

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

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

939 

940 .. container:: class_bases 

941 

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

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

944 

945 Writes out all pending object creations, deletions and modifications 

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

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

948 solver. 

949 

950 Database operations will be issued in the current transactional 

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

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

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

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

955 

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

957 only on elements that are in the given collection. 

958 

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

960 particular objects may need to be operated upon before the 

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

962 

963 .. deprecated:: 2.1 

964 

965 

966 """ # noqa: E501 

967 

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

969 

970 def get( 

971 self, 

972 entity: _EntityBindKey[_O], 

973 ident: _PKIdentityArgument, 

974 *, 

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

976 populate_existing: bool = False, 

977 with_for_update: ForUpdateParameter = None, 

978 identity_token: Optional[Any] = None, 

979 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

980 bind_arguments: Optional[_BindArguments] = None, 

981 ) -> Optional[_O]: 

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

983 or ``None`` if not found. 

984 

985 .. container:: class_bases 

986 

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

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

989 

990 E.g.:: 

991 

992 my_user = session.get(User, 5) 

993 

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

995 

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

997 

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

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

1000 

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

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

1003 If the given primary key identifier is present 

1004 in the local identity map, the object is returned 

1005 directly from this collection and no SQL is emitted, 

1006 unless the object has been marked fully expired. 

1007 If not present, 

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

1009 

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

1011 the object is present in the identity map and 

1012 marked as expired - a SELECT 

1013 is emitted to refresh the object as well as to 

1014 ensure that the row is still present. 

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

1016 

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

1018 type of entity to be loaded. 

1019 

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

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

1022 a tuple or dictionary should be passed. 

1023 

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

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

1026 the call looks like:: 

1027 

1028 my_object = session.get(SomeClass, 5) 

1029 

1030 The tuple form contains primary key values typically in 

1031 the order in which they correspond to the mapped 

1032 :class:`_schema.Table` 

1033 object's primary key columns, or if the 

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

1035 used, in 

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

1037 of a row is represented by the integer 

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

1039 

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

1041 

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

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

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

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

1046 

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

1048 

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

1050 applied to the query, if one is emitted. 

1051 

1052 :param populate_existing: causes the method to unconditionally emit 

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

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

1055 

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

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

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

1059 flags should match the parameters of 

1060 :meth:`_query.Query.with_for_update`. 

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

1062 

1063 :param execution_options: optional dictionary of execution options, 

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

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

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

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

1068 

1069 .. versionadded:: 1.4.29 

1070 

1071 .. seealso:: 

1072 

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

1074 options 

1075 

1076 :param bind_arguments: dictionary of additional arguments to determine 

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

1078 Contents of this dictionary are passed to the 

1079 :meth:`.Session.get_bind` method. 

1080 

1081 .. versionadded:: 2.0.0rc1 

1082 

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

1084 

1085 

1086 """ # noqa: E501 

1087 

1088 return self._proxied.get( 

1089 entity, 

1090 ident, 

1091 options=options, 

1092 populate_existing=populate_existing, 

1093 with_for_update=with_for_update, 

1094 identity_token=identity_token, 

1095 execution_options=execution_options, 

1096 bind_arguments=bind_arguments, 

1097 ) 

1098 

1099 def get_one( 

1100 self, 

1101 entity: _EntityBindKey[_O], 

1102 ident: _PKIdentityArgument, 

1103 *, 

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

1105 populate_existing: bool = False, 

1106 with_for_update: ForUpdateParameter = None, 

1107 identity_token: Optional[Any] = None, 

1108 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1109 bind_arguments: Optional[_BindArguments] = None, 

1110 ) -> _O: 

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

1112 identifier, or raise an exception if not found. 

1113 

1114 .. container:: class_bases 

1115 

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

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

1118 

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

1120 

1121 For a detailed documentation of the arguments see the 

1122 method :meth:`.Session.get`. 

1123 

1124 .. versionadded:: 2.0.22 

1125 

1126 :return: The object instance. 

1127 

1128 .. seealso:: 

1129 

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

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

1132 key 

1133 

1134 

1135 """ # noqa: E501 

1136 

1137 return self._proxied.get_one( 

1138 entity, 

1139 ident, 

1140 options=options, 

1141 populate_existing=populate_existing, 

1142 with_for_update=with_for_update, 

1143 identity_token=identity_token, 

1144 execution_options=execution_options, 

1145 bind_arguments=bind_arguments, 

1146 ) 

1147 

1148 def get_bind( 

1149 self, 

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

1151 *, 

1152 clause: Optional[ClauseElement] = None, 

1153 bind: Optional[_SessionBind] = None, 

1154 _sa_skip_events: Optional[bool] = None, 

1155 _sa_skip_for_implicit_returning: bool = False, 

1156 **kw: Any, 

1157 ) -> Union[Engine, Connection]: 

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

1159 

1160 .. container:: class_bases 

1161 

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

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

1164 

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

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

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

1168 

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

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

1171 appropriate bind to return. 

1172 

1173 Note that the "mapper" argument is usually present 

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

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

1176 individual INSERT/UPDATE/DELETE operation within a 

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

1178 

1179 The order of resolution is: 

1180 

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

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

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

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

1185 superclasses to more general. 

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

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

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

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

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

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

1192 associated with the clause. 

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

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

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

1196 selectable to which the mapper is mapped. 

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

1198 is raised. 

1199 

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

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

1202 of bind resolution scheme. See the example at 

1203 :ref:`session_custom_partitioning`. 

1204 

1205 :param mapper: 

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

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

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

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

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

1211 mapped for a bind. 

1212 

1213 :param clause: 

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

1215 :func:`_expression.select`, 

1216 :func:`_expression.text`, 

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

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

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

1220 associated with 

1221 bound :class:`_schema.MetaData`. 

1222 

1223 .. seealso:: 

1224 

1225 :ref:`session_partitioning` 

1226 

1227 :paramref:`.Session.binds` 

1228 

1229 :meth:`.Session.bind_mapper` 

1230 

1231 :meth:`.Session.bind_table` 

1232 

1233 

1234 """ # noqa: E501 

1235 

1236 return self._proxied.get_bind( 

1237 mapper=mapper, 

1238 clause=clause, 

1239 bind=bind, 

1240 _sa_skip_events=_sa_skip_events, 

1241 _sa_skip_for_implicit_returning=_sa_skip_for_implicit_returning, 

1242 **kw, 

1243 ) 

1244 

1245 def is_modified( 

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

1247 ) -> bool: 

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

1249 modified attributes. 

1250 

1251 .. container:: class_bases 

1252 

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

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

1255 

1256 This method retrieves the history for each instrumented 

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

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

1259 

1260 It is in effect a more expensive and accurate 

1261 version of checking for the given instance in the 

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

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

1264 

1265 E.g.:: 

1266 

1267 return session.is_modified(someobject) 

1268 

1269 A few caveats to this method apply: 

1270 

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

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

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

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

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

1276 change here. 

1277 * Scalar attributes may not have recorded the previously set 

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

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

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

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

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

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

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

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

1286 expensive on average than issuing a defensive SELECT. 

1287 

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

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

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

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

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

1293 argument with :func:`.column_property`. 

1294 

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

1296 :param include_collections: Indicates if multivalued collections 

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

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

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

1300 instance upon flush. 

1301 

1302 

1303 """ # noqa: E501 

1304 

1305 return self._proxied.is_modified( 

1306 instance, include_collections=include_collections 

1307 ) 

1308 

1309 def bulk_save_objects( 

1310 self, 

1311 objects: Iterable[object], 

1312 return_defaults: bool = False, 

1313 update_changed_only: bool = True, 

1314 preserve_order: bool = True, 

1315 ) -> None: 

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

1317 

1318 .. container:: class_bases 

1319 

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

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

1322 

1323 .. legacy:: 

1324 

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

1326 SQLAlchemy. For modern bulk INSERT and UPDATE, see 

1327 the sections :ref:`orm_queryguide_bulk_insert` and 

1328 :ref:`orm_queryguide_bulk_update`. 

1329 

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

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

1332 introduced in the :ref:`unified_tutorial` at 

1333 :ref:`tutorial_orm_data_manipulation`. SQLAlchemy 2.0 

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

1335 which solves previous issues of bulk INSERT slowness. 

1336 

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

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

1339 :class:`.Session` afterwards. 

1340 

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

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

1343 in traditional operation; if the object has the 

1344 :attr:`.InstanceState.key` 

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

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

1347 

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

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

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

1351 attributes present within each object are applied to the UPDATE 

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

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

1354 overhead of checking history on attributes. 

1355 

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

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

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

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

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

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

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

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

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

1365 approach. 

1366 

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

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

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

1370 with the exception of primary key attributes. 

1371 

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

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

1374 False, common types of objects are grouped into inserts 

1375 and updates, to allow for more batching opportunities. 

1376 

1377 .. seealso:: 

1378 

1379 :doc:`queryguide/dml` 

1380 

1381 :meth:`.Session.bulk_insert_mappings` 

1382 

1383 :meth:`.Session.bulk_update_mappings` 

1384 

1385 

1386 """ # noqa: E501 

1387 

1388 return self._proxied.bulk_save_objects( 

1389 objects, 

1390 return_defaults=return_defaults, 

1391 update_changed_only=update_changed_only, 

1392 preserve_order=preserve_order, 

1393 ) 

1394 

1395 def bulk_insert_mappings( 

1396 self, 

1397 mapper: Mapper[Any], 

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

1399 return_defaults: bool = False, 

1400 render_nulls: bool = False, 

1401 ) -> None: 

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

1403 

1404 .. container:: class_bases 

1405 

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

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

1408 

1409 .. legacy:: 

1410 

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

1412 SQLAlchemy. For modern bulk INSERT and UPDATE, see 

1413 the sections :ref:`orm_queryguide_bulk_insert` and 

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

1415 implementation details with this method and adds new features 

1416 as well. 

1417 

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

1419 object, 

1420 representing the single kind of object represented within the mapping 

1421 list. 

1422 

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

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

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

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

1427 keys to be populated into all tables. 

1428 

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

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

1431 The rationale for this parameter is typically to enable 

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

1433 be bulk inserted. 

1434 

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

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

1437 parameter can significantly decrease performance as INSERT 

1438 statements can no longer be batched. See 

1439 :ref:`engine_insertmanyvalues` 

1440 for background on which backends are affected. 

1441 

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

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

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

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

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

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

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

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

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

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

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

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

1454 necessary. 

1455 

1456 .. warning:: 

1457 

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

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

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

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

1462 invoked for the operation as a whole. 

1463 

1464 .. seealso:: 

1465 

1466 :doc:`queryguide/dml` 

1467 

1468 :meth:`.Session.bulk_save_objects` 

1469 

1470 :meth:`.Session.bulk_update_mappings` 

1471 

1472 

1473 """ # noqa: E501 

1474 

1475 return self._proxied.bulk_insert_mappings( 

1476 mapper, 

1477 mappings, 

1478 return_defaults=return_defaults, 

1479 render_nulls=render_nulls, 

1480 ) 

1481 

1482 def bulk_update_mappings( 

1483 self, mapper: Mapper[Any], mappings: Iterable[Dict[str, Any]] 

1484 ) -> None: 

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

1486 

1487 .. container:: class_bases 

1488 

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

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

1491 

1492 .. legacy:: 

1493 

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

1495 SQLAlchemy. For modern bulk INSERT and UPDATE, see 

1496 the sections :ref:`orm_queryguide_bulk_insert` and 

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

1498 implementation details with this method and adds new features 

1499 as well. 

1500 

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

1502 object, 

1503 representing the single kind of object represented within the mapping 

1504 list. 

1505 

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

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

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

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

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

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

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

1513 applied to the WHERE clause. 

1514 

1515 

1516 .. seealso:: 

1517 

1518 :doc:`queryguide/dml` 

1519 

1520 :meth:`.Session.bulk_insert_mappings` 

1521 

1522 :meth:`.Session.bulk_save_objects` 

1523 

1524 

1525 """ # noqa: E501 

1526 

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

1528 

1529 def merge( 

1530 self, 

1531 instance: _O, 

1532 *, 

1533 load: bool = True, 

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

1535 ) -> _O: 

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

1537 within this :class:`.Session`. 

1538 

1539 .. container:: class_bases 

1540 

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

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

1543 

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

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

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

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

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

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

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

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

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

1553 

1554 This operation cascades to associated instances if the association is 

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

1556 

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

1558 

1559 :param instance: Instance to be merged. 

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

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

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

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

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

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

1566 without re-querying the database. 

1567 

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

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

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

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

1572 the merge operation populates local attributes and 

1573 cascades to related objects and 

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

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

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

1577 any existing related objects or collections that might not 

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

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

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

1581 method. 

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

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

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

1585 

1586 .. versionadded:: 1.4.24 

1587 

1588 

1589 .. seealso:: 

1590 

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

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

1593 

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

1595 

1596 

1597 """ # noqa: E501 

1598 

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

1600 

1601 def merge_all( 

1602 self, 

1603 instances: Iterable[_O], 

1604 *, 

1605 load: bool = True, 

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

1607 ) -> Sequence[_O]: 

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

1609 

1610 .. container:: class_bases 

1611 

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

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

1614 

1615 .. seealso:: 

1616 

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

1618 

1619 .. versionadded:: 2.1 

1620 

1621 

1622 """ # noqa: E501 

1623 

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

1625 

1626 @overload 

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

1628 

1629 @overload 

1630 def query( 

1631 self, _colexpr: TypedColumnsClauseRole[_T] 

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

1633 

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

1635 

1636 # code within this block is **programmatically, 

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

1638 

1639 @overload 

1640 def query( 

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

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

1643 

1644 @overload 

1645 def query( 

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

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

1648 

1649 @overload 

1650 def query( 

1651 self, 

1652 __ent0: _TCCA[_T0], 

1653 __ent1: _TCCA[_T1], 

1654 __ent2: _TCCA[_T2], 

1655 __ent3: _TCCA[_T3], 

1656 /, 

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

1658 

1659 @overload 

1660 def query( 

1661 self, 

1662 __ent0: _TCCA[_T0], 

1663 __ent1: _TCCA[_T1], 

1664 __ent2: _TCCA[_T2], 

1665 __ent3: _TCCA[_T3], 

1666 __ent4: _TCCA[_T4], 

1667 /, 

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

1669 

1670 @overload 

1671 def query( 

1672 self, 

1673 __ent0: _TCCA[_T0], 

1674 __ent1: _TCCA[_T1], 

1675 __ent2: _TCCA[_T2], 

1676 __ent3: _TCCA[_T3], 

1677 __ent4: _TCCA[_T4], 

1678 __ent5: _TCCA[_T5], 

1679 /, 

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

1681 

1682 @overload 

1683 def query( 

1684 self, 

1685 __ent0: _TCCA[_T0], 

1686 __ent1: _TCCA[_T1], 

1687 __ent2: _TCCA[_T2], 

1688 __ent3: _TCCA[_T3], 

1689 __ent4: _TCCA[_T4], 

1690 __ent5: _TCCA[_T5], 

1691 __ent6: _TCCA[_T6], 

1692 /, 

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

1694 

1695 @overload 

1696 def query( 

1697 self, 

1698 __ent0: _TCCA[_T0], 

1699 __ent1: _TCCA[_T1], 

1700 __ent2: _TCCA[_T2], 

1701 __ent3: _TCCA[_T3], 

1702 __ent4: _TCCA[_T4], 

1703 __ent5: _TCCA[_T5], 

1704 __ent6: _TCCA[_T6], 

1705 __ent7: _TCCA[_T7], 

1706 /, 

1707 *entities: _ColumnsClauseArgument[Any], 

1708 ) -> RowReturningQuery[ 

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

1710 ]: ... 

1711 

1712 # END OVERLOADED FUNCTIONS self.query 

1713 

1714 @overload 

1715 def query( 

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

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

1718 

1719 def query( 

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

1721 ) -> Query[Any]: 

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

1723 :class:`_orm.Session`. 

1724 

1725 .. container:: class_bases 

1726 

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

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

1729 

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

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

1732 to construct ORM queries. 

1733 

1734 .. seealso:: 

1735 

1736 :ref:`unified_tutorial` 

1737 

1738 :ref:`queryguide_toplevel` 

1739 

1740 :ref:`query_api_toplevel` - legacy API doc 

1741 

1742 

1743 """ # noqa: E501 

1744 

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

1746 

1747 def refresh( 

1748 self, 

1749 instance: object, 

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

1751 with_for_update: ForUpdateParameter = None, 

1752 ) -> None: 

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

1754 

1755 .. container:: class_bases 

1756 

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

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

1759 

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

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

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

1763 value available in the current transaction. 

1764 

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

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

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

1768 

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

1770 can also refresh eagerly loaded attributes. 

1771 

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

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

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

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

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

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

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

1779 refreshed. 

1780 

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

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

1783 attributes for those which are named explicitly in the 

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

1785 

1786 .. tip:: 

1787 

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

1789 refreshing both column and relationship oriented attributes, its 

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

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

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

1793 once while having explicit control over relationship loader 

1794 strategies, use the 

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

1796 instead. 

1797 

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

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

1800 in database state outside of that transaction. Refreshing 

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

1802 where database rows have not yet been accessed. 

1803 

1804 :param attribute_names: optional. An iterable collection of 

1805 string attribute names indicating a subset of attributes to 

1806 be refreshed. 

1807 

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

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

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

1811 flags should match the parameters of 

1812 :meth:`_query.Query.with_for_update`. 

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

1814 

1815 .. seealso:: 

1816 

1817 :ref:`session_expire` - introductory material 

1818 

1819 :meth:`.Session.expire` 

1820 

1821 :meth:`.Session.expire_all` 

1822 

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

1824 to refresh objects as they would be loaded normally. 

1825 

1826 

1827 """ # noqa: E501 

1828 

1829 return self._proxied.refresh( 

1830 instance, 

1831 attribute_names=attribute_names, 

1832 with_for_update=with_for_update, 

1833 ) 

1834 

1835 def rollback(self) -> None: 

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

1837 

1838 .. container:: class_bases 

1839 

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

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

1842 

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

1844 

1845 The method always rolls back 

1846 the topmost database transaction, discarding any nested 

1847 transactions that may be in progress. 

1848 

1849 .. seealso:: 

1850 

1851 :ref:`session_rollback` 

1852 

1853 :ref:`unitofwork_transaction` 

1854 

1855 

1856 """ # noqa: E501 

1857 

1858 return self._proxied.rollback() 

1859 

1860 @overload 

1861 def scalar( 

1862 self, 

1863 statement: TypedReturnsRows[_T], 

1864 params: Optional[_CoreSingleExecuteParams] = None, 

1865 *, 

1866 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1867 bind_arguments: Optional[_BindArguments] = None, 

1868 **kw: Any, 

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

1870 

1871 @overload 

1872 def scalar( 

1873 self, 

1874 statement: Executable, 

1875 params: Optional[_CoreSingleExecuteParams] = None, 

1876 *, 

1877 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1878 bind_arguments: Optional[_BindArguments] = None, 

1879 **kw: Any, 

1880 ) -> Any: ... 

1881 

1882 def scalar( 

1883 self, 

1884 statement: Executable, 

1885 params: Optional[_CoreSingleExecuteParams] = None, 

1886 *, 

1887 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1888 bind_arguments: Optional[_BindArguments] = None, 

1889 **kw: Any, 

1890 ) -> Any: 

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

1892 

1893 .. container:: class_bases 

1894 

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

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

1897 

1898 Usage and parameters are the same as that of 

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

1900 value. 

1901 

1902 

1903 """ # noqa: E501 

1904 

1905 return self._proxied.scalar( 

1906 statement, 

1907 params=params, 

1908 execution_options=execution_options, 

1909 bind_arguments=bind_arguments, 

1910 **kw, 

1911 ) 

1912 

1913 @overload 

1914 def scalars( 

1915 self, 

1916 statement: TypedReturnsRows[_T], 

1917 params: Optional[_CoreAnyExecuteParams] = None, 

1918 *, 

1919 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1920 bind_arguments: Optional[_BindArguments] = None, 

1921 **kw: Any, 

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

1923 

1924 @overload 

1925 def scalars( 

1926 self, 

1927 statement: Executable, 

1928 params: Optional[_CoreAnyExecuteParams] = None, 

1929 *, 

1930 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1931 bind_arguments: Optional[_BindArguments] = None, 

1932 **kw: Any, 

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

1934 

1935 def scalars( 

1936 self, 

1937 statement: Executable, 

1938 params: Optional[_CoreAnyExecuteParams] = None, 

1939 *, 

1940 execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, 

1941 bind_arguments: Optional[_BindArguments] = None, 

1942 **kw: Any, 

1943 ) -> ScalarResult[Any]: 

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

1945 

1946 .. container:: class_bases 

1947 

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

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

1950 

1951 Usage and parameters are the same as that of 

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

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

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

1955 

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

1957 

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

1959 

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

1961 

1962 .. seealso:: 

1963 

1964 :ref:`orm_queryguide_select_orm_entities` - contrasts the behavior 

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

1966 

1967 

1968 """ # noqa: E501 

1969 

1970 return self._proxied.scalars( 

1971 statement, 

1972 params=params, 

1973 execution_options=execution_options, 

1974 bind_arguments=bind_arguments, 

1975 **kw, 

1976 ) 

1977 

1978 @property 

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

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

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

1982 

1983 """ # noqa: E501 

1984 

1985 return self._proxied.bind 

1986 

1987 @bind.setter 

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

1989 self._proxied.bind = attr 

1990 

1991 @property 

1992 def dirty(self) -> Any: 

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

1994 

1995 .. container:: class_bases 

1996 

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

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

1999 

2000 E.g.:: 

2001 

2002 some_mapped_object in session.dirty 

2003 

2004 Instances are considered dirty when they were modified but not 

2005 deleted. 

2006 

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

2008 attribute-setting or collection modification operations will 

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

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

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

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

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

2014 it's only done at flush time). 

2015 

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

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

2018 

2019 

2020 """ # noqa: E501 

2021 

2022 return self._proxied.dirty 

2023 

2024 @property 

2025 def deleted(self) -> Any: 

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

2027 

2028 .. container:: class_bases 

2029 

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

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

2032 

2033 """ # noqa: E501 

2034 

2035 return self._proxied.deleted 

2036 

2037 @property 

2038 def new(self) -> Any: 

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

2040 

2041 .. container:: class_bases 

2042 

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

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

2045 

2046 """ # noqa: E501 

2047 

2048 return self._proxied.new 

2049 

2050 @property 

2051 def identity_map(self) -> IdentityMap: 

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

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

2054 

2055 """ # noqa: E501 

2056 

2057 return self._proxied.identity_map 

2058 

2059 @identity_map.setter 

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

2061 self._proxied.identity_map = attr 

2062 

2063 @property 

2064 def is_active(self) -> Any: 

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

2066 

2067 .. container:: class_bases 

2068 

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

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

2071 

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

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

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

2075 

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

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

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

2079 fully roll back the transaction. 

2080 

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

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

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

2084 

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

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

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

2088 

2089 .. seealso:: 

2090 

2091 :ref:`faq_session_rollback` 

2092 

2093 :meth:`_orm.Session.in_transaction` 

2094 

2095 

2096 """ # noqa: E501 

2097 

2098 return self._proxied.is_active 

2099 

2100 @property 

2101 def autoflush(self) -> bool: 

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

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

2104 

2105 """ # noqa: E501 

2106 

2107 return self._proxied.autoflush 

2108 

2109 @autoflush.setter 

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

2111 self._proxied.autoflush = attr 

2112 

2113 @property 

2114 def no_autoflush(self) -> Any: 

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

2116 

2117 .. container:: class_bases 

2118 

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

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

2121 

2122 e.g.:: 

2123 

2124 with session.no_autoflush: 

2125 

2126 some_object = SomeClass() 

2127 session.add(some_object) 

2128 # won't autoflush 

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

2130 

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

2132 will not be subject to flushes occurring upon query 

2133 access. This is useful when initializing a series 

2134 of objects which involve existing database queries, 

2135 where the uncompleted object should not yet be flushed. 

2136 

2137 

2138 """ # noqa: E501 

2139 

2140 return self._proxied.no_autoflush 

2141 

2142 @property 

2143 def info(self) -> Any: 

2144 r"""A user-modifiable dictionary. 

2145 

2146 .. container:: class_bases 

2147 

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

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

2150 

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

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

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

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

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

2156 

2157 

2158 """ # noqa: E501 

2159 

2160 return self._proxied.info 

2161 

2162 @classmethod 

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

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

2165 

2166 .. container:: class_bases 

2167 

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

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

2170 

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

2172 

2173 

2174 """ # noqa: E501 

2175 

2176 return Session.object_session(instance) 

2177 

2178 @classmethod 

2179 def identity_key( 

2180 cls, 

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

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

2183 *, 

2184 instance: Optional[Any] = None, 

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

2186 identity_token: Optional[Any] = None, 

2187 ) -> _IdentityKeyType[Any]: 

2188 r"""Return an identity key. 

2189 

2190 .. container:: class_bases 

2191 

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

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

2194 

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

2196 

2197 

2198 """ # noqa: E501 

2199 

2200 return Session.identity_key( 

2201 class_=class_, 

2202 ident=ident, 

2203 instance=instance, 

2204 row=row, 

2205 identity_token=identity_token, 

2206 ) 

2207 

2208 # END PROXY METHODS scoped_session 

2209 

2210 

2211ScopedSession = scoped_session 

2212"""Old name for backwards compatibility."""