1# orm/__init__.py
2# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
3# <see AUTHORS file>
4#
5# This module is part of SQLAlchemy and is released under
6# the MIT License: https://www.opensource.org/licenses/mit-license.php
7
8"""
9Functional constructs for ORM configuration.
10
11See the SQLAlchemy object relational tutorial and mapper configuration
12documentation for an overview of how this module is used.
13
14"""
15
16from . import exc
17from . import mapper as mapperlib
18from . import strategy_options
19from .attributes import AttributeEvent
20from .attributes import InstrumentedAttribute
21from .attributes import Mapped
22from .attributes import QueryableAttribute
23from .context import QueryContext
24from .decl_api import as_declarative
25from .decl_api import declarative_base
26from .decl_api import declarative_mixin
27from .decl_api import DeclarativeMeta
28from .decl_api import declared_attr
29from .decl_api import has_inherited_table
30from .decl_api import registry
31from .decl_api import synonym_for
32from .descriptor_props import CompositeProperty
33from .descriptor_props import SynonymProperty
34from .identity import IdentityMap
35from .instrumentation import ClassManager
36from .interfaces import EXT_CONTINUE
37from .interfaces import EXT_SKIP
38from .interfaces import EXT_STOP
39from .interfaces import InspectionAttr
40from .interfaces import InspectionAttrInfo
41from .interfaces import MANYTOMANY
42from .interfaces import MANYTOONE
43from .interfaces import MapperProperty
44from .interfaces import NOT_EXTENSION
45from .interfaces import ONETOMANY
46from .interfaces import PropComparator
47from .interfaces import UserDefinedOption
48from .loading import merge_frozen_result
49from .loading import merge_result
50from .mapper import class_mapper
51from .mapper import configure_mappers
52from .mapper import Mapper
53from .mapper import reconstructor
54from .mapper import validates
55from .properties import ColumnProperty
56from .query import AliasOption
57from .query import FromStatement
58from .query import Query
59from .relationships import foreign
60from .relationships import RelationshipProperty
61from .relationships import remote
62from .scoping import scoped_session
63from .session import close_all_sessions
64from .session import make_transient
65from .session import make_transient_to_detached
66from .session import object_session
67from .session import ORMExecuteState
68from .session import Session
69from .session import sessionmaker
70from .session import SessionTransaction
71from .state import AttributeState
72from .state import InstanceState
73from .strategy_options import Load
74from .unitofwork import UOWTransaction
75from .util import aliased
76from .util import Bundle
77from .util import CascadeOptions
78from .util import join
79from .util import LoaderCriteriaOption
80from .util import object_mapper
81from .util import outerjoin
82from .util import polymorphic_union
83from .util import was_deleted
84from .util import with_parent
85from .util import with_polymorphic
86from .. import sql as _sql
87from .. import util as _sa_util
88from ..util.langhelpers import public_factory
89
90
91def create_session(bind=None, **kwargs):
92 r"""Create a new :class:`.Session`
93 with no automation enabled by default.
94
95 This function is used primarily for testing. The usual
96 route to :class:`.Session` creation is via its constructor
97 or the :func:`.sessionmaker` function.
98
99 :param bind: optional, a single Connectable to use for all
100 database access in the created
101 :class:`~sqlalchemy.orm.session.Session`.
102
103 :param \*\*kwargs: optional, passed through to the
104 :class:`.Session` constructor.
105
106 :returns: an :class:`~sqlalchemy.orm.session.Session` instance
107
108 The defaults of create_session() are the opposite of that of
109 :func:`sessionmaker`; ``autoflush`` and ``expire_on_commit`` are
110 False, ``autocommit`` is True. In this sense the session acts
111 more like the "classic" SQLAlchemy 0.3 session with these.
112
113 .. deprecated:: 1.4 The "autocommit" parameter will be removed in
114 SQLAlchemy 2.0. :func:`_orm.create_session` will return a
115 :class:`_orm.Session` that does not include "autocommit' behavior
116 in release 2.0.
117
118 Usage::
119
120 >>> from sqlalchemy.orm import create_session
121 >>> session = create_session()
122
123 It is recommended to use :func:`sessionmaker` instead of
124 create_session().
125
126 """
127
128 if kwargs.get("future", False):
129 kwargs.setdefault("autocommit", False)
130 else:
131 kwargs.setdefault("autocommit", True)
132
133 kwargs.setdefault("autoflush", False)
134 kwargs.setdefault("expire_on_commit", False)
135 return Session(bind=bind, **kwargs)
136
137
138with_loader_criteria = public_factory(LoaderCriteriaOption, ".orm")
139
140relationship = public_factory(RelationshipProperty, ".orm.relationship")
141
142
143@_sa_util.deprecated_20("relation", "Please use :func:`.relationship`.")
144def relation(*arg, **kw):
145 """A synonym for :func:`relationship`."""
146
147 return relationship(*arg, **kw)
148
149
150def dynamic_loader(argument, **kw):
151 """Construct a dynamically-loading mapper property.
152
153 This is essentially the same as
154 using the ``lazy='dynamic'`` argument with :func:`relationship`::
155
156 dynamic_loader(SomeClass)
157
158 # is the same as
159
160 relationship(SomeClass, lazy="dynamic")
161
162 See the section :ref:`dynamic_relationship` for more details
163 on dynamic loading.
164
165 """
166 kw["lazy"] = "dynamic"
167 return relationship(argument, **kw)
168
169
170column_property = public_factory(ColumnProperty, ".orm.column_property")
171composite = public_factory(CompositeProperty, ".orm.composite")
172
173
174def backref(name, **kwargs):
175 """When using the :paramref:`_orm.relationship.backref` parameter,
176 provides specific parameters to be used when the new
177 :func:`_orm.relationship` is generated.
178
179 E.g.::
180
181 'items':relationship(
182 SomeItem, backref=backref('parent', lazy='subquery'))
183
184 The :paramref:`_orm.relationship.backref` parameter is generally
185 considered to be legacy; for modern applications, using
186 explicit :func:`_orm.relationship` constructs linked together using
187 the :paramref:`_orm.relationship.back_populates` parameter should be
188 preferred.
189
190 .. seealso::
191
192 :ref:`relationships_backref` - background on backrefs
193
194 """
195
196 return (name, kwargs)
197
198
199def deferred(*columns, **kw):
200 r"""Indicate a column-based mapped attribute that by default will
201 not load unless accessed.
202
203 :param \*columns: columns to be mapped. This is typically a single
204 :class:`_schema.Column` object,
205 however a collection is supported in order
206 to support multiple columns mapped under the same attribute.
207
208 :param raiseload: boolean, if True, indicates an exception should be raised
209 if the load operation is to take place.
210
211 .. versionadded:: 1.4
212
213 .. seealso::
214
215 :ref:`deferred_raiseload`
216
217 :param \**kw: additional keyword arguments passed to
218 :class:`.ColumnProperty`.
219
220 .. seealso::
221
222 :ref:`deferred`
223
224 """
225 return ColumnProperty(deferred=True, *columns, **kw)
226
227
228def query_expression(default_expr=_sql.null()):
229 """Indicate an attribute that populates from a query-time SQL expression.
230
231 :param default_expr: Optional SQL expression object that will be used in
232 all cases if not assigned later with :func:`_orm.with_expression`.
233 E.g.::
234
235 from sqlalchemy.sql import literal
236
237 class C(Base):
238 #...
239 my_expr = query_expression(literal(1))
240
241 .. versionadded:: 1.3.18
242
243
244 .. versionadded:: 1.2
245
246 .. seealso::
247
248 :ref:`mapper_querytime_expression`
249
250 """
251 prop = ColumnProperty(default_expr)
252 prop.strategy_key = (("query_expression", True),)
253 return prop
254
255
256mapper = public_factory(Mapper, ".orm.mapper")
257
258synonym = public_factory(SynonymProperty, ".orm.synonym")
259
260
261def clear_mappers():
262 """Remove all mappers from all classes.
263
264 .. versionchanged:: 1.4 This function now locates all
265 :class:`_orm.registry` objects and calls upon the
266 :meth:`_orm.registry.dispose` method of each.
267
268 This function removes all instrumentation from classes and disposes
269 of their associated mappers. Once called, the classes are unmapped
270 and can be later re-mapped with new mappers.
271
272 :func:`.clear_mappers` is *not* for normal use, as there is literally no
273 valid usage for it outside of very specific testing scenarios. Normally,
274 mappers are permanent structural components of user-defined classes, and
275 are never discarded independently of their class. If a mapped class
276 itself is garbage collected, its mapper is automatically disposed of as
277 well. As such, :func:`.clear_mappers` is only for usage in test suites
278 that re-use the same classes with different mappings, which is itself an
279 extremely rare use case - the only such use case is in fact SQLAlchemy's
280 own test suite, and possibly the test suites of other ORM extension
281 libraries which intend to test various combinations of mapper construction
282 upon a fixed set of classes.
283
284 """
285
286 mapperlib._dispose_registries(mapperlib._all_registries(), False)
287
288
289joinedload = strategy_options.joinedload._unbound_fn
290contains_eager = strategy_options.contains_eager._unbound_fn
291defer = strategy_options.defer._unbound_fn
292undefer = strategy_options.undefer._unbound_fn
293undefer_group = strategy_options.undefer_group._unbound_fn
294with_expression = strategy_options.with_expression._unbound_fn
295load_only = strategy_options.load_only._unbound_fn
296lazyload = strategy_options.lazyload._unbound_fn
297subqueryload = strategy_options.subqueryload._unbound_fn
298selectinload = strategy_options.selectinload._unbound_fn
299immediateload = strategy_options.immediateload._unbound_fn
300noload = strategy_options.noload._unbound_fn
301raiseload = strategy_options.raiseload._unbound_fn
302defaultload = strategy_options.defaultload._unbound_fn
303selectin_polymorphic = strategy_options.selectin_polymorphic._unbound_fn
304
305
306@_sa_util.deprecated_20("eagerload", "Please use :func:`_orm.joinedload`.")
307def eagerload(*args, **kwargs):
308 """A synonym for :func:`joinedload()`."""
309 return joinedload(*args, **kwargs)
310
311
312contains_alias = public_factory(AliasOption, ".orm.contains_alias")
313
314if True:
315 from .events import AttributeEvents
316 from .events import MapperEvents
317 from .events import InstanceEvents
318 from .events import InstrumentationEvents
319 from .events import QueryEvents
320 from .events import SessionEvents
321
322
323def __go(lcls):
324 global __all__
325 global AppenderQuery
326 from .. import util as sa_util
327 from . import dynamic
328 from . import events
329 from . import loading
330 import inspect as _inspect
331
332 from .dynamic import AppenderQuery
333
334 __all__ = sorted(
335 name
336 for name, obj in lcls.items()
337 if not (name.startswith("_") or _inspect.ismodule(obj))
338 )
339
340 _sa_util.preloaded.import_prefix("sqlalchemy.orm")
341 _sa_util.preloaded.import_prefix("sqlalchemy.ext")
342
343
344__go(locals())