summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2022-01-03 13:49:26 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2022-01-05 19:28:49 -0500
commit01c50c64e302c193733cef7fb146fbab8eaa44bd (patch)
treedca946206da557a14a681768d094b92c95dfabe4 /lib/sqlalchemy/orm
parent146a349d81023805264f81643db50a5281da90da (diff)
downloadsqlalchemy-01c50c64e302c193733cef7fb146fbab8eaa44bd.tar.gz
Remove all remaining removed_in_20 warnings slated for removal
Finalize all remaining removed-in-2.0 changes so that we can begin doing pep-484 typing without old things getting in the way (we will also have to do public_factory). note there are a few "moved_in_20()" and "became_legacy_in_20()" warnings still in place. The SQLALCHEMY_WARN_20 variable is now removed. Also removed here are the legacy "in place mutators" for Select statements, and some keyword-only argument signatures in Core have been added. Also in the big change department, the ORM mapper() function is removed entirely; the Mapper class is otherwise unchanged, just the public-facing API function. Mappers are now always given a registry in which to participate, however the argument signature of Mapper is not changed. ideally "registry" would be the first positional argument. Fixes: #7257 Change-Id: Ic70c57b9f1cf7eb996338af5183b11bdeb3e1623
Diffstat (limited to 'lib/sqlalchemy/orm')
-rw-r--r--lib/sqlalchemy/orm/__init__.py37
-rw-r--r--lib/sqlalchemy/orm/context.py26
-rw-r--r--lib/sqlalchemy/orm/decl_api.py23
-rw-r--r--lib/sqlalchemy/orm/events.py48
-rw-r--r--lib/sqlalchemy/orm/loading.py3
-rw-r--r--lib/sqlalchemy/orm/mapper.py24
-rw-r--r--lib/sqlalchemy/orm/query.py16
-rw-r--r--lib/sqlalchemy/orm/relationships.py28
-rw-r--r--lib/sqlalchemy/orm/session.py144
-rw-r--r--lib/sqlalchemy/orm/unitofwork.py26
-rw-r--r--lib/sqlalchemy/orm/util.py18
11 files changed, 131 insertions, 262 deletions
diff --git a/lib/sqlalchemy/orm/__init__.py b/lib/sqlalchemy/orm/__init__.py
index 69a3e64da..50b320cb2 100644
--- a/lib/sqlalchemy/orm/__init__.py
+++ b/lib/sqlalchemy/orm/__init__.py
@@ -100,6 +100,7 @@ from .util import with_parent
from .util import with_polymorphic
from .. import sql as _sql
from .. import util as _sa_util
+from ..exc import InvalidRequestError
from ..util.langhelpers import public_factory
@@ -144,11 +145,31 @@ 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`."""
+def mapper(*arg, **kw):
+ """Placeholder for the now-removed ``mapper()`` function.
- return relationship(*arg, **kw)
+ Classical mappings should be performed using the
+ :meth:`_orm.registry.map_imperatively` method.
+
+ This symbol remains in SQLAlchemy 2.0 to suit the deprecated use case
+ of using the ``mapper()`` function as a target for ORM event listeners,
+ which failed to be marked as deprecated in the 1.4 series.
+
+ Global ORM mapper listeners should instead use the :class:`_orm.Mapper`
+ class as the target.
+
+ .. versionchanged:: 2.0 The ``mapper()`` function was removed; the
+ symbol remains temporarily as a placeholder for the event listening
+ use case.
+
+ """
+ raise InvalidRequestError(
+ "The 'sqlalchemy.orm.mapper()' function is removed as of "
+ "SQLAlchemy 2.0. Use the "
+ "'sqlalchemy.orm.registry.map_imperatively()` "
+ "method of the ``sqlalchemy.orm.registry`` class to perform "
+ "classical mapping."
+ )
def dynamic_loader(argument, **kw):
@@ -251,8 +272,6 @@ def query_expression(default_expr=_sql.null()):
return prop
-mapper = public_factory(Mapper, ".orm.mapper")
-
synonym = public_factory(SynonymProperty, ".orm.synonym")
@@ -284,12 +303,6 @@ def clear_mappers():
mapperlib._dispose_registries(mapperlib._all_registries(), False)
-@_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:
diff --git a/lib/sqlalchemy/orm/context.py b/lib/sqlalchemy/orm/context.py
index 012db36c2..36590f8ee 100644
--- a/lib/sqlalchemy/orm/context.py
+++ b/lib/sqlalchemy/orm/context.py
@@ -1091,24 +1091,6 @@ class ORMSelectCompileState(ORMCompileState, SelectState):
def _simple_statement(self):
- if (
- self.compile_options._use_legacy_query_style
- and (self.distinct and not self.distinct_on)
- and self.order_by
- ):
- to_add = sql_util.expand_column_list_from_order_by(
- self.primary_columns, self.order_by
- )
- if to_add:
- util.warn_deprecated_20(
- "ORDER BY columns added implicitly due to "
- "DISTINCT is deprecated and will be removed in "
- "SQLAlchemy 2.0. SELECT statements with DISTINCT "
- "should be written to explicitly include the appropriate "
- "columns in the columns clause"
- )
- self.primary_columns += to_add
-
statement = self._select_statement(
self.primary_columns + self.secondary_columns,
tuple(self.from_clauses) + tuple(self.eager_joins.values()),
@@ -2293,14 +2275,6 @@ class _BundleEntity(_QueryEntity):
)
self.supports_single_entity = self.bundle.single_entity
- if (
- self.supports_single_entity
- and not compile_state.compile_options._use_legacy_query_style
- ):
- util.warn_deprecated_20(
- "The Bundle.single_entity flag has no effect when "
- "using 2.0 style execution."
- )
@property
def mapper(self):
diff --git a/lib/sqlalchemy/orm/decl_api.py b/lib/sqlalchemy/orm/decl_api.py
index 7b6814863..c973f5a4c 100644
--- a/lib/sqlalchemy/orm/decl_api.py
+++ b/lib/sqlalchemy/orm/decl_api.py
@@ -370,7 +370,7 @@ def declarative_base(
The new base class will be given a metaclass that produces
appropriate :class:`~sqlalchemy.schema.Table` objects and makes
- the appropriate :func:`~sqlalchemy.orm.mapper` calls based on the
+ the appropriate :class:`_orm.Mapper` calls based on the
information provided declaratively in the class and any subclasses
of the class.
@@ -408,7 +408,7 @@ def declarative_base(
``metadata`` attribute of the generated declarative base class.
:param mapper:
- An optional callable, defaults to :func:`~sqlalchemy.orm.mapper`. Will
+ An optional callable, defaults to :class:`_orm.Mapper`. Will
be used to map subclasses to their Tables.
:param cls:
@@ -479,8 +479,8 @@ class registry:
* :meth:`_orm.registry.map_imperatively` will produce a
:class:`_orm.Mapper` for a class without scanning the class for
declarative class attributes. This method suits the use case historically
- provided by the
- :func:`_orm.mapper` classical mapping function.
+ provided by the ``sqlalchemy.orm.mapper()`` classical mapping function,
+ which is removed as of SQLAlchemy 2.0.
.. versionadded:: 1.4
@@ -749,7 +749,7 @@ class registry:
examples.
:param mapper:
- An optional callable, defaults to :func:`~sqlalchemy.orm.mapper`.
+ An optional callable, defaults to :class:`_orm.Mapper`.
This function is used to generate new :class:`_orm.Mapper` objects.
:param cls:
@@ -923,8 +923,8 @@ class registry:
information. Instead, all mapping constructs are passed as
arguments.
- This method is intended to be fully equivalent to the classic
- SQLAlchemy :func:`_orm.mapper` function, except that it's in terms of
+ This method is intended to be fully equivalent to the now-removed
+ SQLAlchemy ``mapper()`` function, except that it's in terms of
a particular registry.
E.g.::
@@ -948,15 +948,15 @@ class registry:
and usage examples.
:param class\_: The class to be mapped. Corresponds to the
- :paramref:`_orm.mapper.class_` parameter.
+ :paramref:`_orm.Mapper.class_` parameter.
:param local_table: the :class:`_schema.Table` or other
:class:`_sql.FromClause` object that is the subject of the mapping.
Corresponds to the
- :paramref:`_orm.mapper.local_table` parameter.
+ :paramref:`_orm.Mapper.local_table` parameter.
:param \**kw: all other keyword arguments are passed to the
- :func:`_orm.mapper` function directly.
+ :class:`_orm.Mapper` constructor directly.
.. seealso::
@@ -968,9 +968,6 @@ class registry:
return _mapper(self, class_, local_table, kw)
-mapperlib._legacy_registry = registry()
-
-
def as_declarative(**kw):
"""
Class decorator which will adapt a given class into a
diff --git a/lib/sqlalchemy/orm/events.py b/lib/sqlalchemy/orm/events.py
index a66bf64d8..03e3796a6 100644
--- a/lib/sqlalchemy/orm/events.py
+++ b/lib/sqlalchemy/orm/events.py
@@ -152,8 +152,8 @@ class InstanceEvents(event.Events):
* unmapped superclasses of mapped or to-be-mapped classes
(using the ``propagate=True`` flag)
* :class:`_orm.Mapper` objects
- * the :class:`_orm.Mapper` class itself and the :func:`.mapper`
- function indicate listening for all mappers.
+ * the :class:`_orm.Mapper` class itself indicates listening for all
+ mappers.
Instance events are closely related to mapper events, but
are more specific to the instance and its instrumentation,
@@ -200,6 +200,12 @@ class InstanceEvents(event.Events):
elif isinstance(target, mapperlib.Mapper):
return target.class_manager
elif target is orm.mapper:
+ util.warn_deprecated(
+ "The `sqlalchemy.orm.mapper()` symbol is deprecated and "
+ "will be removed in a future release. For the mapper-wide "
+ "event target, use the 'sqlalchemy.orm.Mapper' class.",
+ "2.0",
+ )
return instrumentation.ClassManager
elif isinstance(target, type):
if issubclass(target, mapperlib.Mapper):
@@ -638,8 +644,8 @@ class MapperEvents(event.Events):
* unmapped superclasses of mapped or to-be-mapped classes
(using the ``propagate=True`` flag)
* :class:`_orm.Mapper` objects
- * the :class:`_orm.Mapper` class itself and the :func:`.mapper`
- function indicate listening for all mappers.
+ * the :class:`_orm.Mapper` class itself indicates listening for all
+ mappers.
Mapper events provide hooks into critical sections of the
mapper, including those related to object instrumentation,
@@ -692,6 +698,12 @@ class MapperEvents(event.Events):
orm = util.preloaded.orm
if target is orm.mapper:
+ util.warn_deprecated(
+ "The `sqlalchemy.orm.mapper()` symbol is deprecated and "
+ "will be removed in a future release. For the mapper-wide "
+ "event target, use the 'sqlalchemy.orm.Mapper' class.",
+ "2.0",
+ )
return mapperlib.Mapper
elif isinstance(target, type):
if issubclass(target, mapperlib.Mapper):
@@ -721,7 +733,7 @@ class MapperEvents(event.Events):
):
util.warn(
"'before_configured' and 'after_configured' ORM events "
- "only invoke with the mapper() function or Mapper class "
+ "only invoke with the Mapper class "
"as the target."
)
@@ -896,13 +908,13 @@ class MapperEvents(event.Events):
new mappers have been made available and new mapper use is
detected.
- This event can **only** be applied to the :class:`_orm.Mapper` class
- or :func:`.mapper` function, and not to individual mappings or
- mapped classes. It is only invoked for all mappings as a whole::
+ This event can **only** be applied to the :class:`_orm.Mapper` class,
+ and not to individual mappings or mapped classes. It is only invoked
+ for all mappings as a whole::
- from sqlalchemy.orm import mapper
+ from sqlalchemy.orm import Mapper
- @event.listens_for(mapper, "before_configured")
+ @event.listens_for(Mapper, "before_configured")
def go():
# ...
@@ -959,13 +971,13 @@ class MapperEvents(event.Events):
Also contrast to :meth:`.MapperEvents.before_configured`,
which is invoked before the series of mappers has been configured.
- This event can **only** be applied to the :class:`_orm.Mapper` class
- or :func:`.mapper` function, and not to individual mappings or
+ This event can **only** be applied to the :class:`_orm.Mapper` class,
+ and not to individual mappings or
mapped classes. It is only invoked for all mappings as a whole::
- from sqlalchemy.orm import mapper
+ from sqlalchemy.orm import Mapper
- @event.listens_for(mapper, "after_configured")
+ @event.listens_for(Mapper, "after_configured")
def go():
# ...
@@ -1005,7 +1017,7 @@ class MapperEvents(event.Events):
The event is often called for a batch of objects of the
same class before their INSERT statements are emitted at
once in a later step. In the extremely rare case that
- this is not desirable, the :func:`.mapper` can be
+ this is not desirable, the :class:`_orm.Mapper` object can be
configured with ``batch=False``, which will cause
batches of instances to be broken up into individual
(and more poorly performing) event->persist->event
@@ -1052,7 +1064,7 @@ class MapperEvents(event.Events):
same class after their INSERT statements have been
emitted at once in a previous step. In the extremely
rare case that this is not desirable, the
- :func:`.mapper` can be configured with ``batch=False``,
+ :class:`_orm.Mapper` object can be configured with ``batch=False``,
which will cause batches of instances to be broken up
into individual (and more poorly performing)
event->persist->event steps.
@@ -1116,7 +1128,7 @@ class MapperEvents(event.Events):
The event is often called for a batch of objects of the
same class before their UPDATE statements are emitted at
once in a later step. In the extremely rare case that
- this is not desirable, the :func:`.mapper` can be
+ this is not desirable, the :class:`_orm.Mapper` can be
configured with ``batch=False``, which will cause
batches of instances to be broken up into individual
(and more poorly performing) event->persist->event
@@ -1180,7 +1192,7 @@ class MapperEvents(event.Events):
The event is often called for a batch of objects of the
same class after their UPDATE statements have been emitted at
once in a previous step. In the extremely rare case that
- this is not desirable, the :func:`.mapper` can be
+ this is not desirable, the :class:`_orm.Mapper` can be
configured with ``batch=False``, which will cause
batches of instances to be broken up into individual
(and more poorly performing) event->persist->event
diff --git a/lib/sqlalchemy/orm/loading.py b/lib/sqlalchemy/orm/loading.py
index 047971d35..796003ebb 100644
--- a/lib/sqlalchemy/orm/loading.py
+++ b/lib/sqlalchemy/orm/loading.py
@@ -262,11 +262,10 @@ def merge_frozen_result(session, statement, frozen_result, load=True):
session.autoflush = autoflush
-@util.deprecated_20(
+@util.became_legacy_20(
":func:`_orm.merge_result`",
alternative="The function as well as the method on :class:`_orm.Query` "
"is superseded by the :func:`_orm.merge_frozen_result` function.",
- becomes_legacy=True,
)
@util.preload_module("sqlalchemy.orm.context")
def merge_result(query, iterator, load=True):
diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py
index 21da7c2f3..bc818559d 100644
--- a/lib/sqlalchemy/orm/mapper.py
+++ b/lib/sqlalchemy/orm/mapper.py
@@ -57,8 +57,6 @@ from ..util import HasMemoized
_mapper_registries = weakref.WeakKeyDictionary()
-_legacy_registry = None
-
def _all_registries():
with _CONFIGURE_MUTEX:
@@ -148,16 +146,15 @@ class Mapper(
):
r"""Direct constructor for a new :class:`_orm.Mapper` object.
- The :func:`_orm.mapper` function is normally invoked through the
+ The :class:`_orm.Mapper` constructor is not called directly, and
+ is normally invoked through the
use of the :class:`_orm.registry` object through either the
:ref:`Declarative <orm_declarative_mapping>` or
:ref:`Imperative <orm_imperative_mapping>` mapping styles.
- .. versionchanged:: 1.4 The :func:`_orm.mapper` function should not
- be called directly for classical mapping; for a classical mapping
- configuration, use the :meth:`_orm.registry.map_imperatively`
- method. The :func:`_orm.mapper` function may become private in a
- future release.
+ .. versionchanged:: 2.0 The public facing ``mapper()`` function is
+ removed; for a classical mapping configuration, use the
+ :meth:`_orm.registry.map_imperatively` method.
Parameters documented below may be passed to either the
:meth:`_orm.registry.map_imperatively` method, or may be passed in the
@@ -1202,8 +1199,7 @@ class Mapper(
# we expect that declarative has applied the class manager
# already and set up a registry. if this is None,
- # we will emit a deprecation warning below when we also see that
- # it has no registry.
+ # this raises as of 2.0.
manager = attributes.manager_of_class(self.class_)
if self.non_primary:
@@ -1251,14 +1247,12 @@ class Mapper(
)
if not manager.registry:
- util.warn_deprecated_20(
- "Calling the mapper() function directly outside of a "
- "declarative registry is deprecated."
+ raise sa_exc.InvalidRequestError(
+ "The _mapper() function may not be invoked directly outside "
+ "of a declarative registry."
" Please use the sqlalchemy.orm.registry.map_imperatively() "
"function for a classical mapping."
)
- assert _legacy_registry is not None
- _legacy_registry._add_manager(manager)
self.class_manager = manager
self.registry = manager.registry
diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py
index 2d574c6b2..e8ec5f156 100644
--- a/lib/sqlalchemy/orm/query.py
+++ b/lib/sqlalchemy/orm/query.py
@@ -677,7 +677,7 @@ class Query(
self._compile_options += opt
return self
- @util.deprecated_20(
+ @util.became_legacy_20(
":meth:`_orm.Query.with_labels` and :meth:`_orm.Query.apply_labels`",
alternative="Use set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL) "
"instead.",
@@ -803,10 +803,9 @@ class Query(
self.load_options += {"_yield_per": count}
return self
- @util.deprecated_20(
+ @util.became_legacy_20(
":meth:`_orm.Query.get`",
alternative="The method is now available as :meth:`_orm.Session.get`",
- becomes_legacy=True,
)
def get(self, ident):
"""Return an instance based on the given primary key identifier,
@@ -933,8 +932,8 @@ class Query(
:func:`~.expression.select`.
The method here accepts mapped classes, :func:`.aliased` constructs,
- and :func:`.mapper` constructs as arguments, which are resolved into
- expression constructs, in addition to appropriate expression
+ and :class:`_orm.Mapper` constructs as arguments, which are resolved
+ into expression constructs, in addition to appropriate expression
constructs.
The correlation arguments are ultimately passed to
@@ -997,10 +996,9 @@ class Query(
self.load_options += {"_invoke_all_eagers": value}
return self
- @util.deprecated_20(
+ @util.became_legacy_20(
":meth:`_orm.Query.with_parent`",
alternative="Use the :func:`_orm.with_parent` standalone construct.",
- becomes_legacy=True,
)
@util.preload_module("sqlalchemy.orm.relationships")
def with_parent(self, instance, property=None, from_entity=None): # noqa
@@ -2046,7 +2044,6 @@ class Query(
return orm_util._getitem(
self,
item,
- allow_negative=not self.session or not self.session.future,
)
@_generative
@@ -2405,11 +2402,10 @@ class Query(
return result
- @util.deprecated_20(
+ @util.became_legacy_20(
":meth:`_orm.Query.merge_result`",
alternative="The method is superseded by the "
":func:`_orm.merge_frozen_result` function.",
- becomes_legacy=True,
enable_warnings=False, # warnings occur via loading.merge_result
)
def merge_result(self, iterator, load=True):
diff --git a/lib/sqlalchemy/orm/relationships.py b/lib/sqlalchemy/orm/relationships.py
index dd58c0201..522947cc5 100644
--- a/lib/sqlalchemy/orm/relationships.py
+++ b/lib/sqlalchemy/orm/relationships.py
@@ -111,7 +111,7 @@ class RelationshipProperty(StrategizedProperty):
passive_updates=True,
enable_typechecks=True,
active_history=False,
- cascade_backrefs=True,
+ cascade_backrefs=False,
)
_dependency_processor = None
@@ -403,21 +403,11 @@ class RelationshipProperty(StrategizedProperty):
:ref:`tutorial_delete_cascade` - Tutorial example describing
a delete cascade.
- :param cascade_backrefs=True:
- A boolean value indicating if the ``save-update`` cascade should
- operate along an assignment event intercepted by a backref.
- When set to ``False``, the attribute managed by this relationship
- will not cascade an incoming transient object into the session of a
- persistent parent, if the event is received via backref.
+ :param cascade_backrefs=False:
+ Legacy; this flag is always False.
- .. deprecated:: 1.4 The
- :paramref:`_orm.relationship.cascade_backrefs`
- flag will default to False in all cases in SQLAlchemy 2.0.
-
- .. seealso::
-
- :ref:`backref_cascade` - Full discussion and examples on how
- the :paramref:`_orm.relationship.cascade_backrefs` option is used.
+ .. versionchanged:: 2.0 "cascade_backrefs" functionality has been
+ removed.
:param collection_class:
A class or callable that returns a new list-holding object. will
@@ -1007,7 +997,13 @@ class RelationshipProperty(StrategizedProperty):
self._user_defined_foreign_keys = foreign_keys
self.collection_class = collection_class
self.passive_deletes = passive_deletes
- self.cascade_backrefs = cascade_backrefs
+
+ if cascade_backrefs:
+ raise sa_exc.ArgumentError(
+ "The 'cascade_backrefs' parameter passed to "
+ "relationship() may only be set to False."
+ )
+
self.passive_updates = passive_updates
self.remote_side = remote_side
self.enable_typechecks = enable_typechecks
diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py
index 62e560475..b1b7005fe 100644
--- a/lib/sqlalchemy/orm/session.py
+++ b/lib/sqlalchemy/orm/session.py
@@ -985,7 +985,7 @@ class Session(_SessionClassMethods):
self,
bind=None,
autoflush=True,
- future=False,
+ future=True,
expire_on_commit=True,
twophase=False,
binds=None,
@@ -1074,20 +1074,7 @@ class Session(_SessionClassMethods):
:ref:`session_committing`
- :param future: if True, use 2.0 style transactional and engine
- behavior. Future mode includes the following behaviors:
-
- * The :class:`_orm.Session` will not use "bound" metadata in order
- to locate an :class:`_engine.Engine`; the engine or engines in use
- must be specified to the constructor of :class:`_orm.Session` or
- otherwise be configured against the :class:`_orm.sessionmaker`
- in use
-
- * The behavior of the :paramref:`_orm.relationship.cascade_backrefs`
- flag on a :func:`_orm.relationship` will always assume
- "False" behavior.
-
- .. versionadded:: 1.4
+ :param future: Deprecated; this flag is always True.
.. seealso::
@@ -1128,6 +1115,12 @@ class Session(_SessionClassMethods):
)
self.identity_map = identity.WeakInstanceDict()
+ if not future:
+ raise sa_exc.ArgumentError(
+ "The 'future' parameter passed to "
+ "Session() may only be set to True."
+ )
+
self._new = {} # InstanceState->object, strong refs object
self._deleted = {} # same
self.bind = bind
@@ -1136,7 +1129,6 @@ class Session(_SessionClassMethods):
self._warn_on_events = False
self._transaction = None
self._nested_transaction = None
- self.future = future
self.hash_key = _new_sessionid()
self.autoflush = autoflush
self.expire_on_commit = expire_on_commit
@@ -1170,33 +1162,6 @@ class Session(_SessionClassMethods):
with self.begin():
yield self
- @property
- @util.deprecated_20(
- ":attr:`_orm.Session.transaction`",
- alternative="For context manager use, use "
- ":meth:`_orm.Session.begin`. To access "
- "the current root transaction, use "
- ":meth:`_orm.Session.get_transaction`.",
- warn_on_attribute_access=True,
- )
- def transaction(self):
- """The current active or inactive :class:`.SessionTransaction`.
-
- May be None if no transaction has begun yet.
-
- .. versionchanged:: 1.4 the :attr:`.Session.transaction` attribute
- is now a read-only descriptor that also may return None if no
- transaction has begun yet.
-
-
- """
- return self._legacy_transaction()
-
- def _legacy_transaction(self):
- if not self.future:
- self._autobegin()
- return self._transaction
-
def in_transaction(self):
"""Return True if this :class:`_orm.Session` has begun a transaction.
@@ -1350,13 +1315,7 @@ class Session(_SessionClassMethods):
If no transaction is in progress, this method is a pass-through.
- In :term:`1.x-style` use, this method rolls back the topmost
- database transaction if no nested transactions are in effect, or
- to the current nested transaction if one is in effect.
-
- When
- :term:`2.0-style` use is in effect via the
- :paramref:`_orm.Session.future` flag, the method always rolls back
+ The method always rolls back
the topmost database transaction, discarding any nested
transactions that may be in progress.
@@ -1370,7 +1329,7 @@ class Session(_SessionClassMethods):
if self._transaction is None:
pass
else:
- self._transaction.rollback(_to_root=self.future)
+ self._transaction.rollback(_to_root=True)
def commit(self):
"""Flush pending changes and commit the current transaction.
@@ -1378,15 +1337,8 @@ class Session(_SessionClassMethods):
If no transaction is in progress, the method will first
"autobegin" a new transaction and commit.
- If :term:`1.x-style` use is in effect and there are currently
- SAVEPOINTs in progress via :meth:`_orm.Session.begin_nested`,
- the operation will release the current SAVEPOINT but not commit
- the outermost database transaction.
-
- If :term:`2.0-style` use is in effect via the
- :paramref:`_orm.Session.future` flag, the outermost database
- transaction is committed unconditionally, automatically releasing any
- SAVEPOINTs in effect.
+ The outermost database transaction is committed unconditionally,
+ automatically releasing any SAVEPOINTs in effect.
.. seealso::
@@ -1399,7 +1351,7 @@ class Session(_SessionClassMethods):
if not self._autobegin():
raise sa_exc.InvalidRequestError("No transaction is begun.")
- self._transaction.commit(_to_root=self.future)
+ self._transaction.commit(_to_root=True)
def prepare(self):
"""Prepare the current transaction in progress for two phase commit.
@@ -1418,7 +1370,7 @@ class Session(_SessionClassMethods):
self._transaction.prepare()
- def connection(self, bind_arguments=None, execution_options=None, **kw):
+ def connection(self, bind_arguments=None, execution_options=None):
r"""Return a :class:`_engine.Connection` object corresponding to this
:class:`.Session` object's transactional state.
@@ -1437,15 +1389,6 @@ class Session(_SessionClassMethods):
"mapper", "bind", "clause", other custom arguments that are passed
to :meth:`.Session.get_bind`.
- :param bind:
- deprecated; use bind_arguments
-
- :param mapper:
- deprecated; use bind_arguments
-
- :param clause:
- deprecated; use bind_arguments
-
:param execution_options: a dictionary of execution options that will
be passed to :meth:`_engine.Connection.execution_options`, **when the
connection is first procured only**. If the connection is already
@@ -1456,17 +1399,15 @@ class Session(_SessionClassMethods):
:ref:`session_transaction_isolation`
- :param \**kw:
- deprecated; use bind_arguments
-
"""
- if not bind_arguments:
- bind_arguments = kw
+ if bind_arguments:
+ bind = bind_arguments.pop("bind", None)
- bind = bind_arguments.pop("bind", None)
- if bind is None:
- bind = self.get_bind(**bind_arguments)
+ if bind is None:
+ bind = self.get_bind(**bind_arguments)
+ else:
+ bind = self.get_bind()
return self._connection_for_bind(
bind,
@@ -1490,7 +1431,6 @@ class Session(_SessionClassMethods):
bind_arguments=None,
_parent_execute_state=None,
_add_event=None,
- **kw,
):
r"""Execute a SQL expression construct.
@@ -1505,8 +1445,8 @@ class Session(_SessionClassMethods):
)
The API contract of :meth:`_orm.Session.execute` is similar to that
- of :meth:`_future.Connection.execute`, the :term:`2.0 style` version
- of :class:`_future.Connection`.
+ of :meth:`_engine.Connection.execute`, the :term:`2.0 style` version
+ of :class:`_engine.Connection`.
.. versionchanged:: 1.4 the :meth:`_orm.Session.execute` method is
now the primary point of ORM statement execution when using
@@ -1539,32 +1479,13 @@ class Session(_SessionClassMethods):
Contents of this dictionary are passed to the
:meth:`.Session.get_bind` method.
- :param mapper:
- deprecated; use the bind_arguments dictionary
-
- :param bind:
- deprecated; use the bind_arguments dictionary
-
- :param \**kw:
- deprecated; use the bind_arguments dictionary
-
:return: a :class:`_engine.Result` object.
"""
statement = coercions.expect(roles.StatementRole, statement)
- if kw:
- util.warn_deprecated_20(
- "Passing bind arguments to Session.execute() as keyword "
- "arguments is deprecated and will be removed SQLAlchemy 2.0. "
- "Please use the bind_arguments parameter."
- )
- if not bind_arguments:
- bind_arguments = kw
- else:
- bind_arguments.update(kw)
- elif not bind_arguments:
+ if not bind_arguments:
bind_arguments = {}
if (
@@ -1848,7 +1769,7 @@ class Session(_SessionClassMethods):
mapped.
:param bind: an :class:`_engine.Engine` or :class:`_engine.Connection`
- object.
+ object.
.. seealso::
@@ -1913,15 +1834,12 @@ class Session(_SessionClassMethods):
:ref:`session_custom_partitioning`.
:param mapper:
- Optional :func:`.mapper` mapped class or instance of
- :class:`_orm.Mapper`. The bind can be derived from a
- :class:`_orm.Mapper`
- first by consulting the "binds" map associated with this
- :class:`.Session`, and secondly by consulting the
- :class:`_schema.MetaData`
- associated with the :class:`_schema.Table` to which the
- :class:`_orm.Mapper`
- is mapped for a bind.
+ Optional mapped class or corresponding :class:`_orm.Mapper` instance.
+ The bind can be derived from a :class:`_orm.Mapper` first by
+ consulting the "binds" map associated with this :class:`.Session`,
+ and secondly by consulting the :class:`_schema.MetaData` associated
+ with the :class:`_schema.Table` to which the :class:`_orm.Mapper` is
+ mapped for a bind.
:param clause:
A :class:`_expression.ClauseElement` (i.e.
@@ -2587,7 +2505,7 @@ class Session(_SessionClassMethods):
)
.. versionadded:: 1.4 Added :meth:`_orm.Session.get`, which is moved
- from the now deprecated :meth:`_orm.Query.get` method.
+ from the now legacy :meth:`_orm.Query.get` method.
:meth:`_orm.Session.get` is special in that it provides direct
access to the identity map of the :class:`.Session`.
diff --git a/lib/sqlalchemy/orm/unitofwork.py b/lib/sqlalchemy/orm/unitofwork.py
index 03456e572..6f85508f3 100644
--- a/lib/sqlalchemy/orm/unitofwork.py
+++ b/lib/sqlalchemy/orm/unitofwork.py
@@ -21,18 +21,6 @@ from .. import util
from ..util import topological
-def _warn_for_cascade_backrefs(state, prop):
- util.warn_deprecated_20(
- '"%s" object is being merged into a Session along the backref '
- 'cascade path for relationship "%s"; in SQLAlchemy 2.0, this '
- "reverse cascade will not take place. Set cascade_backrefs to "
- "False in either the relationship() or backref() function for "
- "the 2.0 behavior; or to set globally for the whole "
- "Session, set the future=True flag" % (state.class_.__name__, prop),
- code="s9r1",
- )
-
-
def track_cascade_events(descriptor, prop):
"""Establish event listeners on object attributes which handle
cascade-on-set/append.
@@ -57,14 +45,9 @@ def track_cascade_events(descriptor, prop):
if (
prop._cascade.save_update
- and (
- (prop.cascade_backrefs and not sess.future)
- or key == initiator.key
- )
+ and (key == initiator.key)
and not sess._contains_state(item_state)
):
- if key != initiator.key:
- _warn_for_cascade_backrefs(item_state, prop)
sess._save_or_update_state(item_state)
return item
@@ -119,14 +102,9 @@ def track_cascade_events(descriptor, prop):
newvalue_state = attributes.instance_state(newvalue)
if (
prop._cascade.save_update
- and (
- (prop.cascade_backrefs and not sess.future)
- or key == initiator.key
- )
+ and (key == initiator.key)
and not sess._contains_state(newvalue_state)
):
- if key != initiator.key:
- _warn_for_cascade_backrefs(newvalue_state, prop)
sess._save_or_update_state(newvalue_state)
if (
diff --git a/lib/sqlalchemy/orm/util.py b/lib/sqlalchemy/orm/util.py
index a282adea4..739d8a4c2 100644
--- a/lib/sqlalchemy/orm/util.py
+++ b/lib/sqlalchemy/orm/util.py
@@ -2046,25 +2046,17 @@ def randomize_unitofwork():
) = session.set = mapper.set = dependency.set = RandomSet
-def _getitem(iterable_query, item, allow_negative):
+def _getitem(iterable_query, item):
"""calculate __getitem__ in terms of an iterable query object
that also has a slice() method.
"""
def _no_negative_indexes():
- if not allow_negative:
- raise IndexError(
- "negative indexes are not accepted by SQL "
- "index / slice operators"
- )
- else:
- util.warn_deprecated_20(
- "Support for negative indexes for SQL index / slice operators "
- "will be "
- "removed in 2.0; these operators fetch the complete result "
- "and do not work efficiently."
- )
+ raise IndexError(
+ "negative indexes are not accepted by SQL "
+ "index / slice operators"
+ )
if isinstance(item, slice):
start, stop, step = util.decode_slice(item)