333 lines
10 KiB
Python
333 lines
10 KiB
Python
# orm/__init__.py
|
|
# Copyright (C) 2005-2021 the SQLAlchemy authors and contributors
|
|
# <see AUTHORS file>
|
|
#
|
|
# This module is part of SQLAlchemy and is released under
|
|
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
|
|
|
"""
|
|
Functional constructs for ORM configuration.
|
|
|
|
See the SQLAlchemy object relational tutorial and mapper configuration
|
|
documentation for an overview of how this module is used.
|
|
|
|
"""
|
|
|
|
from . import exc
|
|
from . import mapper as mapperlib
|
|
from . import strategy_options
|
|
from .attributes import AttributeEvent
|
|
from .attributes import InstrumentedAttribute
|
|
from .attributes import Mapped
|
|
from .attributes import QueryableAttribute
|
|
from .context import QueryContext
|
|
from .decl_api import as_declarative
|
|
from .decl_api import declarative_base
|
|
from .decl_api import declarative_mixin
|
|
from .decl_api import DeclarativeMeta
|
|
from .decl_api import declared_attr
|
|
from .decl_api import has_inherited_table
|
|
from .decl_api import registry
|
|
from .decl_api import synonym_for
|
|
from .descriptor_props import CompositeProperty
|
|
from .descriptor_props import SynonymProperty
|
|
from .identity import IdentityMap
|
|
from .instrumentation import ClassManager
|
|
from .interfaces import EXT_CONTINUE
|
|
from .interfaces import EXT_SKIP
|
|
from .interfaces import EXT_STOP
|
|
from .interfaces import InspectionAttr
|
|
from .interfaces import InspectionAttrInfo
|
|
from .interfaces import MANYTOMANY
|
|
from .interfaces import MANYTOONE
|
|
from .interfaces import MapperProperty
|
|
from .interfaces import NOT_EXTENSION
|
|
from .interfaces import ONETOMANY
|
|
from .interfaces import PropComparator
|
|
from .loading import merge_frozen_result
|
|
from .loading import merge_result
|
|
from .mapper import class_mapper
|
|
from .mapper import configure_mappers
|
|
from .mapper import Mapper
|
|
from .mapper import reconstructor
|
|
from .mapper import validates
|
|
from .properties import ColumnProperty
|
|
from .query import AliasOption
|
|
from .query import FromStatement
|
|
from .query import Query
|
|
from .relationships import foreign
|
|
from .relationships import RelationshipProperty
|
|
from .relationships import remote
|
|
from .scoping import scoped_session
|
|
from .session import close_all_sessions
|
|
from .session import make_transient
|
|
from .session import make_transient_to_detached
|
|
from .session import object_session
|
|
from .session import ORMExecuteState
|
|
from .session import Session
|
|
from .session import sessionmaker
|
|
from .session import SessionTransaction
|
|
from .state import AttributeState
|
|
from .state import InstanceState
|
|
from .strategy_options import Load
|
|
from .unitofwork import UOWTransaction
|
|
from .util import aliased
|
|
from .util import Bundle
|
|
from .util import CascadeOptions
|
|
from .util import join
|
|
from .util import LoaderCriteriaOption
|
|
from .util import object_mapper
|
|
from .util import outerjoin
|
|
from .util import polymorphic_union
|
|
from .util import was_deleted
|
|
from .util import with_parent
|
|
from .util import with_polymorphic
|
|
from .. import sql as _sql
|
|
from .. import util as _sa_util
|
|
from ..util.langhelpers import public_factory
|
|
|
|
|
|
def create_session(bind=None, **kwargs):
|
|
r"""Create a new :class:`.Session`
|
|
with no automation enabled by default.
|
|
|
|
This function is used primarily for testing. The usual
|
|
route to :class:`.Session` creation is via its constructor
|
|
or the :func:`.sessionmaker` function.
|
|
|
|
:param bind: optional, a single Connectable to use for all
|
|
database access in the created
|
|
:class:`~sqlalchemy.orm.session.Session`.
|
|
|
|
:param \*\*kwargs: optional, passed through to the
|
|
:class:`.Session` constructor.
|
|
|
|
:returns: an :class:`~sqlalchemy.orm.session.Session` instance
|
|
|
|
The defaults of create_session() are the opposite of that of
|
|
:func:`sessionmaker`; ``autoflush`` and ``expire_on_commit`` are
|
|
False, ``autocommit`` is True. In this sense the session acts
|
|
more like the "classic" SQLAlchemy 0.3 session with these.
|
|
|
|
Usage::
|
|
|
|
>>> from sqlalchemy.orm import create_session
|
|
>>> session = create_session()
|
|
|
|
It is recommended to use :func:`sessionmaker` instead of
|
|
create_session().
|
|
|
|
"""
|
|
|
|
if kwargs.get("future", False):
|
|
kwargs.setdefault("autocommit", False)
|
|
else:
|
|
kwargs.setdefault("autocommit", True)
|
|
|
|
kwargs.setdefault("autoflush", False)
|
|
kwargs.setdefault("expire_on_commit", False)
|
|
return Session(bind=bind, **kwargs)
|
|
|
|
|
|
with_loader_criteria = public_factory(LoaderCriteriaOption, ".orm")
|
|
|
|
relationship = public_factory(RelationshipProperty, ".orm.relationship")
|
|
|
|
|
|
@_sa_util.deprecated_20("relation", "Please use :func:`.relationship`.")
|
|
def relation(*arg, **kw):
|
|
"""A synonym for :func:`relationship`."""
|
|
|
|
return relationship(*arg, **kw)
|
|
|
|
|
|
def dynamic_loader(argument, **kw):
|
|
"""Construct a dynamically-loading mapper property.
|
|
|
|
This is essentially the same as
|
|
using the ``lazy='dynamic'`` argument with :func:`relationship`::
|
|
|
|
dynamic_loader(SomeClass)
|
|
|
|
# is the same as
|
|
|
|
relationship(SomeClass, lazy="dynamic")
|
|
|
|
See the section :ref:`dynamic_relationship` for more details
|
|
on dynamic loading.
|
|
|
|
"""
|
|
kw["lazy"] = "dynamic"
|
|
return relationship(argument, **kw)
|
|
|
|
|
|
column_property = public_factory(ColumnProperty, ".orm.column_property")
|
|
composite = public_factory(CompositeProperty, ".orm.composite")
|
|
|
|
|
|
def backref(name, **kwargs):
|
|
"""Create a back reference with explicit keyword arguments, which are the
|
|
same arguments one can send to :func:`relationship`.
|
|
|
|
Used with the ``backref`` keyword argument to :func:`relationship` in
|
|
place of a string argument, e.g.::
|
|
|
|
'items':relationship(
|
|
SomeItem, backref=backref('parent', lazy='subquery'))
|
|
|
|
.. seealso::
|
|
|
|
:ref:`relationships_backref`
|
|
|
|
"""
|
|
|
|
return (name, kwargs)
|
|
|
|
|
|
def deferred(*columns, **kw):
|
|
r"""Indicate a column-based mapped attribute that by default will
|
|
not load unless accessed.
|
|
|
|
:param \*columns: columns to be mapped. This is typically a single
|
|
:class:`_schema.Column` object,
|
|
however a collection is supported in order
|
|
to support multiple columns mapped under the same attribute.
|
|
|
|
:param raiseload: boolean, if True, indicates an exception should be raised
|
|
if the load operation is to take place.
|
|
|
|
.. versionadded:: 1.4
|
|
|
|
.. seealso::
|
|
|
|
:ref:`deferred_raiseload`
|
|
|
|
:param \**kw: additional keyword arguments passed to
|
|
:class:`.ColumnProperty`.
|
|
|
|
.. seealso::
|
|
|
|
:ref:`deferred`
|
|
|
|
"""
|
|
return ColumnProperty(deferred=True, *columns, **kw)
|
|
|
|
|
|
def query_expression(default_expr=_sql.null()):
|
|
"""Indicate an attribute that populates from a query-time SQL expression.
|
|
|
|
:param default_expr: Optional SQL expression object that will be used in
|
|
all cases if not assigned later with :func:`_orm.with_expression`.
|
|
E.g.::
|
|
|
|
from sqlalchemy.sql import literal
|
|
|
|
class C(Base):
|
|
#...
|
|
my_expr = query_expression(literal(1))
|
|
|
|
.. versionadded:: 1.3.18
|
|
|
|
|
|
.. versionadded:: 1.2
|
|
|
|
.. seealso::
|
|
|
|
:ref:`mapper_querytime_expression`
|
|
|
|
"""
|
|
prop = ColumnProperty(default_expr)
|
|
prop.strategy_key = (("query_expression", True),)
|
|
return prop
|
|
|
|
|
|
mapper = public_factory(Mapper, ".orm.mapper")
|
|
|
|
synonym = public_factory(SynonymProperty, ".orm.synonym")
|
|
|
|
|
|
def clear_mappers():
|
|
"""Remove all mappers from all classes.
|
|
|
|
.. versionchanged:: 1.4 This function now locates all
|
|
:class:`_orm.registry` objects and calls upon the
|
|
:meth:`_orm.registry.dispose` method of each.
|
|
|
|
This function removes all instrumentation from classes and disposes
|
|
of their associated mappers. Once called, the classes are unmapped
|
|
and can be later re-mapped with new mappers.
|
|
|
|
:func:`.clear_mappers` is *not* for normal use, as there is literally no
|
|
valid usage for it outside of very specific testing scenarios. Normally,
|
|
mappers are permanent structural components of user-defined classes, and
|
|
are never discarded independently of their class. If a mapped class
|
|
itself is garbage collected, its mapper is automatically disposed of as
|
|
well. As such, :func:`.clear_mappers` is only for usage in test suites
|
|
that re-use the same classes with different mappings, which is itself an
|
|
extremely rare use case - the only such use case is in fact SQLAlchemy's
|
|
own test suite, and possibly the test suites of other ORM extension
|
|
libraries which intend to test various combinations of mapper construction
|
|
upon a fixed set of classes.
|
|
|
|
"""
|
|
|
|
mapperlib._dispose_registries(mapperlib._all_registries(), False)
|
|
|
|
|
|
joinedload = strategy_options.joinedload._unbound_fn
|
|
contains_eager = strategy_options.contains_eager._unbound_fn
|
|
defer = strategy_options.defer._unbound_fn
|
|
undefer = strategy_options.undefer._unbound_fn
|
|
undefer_group = strategy_options.undefer_group._unbound_fn
|
|
with_expression = strategy_options.with_expression._unbound_fn
|
|
load_only = strategy_options.load_only._unbound_fn
|
|
lazyload = strategy_options.lazyload._unbound_fn
|
|
subqueryload = strategy_options.subqueryload._unbound_fn
|
|
selectinload = strategy_options.selectinload._unbound_fn
|
|
immediateload = strategy_options.immediateload._unbound_fn
|
|
noload = strategy_options.noload._unbound_fn
|
|
raiseload = strategy_options.raiseload._unbound_fn
|
|
defaultload = strategy_options.defaultload._unbound_fn
|
|
selectin_polymorphic = strategy_options.selectin_polymorphic._unbound_fn
|
|
|
|
|
|
@_sa_util.deprecated_20("eagerload", "Please use :func:`_orm.joinedload`.")
|
|
def eagerload(*args, **kwargs):
|
|
"""A synonym for :func:`joinedload()`."""
|
|
return joinedload(*args, **kwargs)
|
|
|
|
|
|
contains_alias = public_factory(AliasOption, ".orm.contains_alias")
|
|
|
|
if True:
|
|
from .events import AttributeEvents
|
|
from .events import MapperEvents
|
|
from .events import InstanceEvents
|
|
from .events import InstrumentationEvents
|
|
from .events import QueryEvents
|
|
from .events import SessionEvents
|
|
|
|
|
|
def __go(lcls):
|
|
global __all__
|
|
global AppenderQuery
|
|
from .. import util as sa_util
|
|
from . import dynamic
|
|
from . import events
|
|
from . import loading
|
|
import inspect as _inspect
|
|
|
|
from .dynamic import AppenderQuery
|
|
|
|
__all__ = sorted(
|
|
name
|
|
for name, obj in lcls.items()
|
|
if not (name.startswith("_") or _inspect.ismodule(obj))
|
|
)
|
|
|
|
_sa_util.preloaded.import_prefix("sqlalchemy.orm")
|
|
_sa_util.preloaded.import_prefix("sqlalchemy.ext")
|
|
|
|
|
|
__go(locals())
|