diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-01-03 13:49:26 -0500 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-01-05 19:28:49 -0500 |
| commit | 01c50c64e302c193733cef7fb146fbab8eaa44bd (patch) | |
| tree | dca946206da557a14a681768d094b92c95dfabe4 /lib/sqlalchemy/orm | |
| parent | 146a349d81023805264f81643db50a5281da90da (diff) | |
| download | sqlalchemy-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__.py | 37 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/context.py | 26 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/decl_api.py | 23 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/events.py | 48 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/loading.py | 3 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/mapper.py | 24 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/query.py | 16 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/relationships.py | 28 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/session.py | 144 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/unitofwork.py | 26 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/util.py | 18 |
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) |
