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 | |
| 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')
28 files changed, 195 insertions, 1031 deletions
diff --git a/lib/sqlalchemy/dialects/mysql/enumerated.py b/lib/sqlalchemy/dialects/mysql/enumerated.py index b84608f58..f92e2cf19 100644 --- a/lib/sqlalchemy/dialects/mysql/enumerated.py +++ b/lib/sqlalchemy/dialects/mysql/enumerated.py @@ -12,7 +12,6 @@ from ... import exc from ... import sql from ... import util from ...sql import sqltypes -from ...sql.base import NO_ARG class ENUM(sqltypes.NativeForEmulated, sqltypes.Enum, _StringType): @@ -59,15 +58,7 @@ class ENUM(sqltypes.NativeForEmulated, sqltypes.Enum, _StringType): BINARY in schema. This does not affect the type of data stored, only the collation of character data. - :param quoting: Not used. A warning will be raised if provided. - """ - if kw.pop("quoting", NO_ARG) is not NO_ARG: - util.warn_deprecated_20( - "The 'quoting' parameter to :class:`.mysql.ENUM` is deprecated" - " and will be removed in a future release. " - "This parameter now has no effect." - ) kw.pop("strict", None) self._enum_init(enums, kw) _StringType.__init__(self, length=self.length, **kw) @@ -151,15 +142,7 @@ class SET(_StringType): .. versionadded:: 1.0.0 - :param quoting: Not used. A warning will be raised if passed. - """ - if kw.pop("quoting", NO_ARG) is not NO_ARG: - util.warn_deprecated_20( - "The 'quoting' parameter to :class:`.mysql.SET` is deprecated" - " and will be removed in a future release. " - "This parameter now has no effect." - ) self.retrieve_as_bitwise = kw.pop("retrieve_as_bitwise", False) self.values = tuple(values) if not self.retrieve_as_bitwise and "" in values: diff --git a/lib/sqlalchemy/engine/reflection.py b/lib/sqlalchemy/engine/reflection.py index e1b06a314..92c243de3 100644 --- a/lib/sqlalchemy/engine/reflection.py +++ b/lib/sqlalchemy/engine/reflection.py @@ -681,17 +681,6 @@ class Inspector: conn, table_name, schema, info_cache=self.info_cache, **kw ) - @util.deprecated_20( - ":meth:`_reflection.Inspector.reflecttable`", - "The :meth:`_reflection.Inspector.reflecttable` " - "method was renamed to " - ":meth:`_reflection.Inspector.reflect_table`. This deprecated alias " - "will be removed in a future release.", - ) - def reflecttable(self, *args, **kwargs): - "See reflect_table. This method name is deprecated" - return self.reflect_table(*args, **kwargs) - def reflect_table( self, table, diff --git a/lib/sqlalchemy/exc.py b/lib/sqlalchemy/exc.py index e51214fd9..77edf98a0 100644 --- a/lib/sqlalchemy/exc.py +++ b/lib/sqlalchemy/exc.py @@ -705,11 +705,7 @@ class LegacyAPIWarning(Base20DeprecationWarning): """indicates an API that is in 'legacy' status, a long term deprecation.""" -class RemovedIn20Warning(Base20DeprecationWarning): - """indicates an API that will be fully removed in SQLAlchemy 2.0.""" - - -class MovedIn20Warning(RemovedIn20Warning): +class MovedIn20Warning(Base20DeprecationWarning): """Subtype of RemovedIn20Warning to indicate an API that moved only.""" diff --git a/lib/sqlalchemy/ext/declarative/__init__.py b/lib/sqlalchemy/ext/declarative/__init__.py index b1c1d3691..ebb992742 100644 --- a/lib/sqlalchemy/ext/declarative/__init__.py +++ b/lib/sqlalchemy/ext/declarative/__init__.py @@ -8,7 +8,6 @@ from .extensions import AbstractConcreteBase from .extensions import ConcreteBase from .extensions import DeferredReflection -from .extensions import instrument_declarative from ... import util from ...orm.decl_api import as_declarative as _as_declarative from ...orm.decl_api import declarative_base as _declarative_base diff --git a/lib/sqlalchemy/ext/declarative/extensions.py b/lib/sqlalchemy/ext/declarative/extensions.py index 1862592f5..b7c0e78d9 100644 --- a/lib/sqlalchemy/ext/declarative/extensions.py +++ b/lib/sqlalchemy/ext/declarative/extensions.py @@ -8,9 +8,7 @@ from ... import inspection -from ... import util from ...orm import exc as orm_exc -from ...orm import registry from ...orm import relationships from ...orm.base import _mapper_or_none from ...orm.clsregistry import _resolver @@ -20,23 +18,6 @@ from ...schema import Table from ...util import OrderedDict -@util.deprecated( - "2.0", - "the instrument_declarative function is deprecated " - "and will be removed in SQLAlhcemy 2.0. Please use " - ":meth:`_orm.registry.map_declaratively", -) -def instrument_declarative(cls, cls_registry, metadata): - """Given a class, configure the class declaratively, - using the given registry, which can be any dictionary, and - MetaData object. - - """ - registry(metadata=metadata, class_registry=cls_registry).map_declaratively( - cls - ) - - class ConcreteBase: """A helper class for 'concrete' declarative mappings. diff --git a/lib/sqlalchemy/ext/mutable.py b/lib/sqlalchemy/ext/mutable.py index 7e277d379..7a497abfc 100644 --- a/lib/sqlalchemy/ext/mutable.py +++ b/lib/sqlalchemy/ext/mutable.py @@ -360,7 +360,6 @@ from .. import event from .. import inspect from .. import types from ..orm import Mapper -from ..orm import mapper from ..orm.attributes import flag_modified from ..sql.base import SchemaEventTarget from ..util import memoized_property @@ -567,7 +566,7 @@ class Mutable(MutableBase): if isinstance(prop.columns[0].type, sqltype): cls.associate_with_attribute(getattr(class_, prop.key)) - event.listen(mapper, "mapper_configured", listen_for_type) + event.listen(Mapper, "mapper_configured", listen_for_type) @classmethod def as_mutable(cls, sqltype): @@ -629,7 +628,7 @@ class Mutable(MutableBase): ) or (prop.columns[0].type is sqltype): cls.associate_with_attribute(getattr(class_, prop.key)) - event.listen(mapper, "mapper_configured", listen_for_type) + event.listen(Mapper, "mapper_configured", listen_for_type) return sqltype 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) diff --git a/lib/sqlalchemy/sql/coercions.py b/lib/sqlalchemy/sql/coercions.py index d11ab6712..fe4fc4b40 100644 --- a/lib/sqlalchemy/sql/coercions.py +++ b/lib/sqlalchemy/sql/coercions.py @@ -99,14 +99,15 @@ def _document_text_coercion(paramname, meth_rst, param_rst): def _expression_collection_was_a_list(attrname, fnname, args): if args and isinstance(args[0], (list, set, dict)) and len(args) == 1: if isinstance(args[0], list): - util.warn_deprecated_20( - 'The "%s" argument to %s(), when referring to a sequence ' + raise exc.ArgumentError( + f'The "{attrname}" argument to {fnname}(), when ' + "referring to a sequence " "of items, is now passed as a series of positional " - "elements, rather than as a list. " % (attrname, fnname) + "elements, rather than as a list. " ) return args[0] - else: - return args + + return args def expect( @@ -883,15 +884,6 @@ class StatementImpl(_CoerceLiterals, RoleImpl): original_element, resolved, argname=argname, **kw ) - def _text_coercion(self, element, argname=None): - util.warn_deprecated_20( - "Using plain strings to indicate SQL statements without using " - "the text() construct is " - "deprecated and will be removed in version 2.0. Ensure plain " - "SQL statements are passed using the text() construct." - ) - return elements.TextClause(element) - class SelectStatementImpl(_NoTextCoercion, RoleImpl): __slots__ = () diff --git a/lib/sqlalchemy/sql/dml.py b/lib/sqlalchemy/sql/dml.py index feb286d65..fad1728f8 100644 --- a/lib/sqlalchemy/sql/dml.py +++ b/lib/sqlalchemy/sql/dml.py @@ -237,66 +237,6 @@ class UpdateBase( is_dml = True - @classmethod - def _constructor_20_deprecations(cls, fn_name, clsname, names): - - param_to_method_lookup = dict( - whereclause=( - "The :paramref:`%(func)s.whereclause` parameter " - "will be removed " - "in SQLAlchemy 2.0. Please refer to the " - ":meth:`%(classname)s.where` method." - ), - values=( - "The :paramref:`%(func)s.values` parameter will be removed " - "in SQLAlchemy 2.0. Please refer to the " - ":meth:`%(classname)s.values` method." - ), - inline=( - "The :paramref:`%(func)s.inline` parameter will be " - "removed in " - "SQLAlchemy 2.0. Please use the " - ":meth:`%(classname)s.inline` method." - ), - prefixes=( - "The :paramref:`%(func)s.prefixes parameter will be " - "removed in " - "SQLAlchemy 2.0. Please use the " - ":meth:`%(classname)s.prefix_with` " - "method." - ), - return_defaults=( - "The :paramref:`%(func)s.return_defaults` parameter will be " - "removed in SQLAlchemy 2.0. Please use the " - ":meth:`%(classname)s.return_defaults` method." - ), - returning=( - "The :paramref:`%(func)s.returning` parameter will be " - "removed in SQLAlchemy 2.0. Please use the " - ":meth:`%(classname)s.returning`` method." - ), - preserve_parameter_order=( - "The :paramref:`%(func)s.preserve_parameter_order` parameter " - "will be removed in SQLAlchemy 2.0. Use the " - ":meth:`%(classname)s.ordered_values` method with a list " - "of tuples. " - ), - ) - - return util.deprecated_params( - **{ - name: ( - "2.0", - param_to_method_lookup[name] - % { - "func": "_expression.%s" % fn_name, - "classname": "_expression.%s" % clsname, - }, - ) - for name in names - } - ) - def _generate_fromclause_column_proxies(self, fromclause): fromclause._columns._populate_separate_keys( col._make_proxy(fromclause) for col in self._returning @@ -332,15 +272,6 @@ class UpdateBase( self._validate_dialect_kwargs(opt) return self - def _validate_dialect_kwargs_deprecated(self, dialect_kw): - util.warn_deprecated_20( - "Passing dialect keyword arguments directly to the " - "%s constructor is deprecated and will be removed in SQLAlchemy " - "2.0. Please use the ``with_dialect_options()`` method." - % (self.__class__.__name__) - ) - self._validate_dialect_kwargs(dialect_kw) - @_generative def returning(self: SelfUpdateBase, *cols) -> SelfUpdateBase: r"""Add a :term:`RETURNING` or equivalent clause to this statement. @@ -499,14 +430,10 @@ class ValuesBase(UpdateBase): _returning = () - def __init__(self, table, values, prefixes): + def __init__(self, table): self.table = coercions.expect( roles.DMLTableRole, table, apply_propagate_attrs=self ) - if values is not None: - self.values.non_generative(self, values) - if prefixes: - self._setup_prefixes(prefixes) @_generative @_exclusive_against( @@ -765,7 +692,7 @@ class ValuesBase(UpdateBase): :meth:`.ValuesBase.return_defaults` is used by the ORM to provide an efficient implementation for the ``eager_defaults`` feature of - :func:`.mapper`. + :class:`_orm.Mapper`. :param cols: optional list of column key names or :class:`_schema.Column` @@ -809,6 +736,7 @@ class Insert(ValuesBase): select = None include_insert_from_select_defaults = False + _inline = False is_insert = True @@ -835,26 +763,9 @@ class Insert(ValuesBase): + HasCTE._has_ctes_traverse_internals ) - @ValuesBase._constructor_20_deprecations( - "insert", - "Insert", - [ - "values", - "inline", - "prefixes", - "returning", - "return_defaults", - ], - ) def __init__( self, table, - values=None, - inline=False, - prefixes=None, - returning=None, - return_defaults=False, - **dialect_kw, ): """Construct an :class:`_expression.Insert` object. @@ -922,17 +833,7 @@ class Insert(ValuesBase): :ref:`inserts_and_updates` - SQL Expression Tutorial """ - super(Insert, self).__init__(table, values, prefixes) - self._inline = inline - if returning: - self._returning = returning - if dialect_kw: - self._validate_dialect_kwargs_deprecated(dialect_kw) - - if return_defaults: - self._return_defaults = True - if not isinstance(return_defaults, bool): - self._return_defaults_columns = return_defaults + super(Insert, self).__init__(table) @_generative def inline(self: SelfInsert) -> SelfInsert: @@ -1120,6 +1021,8 @@ class Update(DMLWhereBase, ValuesBase): __visit_name__ = "update" is_update = True + _preserve_parameter_order = False + _inline = False _traverse_internals = ( [ @@ -1142,30 +1045,9 @@ class Update(DMLWhereBase, ValuesBase): + HasCTE._has_ctes_traverse_internals ) - @ValuesBase._constructor_20_deprecations( - "update", - "Update", - [ - "whereclause", - "values", - "inline", - "prefixes", - "returning", - "return_defaults", - "preserve_parameter_order", - ], - ) def __init__( self, table, - whereclause=None, - values=None, - inline=False, - prefixes=None, - returning=None, - return_defaults=False, - preserve_parameter_order=False, - **dialect_kw, ): r"""Construct an :class:`_expression.Update` object. @@ -1275,18 +1157,7 @@ class Update(DMLWhereBase, ValuesBase): """ - self._preserve_parameter_order = preserve_parameter_order - super(Update, self).__init__(table, values, prefixes) - if returning: - self._returning = returning - if whereclause is not None: - self._where_criteria += ( - coercions.expect(roles.WhereHavingRole, whereclause), - ) - self._inline = inline - if dialect_kw: - self._validate_dialect_kwargs_deprecated(dialect_kw) - self._return_defaults = return_defaults + super(Update, self).__init__(table) @_generative def ordered_values(self: SelfUpdate, *args) -> SelfUpdate: @@ -1373,18 +1244,9 @@ class Delete(DMLWhereBase, UpdateBase): + HasCTE._has_ctes_traverse_internals ) - @ValuesBase._constructor_20_deprecations( - "delete", - "Delete", - ["whereclause", "values", "prefixes", "returning"], - ) def __init__( self, table, - whereclause=None, - returning=None, - prefixes=None, - **dialect_kw, ): r"""Construct :class:`_expression.Delete` object. @@ -1424,16 +1286,3 @@ class Delete(DMLWhereBase, UpdateBase): self.table = coercions.expect( roles.DMLTableRole, table, apply_propagate_attrs=self ) - if returning: - self._returning = returning - - if prefixes: - self._setup_prefixes(prefixes) - - if whereclause is not None: - self._where_criteria += ( - coercions.expect(roles.WhereHavingRole, whereclause), - ) - - if dialect_kw: - self._validate_dialect_kwargs_deprecated(dialect_kw) diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py index 6e5fbba88..3ec702e10 100644 --- a/lib/sqlalchemy/sql/elements.py +++ b/lib/sqlalchemy/sql/elements.py @@ -2785,10 +2785,7 @@ class Case(ColumnElement): ("else_", InternalTraversal.dp_clauseelement), ] - # TODO: for Py2k removal, this will be: - # def __init__(self, *whens, value=None, else_=None): - - def __init__(self, *whens, **kw): + def __init__(self, *whens, value=None, else_=None): r"""Produce a ``CASE`` expression. The ``CASE`` construct in SQL is a conditional object that @@ -2875,8 +2872,7 @@ class Case(ColumnElement): whether or not :paramref:`.case.value` is used. .. versionchanged:: 1.4 the :func:`_sql.case` - function now accepts the series of WHEN conditions positionally; - passing the expressions within a list is deprecated. + function now accepts the series of WHEN conditions positionally In the first form, it accepts a list of 2-tuples; each 2-tuple consists of ``(<sql expression>, <value>)``, where the SQL @@ -2911,24 +2907,14 @@ class Case(ColumnElement): """ - if "whens" in kw: - util.warn_deprecated_20( - 'The "whens" argument to case() is now passed using ' - "positional style only, not as a keyword argument." - ) - whens = (kw.pop("whens"),) - whens = coercions._expression_collection_was_a_list( "whens", "case", whens ) - try: whens = util.dictlike_iteritems(whens) except TypeError: pass - value = kw.pop("value", None) - whenlist = [ ( coercions.expect( @@ -2954,15 +2940,11 @@ class Case(ColumnElement): self.type = type_ self.whens = whenlist - else_ = kw.pop("else_", None) if else_ is not None: self.else_ = coercions.expect(roles.ExpressionElementRole, else_) else: self.else_ = None - if kw: - raise TypeError("unknown arguments: %s" % (", ".join(sorted(kw)))) - @property def _from_objects(self): return list( diff --git a/lib/sqlalchemy/sql/schema.py b/lib/sqlalchemy/sql/schema.py index a5fdd39d4..d836384b4 100644 --- a/lib/sqlalchemy/sql/schema.py +++ b/lib/sqlalchemy/sql/schema.py @@ -538,12 +538,6 @@ class Table(DialectKWArgs, SchemaItem, TableClause): "1.4", "Deprecated alias of :paramref:`_schema.Table.must_exist`", ), - autoload=( - "2.0", - "The autoload parameter is deprecated and will be removed in " - "version 2.0. Please use the " - "autoload_with parameter, passing an engine or connection.", - ), ) def __new__(cls, *args, **kw): if not args and not kw: @@ -638,7 +632,7 @@ class Table(DialectKWArgs, SchemaItem, TableClause): self.fullname = self.name autoload_with = kwargs.pop("autoload_with", None) - autoload = kwargs.pop("autoload", autoload_with is not None) + autoload = autoload_with is not None # this argument is only used with _init_existing() kwargs.pop("autoload_replace", True) keep_existing = kwargs.pop("keep_existing", False) diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py index 9c5850761..046b41d89 100644 --- a/lib/sqlalchemy/sql/selectable.py +++ b/lib/sqlalchemy/sql/selectable.py @@ -1360,110 +1360,6 @@ class Join(roles.DMLTableRole, FromClause): .alias(name) ) - @util.deprecated_20( - ":meth:`_sql.Join.alias`", - alternative="Create a select + subquery, or alias the " - "individual tables inside the join, instead.", - ) - def alias(self, name=None, flat=False): - r"""Return an alias of this :class:`_expression.Join`. - - The default behavior here is to first produce a SELECT - construct from this :class:`_expression.Join`, then to produce an - :class:`_expression.Alias` from that. So given a join of the form:: - - j = table_a.join(table_b, table_a.c.id == table_b.c.a_id) - - The JOIN by itself would look like:: - - table_a JOIN table_b ON table_a.id = table_b.a_id - - Whereas the alias of the above, ``j.alias()``, would in a - SELECT context look like:: - - (SELECT table_a.id AS table_a_id, table_b.id AS table_b_id, - table_b.a_id AS table_b_a_id - FROM table_a - JOIN table_b ON table_a.id = table_b.a_id) AS anon_1 - - The equivalent long-hand form, given a :class:`_expression.Join` - object ``j``, is:: - - from sqlalchemy import select, alias - j = alias( - select(j.left, j.right).\ - select_from(j).\ - set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL).\ - correlate(False), - name=name - ) - - The selectable produced by :meth:`_expression.Join.alias` - features the same - columns as that of the two individual selectables presented under - a single name - the individual columns are "auto-labeled", meaning - the ``.c.`` collection of the resulting :class:`_expression.Alias` - represents - the names of the individual columns using a - ``<tablename>_<columname>`` scheme:: - - j.c.table_a_id - j.c.table_b_a_id - - :meth:`_expression.Join.alias` also features an alternate - option for aliasing joins which produces no enclosing SELECT and - does not normally apply labels to the column names. The - ``flat=True`` option will call :meth:`_expression.FromClause.alias` - against the left and right sides individually. - Using this option, no new ``SELECT`` is produced; - we instead, from a construct as below:: - - j = table_a.join(table_b, table_a.c.id == table_b.c.a_id) - j = j.alias(flat=True) - - we get a result like this:: - - table_a AS table_a_1 JOIN table_b AS table_b_1 ON - table_a_1.id = table_b_1.a_id - - The ``flat=True`` argument is also propagated to the contained - selectables, so that a composite join such as:: - - j = table_a.join( - table_b.join(table_c, - table_b.c.id == table_c.c.b_id), - table_b.c.a_id == table_a.c.id - ).alias(flat=True) - - Will produce an expression like:: - - table_a AS table_a_1 JOIN ( - table_b AS table_b_1 JOIN table_c AS table_c_1 - ON table_b_1.id = table_c_1.b_id - ) ON table_a_1.id = table_b_1.a_id - - The standalone :func:`_expression.alias` function as well as the - base :meth:`_expression.FromClause.alias` - method also support the ``flat=True`` - argument as a no-op, so that the argument can be passed to the - ``alias()`` method of any selectable. - - :param name: name given to the alias. - - :param flat: if True, produce an alias of the left and right - sides of this :class:`_expression.Join` and return the join of those - two selectables. This produces join expression that does not - include an enclosing SELECT. - - .. seealso:: - - :ref:`core_tutorial_aliases` - - :func:`_expression.alias` - - """ - return self._anonymous_fromclause(flat=flat, name=name) - @property def _hide_froms(self): return itertools.chain( @@ -2618,7 +2514,6 @@ class TableClause(roles.DMLTableRole, Immutable, FromClause): .. versionadded:: 1.3.18 :func:`_expression.table` can now accept a ``schema`` argument. """ - super(TableClause, self).__init__() self.name = name self._columns = DedupeColumnCollection() @@ -2665,7 +2560,7 @@ class TableClause(roles.DMLTableRole, Immutable, FromClause): c.table = self @util.preload_module("sqlalchemy.sql.dml") - def insert(self, values=None, inline=False, **kwargs): + def insert(self): """Generate an :func:`_expression.insert` construct against this :class:`_expression.TableClause`. @@ -2676,12 +2571,10 @@ class TableClause(roles.DMLTableRole, Immutable, FromClause): See :func:`_expression.insert` for argument and usage information. """ - return util.preloaded.sql_dml.Insert( - self, values=values, inline=inline, **kwargs - ) + return util.preloaded.sql_dml.Insert(self) @util.preload_module("sqlalchemy.sql.dml") - def update(self, whereclause=None, values=None, inline=False, **kwargs): + def update(self): """Generate an :func:`_expression.update` construct against this :class:`_expression.TableClause`. @@ -2694,14 +2587,10 @@ class TableClause(roles.DMLTableRole, Immutable, FromClause): """ return util.preloaded.sql_dml.Update( self, - whereclause=whereclause, - values=values, - inline=inline, - **kwargs, ) @util.preload_module("sqlalchemy.sql.dml") - def delete(self, whereclause=None, **kwargs): + def delete(self): """Generate a :func:`_expression.delete` construct against this :class:`_expression.TableClause`. @@ -2712,7 +2601,7 @@ class TableClause(roles.DMLTableRole, Immutable, FromClause): See :func:`_expression.delete` for argument and usage information. """ - return util.preloaded.sql_dml.Delete(self, whereclause, **kwargs) + return util.preloaded.sql_dml.Delete(self) @property def _from_objects(self): @@ -2806,7 +2695,7 @@ class Values(Generative, FromClause): ("literal_binds", InternalTraversal.dp_boolean), ] - def __init__(self, *columns, **kw): + def __init__(self, *columns, name=None, literal_binds=False): r"""Construct a :class:`_expression.Values` construct. The column expressions and the actual data for @@ -2844,8 +2733,8 @@ class Values(Generative, FromClause): super(Values, self).__init__() self._column_args = columns - self.name = kw.pop("name", None) - self.literal_binds = kw.pop("literal_binds", False) + self.name = name + self.literal_binds = literal_binds self.named_with_column = self.name is not None @property @@ -3286,65 +3175,12 @@ class SelectStatementGrouping(GroupedElement, SelectBase): return self.element._from_objects -class DeprecatedSelectBaseGenerations: - """A collection of methods available on :class:`_sql.Select` and - :class:`_sql.CompoundSelect`, these are all **deprecated** methods as they - modify the object in-place. - - """ - - @util.deprecated( - "1.4", - "The :meth:`_expression.GenerativeSelect.append_order_by` " - "method is deprecated " - "and will be removed in a future release. Use the generative method " - ":meth:`_expression.GenerativeSelect.order_by`.", - ) - def append_order_by(self, *clauses): - """Append the given ORDER BY criterion applied to this selectable. - - The criterion will be appended to any pre-existing ORDER BY criterion. - - This is an **in-place** mutation method; the - :meth:`_expression.GenerativeSelect.order_by` method is preferred, - as it - provides standard :term:`method chaining`. - - .. seealso:: - - :meth:`_expression.GenerativeSelect.order_by` - - """ - self.order_by.non_generative(self, *clauses) - - @util.deprecated( - "1.4", - "The :meth:`_expression.GenerativeSelect.append_group_by` " - "method is deprecated " - "and will be removed in a future release. Use the generative method " - ":meth:`_expression.GenerativeSelect.group_by`.", - ) - def append_group_by(self, *clauses): - """Append the given GROUP BY criterion applied to this selectable. - - The criterion will be appended to any pre-existing GROUP BY criterion. - - This is an **in-place** mutation method; the - :meth:`_expression.GenerativeSelect.group_by` method is preferred, - as it - provides standard :term:`method chaining`. - - - """ - self.group_by.non_generative(self, *clauses) - - SelfGenerativeSelect = typing.TypeVar( "SelfGenerativeSelect", bound="GenerativeSelect" ) -class GenerativeSelect(DeprecatedSelectBaseGenerations, SelectBase): +class GenerativeSelect(SelectBase): """Base class for SELECT statements where additional elements can be added. @@ -3368,39 +3204,9 @@ class GenerativeSelect(DeprecatedSelectBaseGenerations, SelectBase): _fetch_clause_options = None _for_update_arg = None - def __init__( - self, - _label_style=LABEL_STYLE_DEFAULT, - use_labels=False, - limit=None, - offset=None, - order_by=None, - group_by=None, - ): - if use_labels: - if util.SQLALCHEMY_WARN_20: - util.warn_deprecated_20( - "The use_labels=True keyword argument to GenerativeSelect " - "is deprecated and will be removed in version 2.0. Please " - "use " - "select.set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL) " - "if you need to replicate this legacy behavior.", - stacklevel=4, - ) - _label_style = LABEL_STYLE_TABLENAME_PLUS_COL - + def __init__(self, _label_style=LABEL_STYLE_DEFAULT): self._label_style = _label_style - if limit is not None: - self.limit.non_generative(self, limit) - if offset is not None: - self.offset.non_generative(self, offset) - - if order_by is not None: - self.order_by.non_generative(self, *util.to_list(order_by)) - if group_by is not None: - self.group_by.non_generative(self, *util.to_list(group_by)) - @_generative def with_for_update( self: SelfGenerativeSelect, @@ -3516,14 +3322,6 @@ class GenerativeSelect(DeprecatedSelectBaseGenerations, SelectBase): self._label_style = style return self - @util.deprecated_20( - ":meth:`_sql.GenerativeSelect.apply_labels`", - alternative="Use set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL) " - "instead.", - ) - def apply_labels(self): - return self.set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL) - @property def _group_by_clause(self): """ClauseList access to group_by_clauses for legacy dialects""" @@ -3894,9 +3692,9 @@ class CompoundSelect(HasCompileState, GenerativeSelect): INTERSECT_ALL = util.symbol("INTERSECT ALL") _is_from_container = True + _auto_correlate = False - def __init__(self, keyword, *selects, **kwargs): - self._auto_correlate = kwargs.pop("correlate", False) + def __init__(self, keyword, *selects): self.keyword = keyword self.selects = [ coercions.expect(roles.CompoundElementRole, s).self_group( @@ -3905,17 +3703,7 @@ class CompoundSelect(HasCompileState, GenerativeSelect): for s in selects ] - if kwargs and util.SQLALCHEMY_WARN_20: - util.warn_deprecated_20( - "Set functions such as union(), union_all(), extract(), etc. " - "in SQLAlchemy 2.0 will accept a " - "series of SELECT statements only. " - "Please use generative methods such as order_by() for " - "additional modifications to this CompoundSelect.", - stacklevel=4, - ) - - GenerativeSelect.__init__(self, **kwargs) + GenerativeSelect.__init__(self) @classmethod def _create_union(cls, *selects, **kwargs): @@ -3938,7 +3726,7 @@ class CompoundSelect(HasCompileState, GenerativeSelect): return CompoundSelect(CompoundSelect.UNION, *selects, **kwargs) @classmethod - def _create_union_all(cls, *selects, **kwargs): + def _create_union_all(cls, *selects): r"""Return a ``UNION ALL`` of multiple selectables. The returned object is an instance of @@ -3950,15 +3738,11 @@ class CompoundSelect(HasCompileState, GenerativeSelect): :param \*selects: a list of :class:`_expression.Select` instances. - :param \**kwargs: - available keyword arguments are the same as those of - :func:`select`. - """ - return CompoundSelect(CompoundSelect.UNION_ALL, *selects, **kwargs) + return CompoundSelect(CompoundSelect.UNION_ALL, *selects) @classmethod - def _create_except(cls, *selects, **kwargs): + def _create_except(cls, *selects): r"""Return an ``EXCEPT`` of multiple selectables. The returned object is an instance of @@ -3967,15 +3751,11 @@ class CompoundSelect(HasCompileState, GenerativeSelect): :param \*selects: a list of :class:`_expression.Select` instances. - :param \**kwargs: - available keyword arguments are the same as those of - :func:`select`. - """ - return CompoundSelect(CompoundSelect.EXCEPT, *selects, **kwargs) + return CompoundSelect(CompoundSelect.EXCEPT, *selects) @classmethod - def _create_except_all(cls, *selects, **kwargs): + def _create_except_all(cls, *selects): r"""Return an ``EXCEPT ALL`` of multiple selectables. The returned object is an instance of @@ -3984,15 +3764,11 @@ class CompoundSelect(HasCompileState, GenerativeSelect): :param \*selects: a list of :class:`_expression.Select` instances. - :param \**kwargs: - available keyword arguments are the same as those of - :func:`select`. - """ - return CompoundSelect(CompoundSelect.EXCEPT_ALL, *selects, **kwargs) + return CompoundSelect(CompoundSelect.EXCEPT_ALL, *selects) @classmethod - def _create_intersect(cls, *selects, **kwargs): + def _create_intersect(cls, *selects): r"""Return an ``INTERSECT`` of multiple selectables. The returned object is an instance of @@ -4001,15 +3777,11 @@ class CompoundSelect(HasCompileState, GenerativeSelect): :param \*selects: a list of :class:`_expression.Select` instances. - :param \**kwargs: - available keyword arguments are the same as those of - :func:`select`. - """ - return CompoundSelect(CompoundSelect.INTERSECT, *selects, **kwargs) + return CompoundSelect(CompoundSelect.INTERSECT, *selects) @classmethod - def _create_intersect_all(cls, *selects, **kwargs): + def _create_intersect_all(cls, *selects): r"""Return an ``INTERSECT ALL`` of multiple selectables. The returned object is an instance of @@ -4018,12 +3790,9 @@ class CompoundSelect(HasCompileState, GenerativeSelect): :param \*selects: a list of :class:`_expression.Select` instances. - :param \**kwargs: - available keyword arguments are the same as those of - :func:`select`. """ - return CompoundSelect(CompoundSelect.INTERSECT_ALL, *selects, **kwargs) + return CompoundSelect(CompoundSelect.INTERSECT_ALL, *selects) def _scalar_type(self): return self.selects[0]._scalar_type() @@ -4117,134 +3886,6 @@ class CompoundSelect(HasCompileState, GenerativeSelect): return self.selects[0].selected_columns -class DeprecatedSelectGenerations: - """A collection of methods available on :class:`_sql.Select`, these - are all **deprecated** methods as they modify the :class:`_sql.Select` - object in -place. - - """ - - @util.deprecated( - "1.4", - "The :meth:`_expression.Select.append_correlation` " - "method is deprecated " - "and will be removed in a future release. Use the generative " - "method :meth:`_expression.Select.correlate`.", - ) - def append_correlation(self, fromclause): - """Append the given correlation expression to this select() - construct. - - This is an **in-place** mutation method; the - :meth:`_expression.Select.correlate` method is preferred, - as it provides - standard :term:`method chaining`. - - """ - - self.correlate.non_generative(self, fromclause) - - @util.deprecated( - "1.4", - "The :meth:`_expression.Select.append_column` method is deprecated " - "and will be removed in a future release. Use the generative " - "method :meth:`_expression.Select.add_columns`.", - ) - def append_column(self, column): - """Append the given column expression to the columns clause of this - select() construct. - - E.g.:: - - my_select.append_column(some_table.c.new_column) - - This is an **in-place** mutation method; the - :meth:`_expression.Select.add_columns` method is preferred, - as it provides standard - :term:`method chaining`. - - """ - self.add_columns.non_generative(self, column) - - @util.deprecated( - "1.4", - "The :meth:`_expression.Select.append_prefix` method is deprecated " - "and will be removed in a future release. Use the generative " - "method :meth:`_expression.Select.prefix_with`.", - ) - def append_prefix(self, clause): - """Append the given columns clause prefix expression to this select() - construct. - - This is an **in-place** mutation method; the - :meth:`_expression.Select.prefix_with` method is preferred, - as it provides - standard :term:`method chaining`. - - """ - self.prefix_with.non_generative(self, clause) - - @util.deprecated( - "1.4", - "The :meth:`_expression.Select.append_whereclause` " - "method is deprecated " - "and will be removed in a future release. Use the generative " - "method :meth:`_expression.Select.where`.", - ) - def append_whereclause(self, whereclause): - """Append the given expression to this select() construct's WHERE - criterion. - - The expression will be joined to existing WHERE criterion via AND. - - This is an **in-place** mutation method; the - :meth:`_expression.Select.where` method is preferred, - as it provides standard - :term:`method chaining`. - - """ - self.where.non_generative(self, whereclause) - - @util.deprecated( - "1.4", - "The :meth:`_expression.Select.append_having` method is deprecated " - "and will be removed in a future release. Use the generative " - "method :meth:`_expression.Select.having`.", - ) - def append_having(self, having): - """Append the given expression to this select() construct's HAVING - criterion. - - The expression will be joined to existing HAVING criterion via AND. - - This is an **in-place** mutation method; the - :meth:`_expression.Select.having` method is preferred, - as it provides standard - :term:`method chaining`. - - """ - - self.having.non_generative(self, having) - - @util.deprecated( - "1.4", - "The :meth:`_expression.Select.append_from` method is deprecated " - "and will be removed in a future release. Use the generative " - "method :meth:`_expression.Select.select_from`.", - ) - def append_from(self, fromclause): - """Append the given :class:`_expression.FromClause` expression - to this select() construct's FROM clause. - - This is an **in-place** mutation method; the - :meth:`_expression.Select.select_from` method is preferred, - as it provides - standard :term:`method chaining`. - - """ - self.select_from.non_generative(self, fromclause) - - @CompileState.plugin_for("default", "select") class SelectState(util.MemoizedSlots, CompileState): __slots__ = ( @@ -4700,7 +4341,6 @@ class Select( HasSuffixes, HasHints, HasCompileState, - DeprecatedSelectGenerations, _SelectFromElements, GenerativeSelect, ): @@ -5345,7 +4985,9 @@ class Select( ) @_generative - def with_only_columns(self: SelfSelect, *columns, **kw) -> SelfSelect: + def with_only_columns( + self: SelfSelect, *columns, maintain_column_froms=False + ) -> SelfSelect: r"""Return a new :func:`_expression.select` construct with its columns clause replaced with the given columns. @@ -5404,10 +5046,6 @@ class Select( # is the case for now. self._assert_no_memoizations() - maintain_column_froms = kw.pop("maintain_column_froms", False) - if kw: - raise TypeError("unknown parameters: %s" % (", ".join(kw),)) - if maintain_column_froms: self.select_from.non_generative(self, *self.columns_clause_froms) diff --git a/lib/sqlalchemy/sql/sqltypes.py b/lib/sqlalchemy/sql/sqltypes.py index cb44fc086..3c1632172 100644 --- a/lib/sqlalchemy/sql/sqltypes.py +++ b/lib/sqlalchemy/sql/sqltypes.py @@ -1207,14 +1207,9 @@ class Enum(Emulated, String, SchemaType): .. versionadded:: 1.3.8 :param omit_aliases: A boolean that when true will remove aliases from - pep 435 enums. For backward compatibility it defaults to ``False``. - A deprecation warning is raised if the enum has aliases and this - flag was not set. + pep 435 enums. defaults to ``True``. - .. versionadded:: 1.4.5 - - .. deprecated:: 1.4 The default will be changed to ``True`` in - SQLAlchemy 2.0. + .. versionchanged:: 2.0 This parameter now defaults to True. """ self._enum_init(enums, kw) @@ -1239,7 +1234,7 @@ class Enum(Emulated, String, SchemaType): self.values_callable = kw.pop("values_callable", None) self._sort_key_function = kw.pop("sort_key_function", NO_ARG) length_arg = kw.pop("length", NO_ARG) - self._omit_aliases = kw.pop("omit_aliases", NO_ARG) + self._omit_aliases = kw.pop("omit_aliases", True) values, objects = self._parse_into_values(enums, kw) self._setup_for_values(values, objects, kw) @@ -1284,14 +1279,6 @@ class Enum(Emulated, String, SchemaType): _members = self.enum_class.__members__ - aliases = [n for n, v in _members.items() if v.name != n] - if self._omit_aliases is NO_ARG and aliases: - util.warn_deprecated_20( - "The provided enum %s contains the aliases %s. The " - "``omit_aliases`` will default to ``True`` in SQLAlchemy " - "2.0. Specify a value to silence this warning." - % (self.enum_class.__name__, aliases) - ) if self._omit_aliases is True: # remove aliases members = OrderedDict( diff --git a/lib/sqlalchemy/testing/assertions.py b/lib/sqlalchemy/testing/assertions.py index 795b53804..978e6764f 100644 --- a/lib/sqlalchemy/testing/assertions.py +++ b/lib/sqlalchemy/testing/assertions.py @@ -31,7 +31,7 @@ from ..util import decorator def expect_warnings(*messages, **kw): """Context manager which expects one or more warnings. - With no arguments, squelches all SAWarning and RemovedIn20Warning emitted via + With no arguments, squelches all SAWarning emitted via sqlalchemy.util.warn and sqlalchemy.util.warn_limited. Otherwise pass string expressions that will match selected warnings via regex; all non-matching warnings are sent through. @@ -41,9 +41,7 @@ def expect_warnings(*messages, **kw): Note that the test suite sets SAWarning warnings to raise exceptions. """ # noqa - return _expect_warnings( - (sa_exc.RemovedIn20Warning, sa_exc.SAWarning), messages, **kw - ) + return _expect_warnings(sa_exc.SAWarning, messages, **kw) @contextlib.contextmanager @@ -199,9 +197,7 @@ def _expect_warnings( else: real_warn(msg, *arg, **kw) - with mock.patch("warnings.warn", our_warn), mock.patch( - "sqlalchemy.util.SQLALCHEMY_WARN_20", True - ), mock.patch("sqlalchemy.util.deprecations.SQLALCHEMY_WARN_20", True): + with mock.patch("warnings.warn", our_warn): try: yield finally: diff --git a/lib/sqlalchemy/testing/profiling.py b/lib/sqlalchemy/testing/profiling.py index 2761d4987..6ccfe4ea7 100644 --- a/lib/sqlalchemy/testing/profiling.py +++ b/lib/sqlalchemy/testing/profiling.py @@ -238,21 +238,18 @@ def function_call_count(variance=0.05, times=1, warmup=0): # likely due to the introduction of __signature__. from sqlalchemy.util import decorator - from sqlalchemy.util import deprecations - from sqlalchemy.testing import mock @decorator def wrap(fn, *args, **kw): - with mock.patch.object(deprecations, "SQLALCHEMY_WARN_20", False): - for warm in range(warmup): - fn(*args, **kw) + for warm in range(warmup): + fn(*args, **kw) - timerange = range(times) - with count_functions(variance=variance): - for time in timerange: - rv = fn(*args, **kw) - return rv + timerange = range(times) + with count_functions(variance=variance): + for time in timerange: + rv = fn(*args, **kw) + return rv return wrap diff --git a/lib/sqlalchemy/testing/warnings.py b/lib/sqlalchemy/testing/warnings.py index c8e481a90..0c550731c 100644 --- a/lib/sqlalchemy/testing/warnings.py +++ b/lib/sqlalchemy/testing/warnings.py @@ -46,13 +46,6 @@ def setup_filters(): message="The loop argument is deprecated", ) - # ignore things that are deprecated *as of* 2.0 :) - warnings.filterwarnings( - "ignore", - category=sa_exc.SADeprecationWarning, - message=r".*\(deprecated since: 2.0\)$", - ) - try: import pytest except ImportError: diff --git a/lib/sqlalchemy/util/__init__.py b/lib/sqlalchemy/util/__init__.py index b452a1fda..eb9ddb313 100644 --- a/lib/sqlalchemy/util/__init__.py +++ b/lib/sqlalchemy/util/__init__.py @@ -70,16 +70,13 @@ from .concurrency import await_fallback from .concurrency import await_only from .concurrency import greenlet_spawn from .concurrency import is_exit_exception +from .deprecations import became_legacy_20 from .deprecations import deprecated -from .deprecations import deprecated_20 -from .deprecations import deprecated_20_cls from .deprecations import deprecated_cls from .deprecations import deprecated_params from .deprecations import inject_docstring_text from .deprecations import moved_20 -from .deprecations import SQLALCHEMY_WARN_20 from .deprecations import warn_deprecated -from .deprecations import warn_deprecated_20 from .langhelpers import add_parameter_text from .langhelpers import as_interface from .langhelpers import asbool diff --git a/lib/sqlalchemy/util/deprecations.py b/lib/sqlalchemy/util/deprecations.py index 4d3e04fde..6a0fdecb5 100644 --- a/lib/sqlalchemy/util/deprecations.py +++ b/lib/sqlalchemy/util/deprecations.py @@ -8,7 +8,6 @@ """Helpers related to deprecation of functions, methods, classes, other functionality.""" -import os import re from . import compat @@ -20,19 +19,7 @@ from .langhelpers import inject_param_text from .. import exc -SQLALCHEMY_WARN_20 = False - -if os.getenv("SQLALCHEMY_WARN_20", "false").lower() in ("true", "yes", "1"): - SQLALCHEMY_WARN_20 = True - - def _warn_with_version(msg, version, type_, stacklevel, code=None): - if ( - issubclass(type_, exc.Base20DeprecationWarning) - and not SQLALCHEMY_WARN_20 - ): - return - warn = type_(msg, code=code) warn.deprecated_since = version @@ -57,17 +44,6 @@ def warn_deprecated_limited(msg, args, version, stacklevel=3, code=None): ) -def warn_deprecated_20(msg, stacklevel=3, code=None): - - _warn_with_version( - msg, - exc.RemovedIn20Warning.deprecated_since, - exc.RemovedIn20Warning, - stacklevel, - code=code, - ) - - def deprecated_cls(version, message, constructor="__init__"): header = ".. deprecated:: %s %s" % (version, (message or "")) @@ -84,41 +60,6 @@ def deprecated_cls(version, message, constructor="__init__"): return decorate -def deprecated_20_cls( - clsname, alternative=None, constructor="__init__", becomes_legacy=False -): - message = ( - ".. deprecated:: 1.4 The %s class is considered legacy as of the " - "1.x series of SQLAlchemy and %s in 2.0." - % ( - clsname, - "will be removed" - if not becomes_legacy - else "becomes a legacy construct", - ) - ) - - if alternative: - message += " " + alternative - - if becomes_legacy: - warning_cls = exc.LegacyAPIWarning - else: - warning_cls = exc.RemovedIn20Warning - - def decorate(cls): - return _decorate_cls_with_warning( - cls, - constructor, - warning_cls, - message, - warning_cls.deprecated_since, - message, - ) - - return decorate - - def deprecated( version, message=None, @@ -142,14 +83,6 @@ def deprecated( """ - # nothing is deprecated "since" 2.0 at this time. All "removed in 2.0" - # should emit the RemovedIn20Warning, but messaging should be expressed - # in terms of "deprecated since 1.4". - - if version == "2.0": - if warning is None: - warning = exc.RemovedIn20Warning - version = "1.4" if add_deprecation_to_docstring: header = ".. deprecated:: %s %s" % ( version, @@ -164,8 +97,7 @@ def deprecated( if warning is None: warning = exc.SADeprecationWarning - if warning is not exc.RemovedIn20Warning: - message += " (deprecated since: %s)" % version + message += " (deprecated since: %s)" % version def decorate(fn): return _decorate_with_warning( @@ -186,7 +118,7 @@ def moved_20(message, **kw): ) -def deprecated_20(api_name, alternative=None, becomes_legacy=False, **kw): +def became_legacy_20(api_name, alternative=None, **kw): type_reg = re.match("^:(attr|func|meth):", api_name) if type_reg: type_ = {"attr": "attribute", "func": "function", "meth": "method"}[ @@ -200,9 +132,7 @@ def deprecated_20(api_name, alternative=None, becomes_legacy=False, **kw): % ( api_name, type_, - "will be removed" - if not becomes_legacy - else "becomes a legacy construct", + "becomes a legacy construct", ) ) @@ -219,10 +149,7 @@ def deprecated_20(api_name, alternative=None, becomes_legacy=False, **kw): if alternative: message += " " + alternative - if becomes_legacy: - warning_cls = exc.LegacyAPIWarning - else: - warning_cls = exc.RemovedIn20Warning + warning_cls = exc.LegacyAPIWarning return deprecated("2.0", message=message, warning=warning_cls, **kw) @@ -250,11 +177,7 @@ def deprecated_params(**specs): for param, (version, message) in specs.items(): versions[param] = version messages[param] = _sanitize_restructured_text(message) - version_warnings[param] = ( - exc.RemovedIn20Warning - if version == "2.0" - else exc.SADeprecationWarning - ) + version_warnings[param] = exc.SADeprecationWarning def decorate(fn): spec = compat.inspect_getfullargspec(fn) |
