From: Federico Caselli Date: Sun, 16 Mar 2025 21:31:09 +0000 (+0100) Subject: remove deprecated features X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1ebd8c525b7533ac1c082341ac0df760bf26dd2c;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git remove deprecated features Remove feature deprecates in 1.3 and before Fixes: #12441 Change-Id: Ice3d35ec02988ce94cdeb9db41cb684db2fb5d8d --- diff --git a/doc/build/changelog/unreleased_21/12441.rst b/doc/build/changelog/unreleased_21/12441.rst new file mode 100644 index 0000000000..dd73789756 --- /dev/null +++ b/doc/build/changelog/unreleased_21/12441.rst @@ -0,0 +1,17 @@ +.. change:: + :tags: misc, changed + :tickets: 12441 + + Removed multiple api that were deprecated in the 1.3 series and earlier. + The list of removed features includes: + + * The ``force`` parameter of ``IdentifierPreparer.quote`` and + ``IdentifierPreparer.quote_schema``; + * The ``threaded`` parameter of the cx-Oracle dialect; + * The ``_json_serializer`` and ``_json_deserializer`` parameters of the + SQLite dialect; + * The ``collection.converter`` decorator; + * The ``Mapper.mapped_table`` property; + * The ``Session.close_all`` method; + * Support for multiple arguments in :func:`_orm.defer` and + :func:`_orm.undefer`. diff --git a/doc/build/faq/ormconfiguration.rst b/doc/build/faq/ormconfiguration.rst index bfcf117ae0..9388789cc6 100644 --- a/doc/build/faq/ormconfiguration.rst +++ b/doc/build/faq/ormconfiguration.rst @@ -110,11 +110,11 @@ such as: * :attr:`_orm.Mapper.columns` - A namespace of :class:`_schema.Column` objects and other named SQL expressions associated with the mapping. -* :attr:`_orm.Mapper.mapped_table` - The :class:`_schema.Table` or other selectable to which +* :attr:`_orm.Mapper.persist_selectable` - The :class:`_schema.Table` or other selectable to which this mapper is mapped. * :attr:`_orm.Mapper.local_table` - The :class:`_schema.Table` that is "local" to this mapper; - this differs from :attr:`_orm.Mapper.mapped_table` in the case of a mapper mapped + this differs from :attr:`_orm.Mapper.persist_selectable` in the case of a mapper mapped using inheritance to a composed selectable. .. _faq_combining_columns: diff --git a/examples/nested_sets/nested_sets.py b/examples/nested_sets/nested_sets.py index 1492f6abd8..eed7b497a9 100644 --- a/examples/nested_sets/nested_sets.py +++ b/examples/nested_sets/nested_sets.py @@ -44,7 +44,7 @@ def before_insert(mapper, connection, instance): instance.left = 1 instance.right = 2 else: - personnel = mapper.mapped_table + personnel = mapper.persist_selectable right_most_sibling = connection.scalar( select(personnel.c.rgt).where( personnel.c.emp == instance.parent.emp diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py index a7e1a16491..24425fc817 100644 --- a/lib/sqlalchemy/dialects/mssql/base.py +++ b/lib/sqlalchemy/dialects/mssql/base.py @@ -100,14 +100,6 @@ is set to ``False`` on any integer primary key column:: ``dialect_options`` key in :meth:`_reflection.Inspector.get_columns`. Use the information in the ``identity`` key instead. -.. deprecated:: 1.3 - - The use of :class:`.Sequence` to specify IDENTITY characteristics is - deprecated and will be removed in a future release. Please use - the :class:`_schema.Identity` object parameters - :paramref:`_schema.Identity.start` and - :paramref:`_schema.Identity.increment`. - .. versionchanged:: 1.4 Removed the ability to use a :class:`.Sequence` object to modify IDENTITY characteristics. :class:`.Sequence` objects now only manipulate true T-SQL SEQUENCE types. @@ -2832,23 +2824,9 @@ class MSIdentifierPreparer(compiler.IdentifierPreparer): def _unescape_identifier(self, value): return value.replace("]]", "]") - def quote_schema(self, schema, force=None): + def quote_schema(self, schema): """Prepare a quoted table and schema name.""" - # need to re-implement the deprecation warning entirely - if force is not None: - # not using the util.deprecated_params() decorator in this - # case because of the additional function call overhead on this - # very performance-critical spot. - util.warn_deprecated( - "The IdentifierPreparer.quote_schema.force parameter is " - "deprecated and will be removed in a future release. This " - "flag has no effect on the behavior of the " - "IdentifierPreparer.quote method; please refer to " - "quoted_name().", - version="1.3", - ) - dbname, owner = _schema_elements(schema) if dbname: result = "%s.%s" % (self.quote(dbname), self.quote(owner)) diff --git a/lib/sqlalchemy/dialects/oracle/cx_oracle.py b/lib/sqlalchemy/dialects/oracle/cx_oracle.py index b5328f3427..7ab48de4ff 100644 --- a/lib/sqlalchemy/dialects/oracle/cx_oracle.py +++ b/lib/sqlalchemy/dialects/oracle/cx_oracle.py @@ -1067,28 +1067,14 @@ class OracleDialect_cx_oracle(OracleDialect): execute_sequence_format = list - _cx_oracle_threaded = None - _cursor_var_unicode_kwargs = util.immutabledict() - @util.deprecated_params( - threaded=( - "1.3", - "The 'threaded' parameter to the cx_oracle/oracledb dialect " - "is deprecated as a dialect-level argument, and will be removed " - "in a future release. As of version 1.3, it defaults to False " - "rather than True. The 'threaded' option can be passed to " - "cx_Oracle directly in the URL query string passed to " - ":func:`_sa.create_engine`.", - ) - ) def __init__( self, auto_convert_lobs=True, coerce_to_decimal=True, arraysize=None, encoding_errors=None, - threaded=None, **kwargs, ): OracleDialect.__init__(self, **kwargs) @@ -1098,8 +1084,6 @@ class OracleDialect_cx_oracle(OracleDialect): self._cursor_var_unicode_kwargs = { "encodingErrors": encoding_errors } - if threaded is not None: - self._cx_oracle_threaded = threaded self.auto_convert_lobs = auto_convert_lobs self.coerce_to_decimal = coerce_to_decimal if self._use_nchar_for_unicode: @@ -1373,17 +1357,6 @@ class OracleDialect_cx_oracle(OracleDialect): def create_connect_args(self, url): opts = dict(url.query) - for opt in ("use_ansi", "auto_convert_lobs"): - if opt in opts: - util.warn_deprecated( - f"{self.driver} dialect option {opt!r} should only be " - "passed to create_engine directly, not within the URL " - "string", - version="1.3", - ) - util.coerce_kw_type(opts, opt, bool) - setattr(self, opt, opts.pop(opt)) - database = url.database service_name = opts.pop("service_name", None) if database or service_name: @@ -1416,9 +1389,6 @@ class OracleDialect_cx_oracle(OracleDialect): if url.username is not None: opts["user"] = url.username - if self._cx_oracle_threaded is not None: - opts.setdefault("threaded", self._cx_oracle_threaded) - def convert_cx_oracle_constant(value): if isinstance(value, str): try: diff --git a/lib/sqlalchemy/dialects/sqlite/base.py b/lib/sqlalchemy/dialects/sqlite/base.py index ffd7921eb7..e7302b641a 100644 --- a/lib/sqlalchemy/dialects/sqlite/base.py +++ b/lib/sqlalchemy/dialects/sqlite/base.py @@ -2010,35 +2010,15 @@ class SQLiteDialect(default.DefaultDialect): _broken_fk_pragma_quotes = False _broken_dotted_colnames = False - @util.deprecated_params( - _json_serializer=( - "1.3.7", - "The _json_serializer argument to the SQLite dialect has " - "been renamed to the correct name of json_serializer. The old " - "argument name will be removed in a future release.", - ), - _json_deserializer=( - "1.3.7", - "The _json_deserializer argument to the SQLite dialect has " - "been renamed to the correct name of json_deserializer. The old " - "argument name will be removed in a future release.", - ), - ) def __init__( self, native_datetime=False, json_serializer=None, json_deserializer=None, - _json_serializer=None, - _json_deserializer=None, **kwargs, ): default.DefaultDialect.__init__(self, **kwargs) - if _json_serializer: - json_serializer = _json_serializer - if _json_deserializer: - json_deserializer = _json_deserializer self._json_serializer = json_serializer self._json_deserializer = json_deserializer diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py index 651ea5cce2..fc95401ca2 100644 --- a/lib/sqlalchemy/orm/attributes.py +++ b/lib/sqlalchemy/orm/attributes.py @@ -1925,33 +1925,32 @@ class _CollectionAttributeImpl(_HasCollectionAdapter, _AttributeImpl): # not trigger a lazy load of the old collection. new_collection, user_data = self._initialize_collection(state) if _adapt: - if new_collection._converter is not None: - iterable = new_collection._converter(iterable) - else: - setting_type = util.duck_type_collection(iterable) - receiving_type = self._duck_typed_as - - if setting_type is not receiving_type: - given = ( - iterable is None - and "None" - or iterable.__class__.__name__ - ) - wanted = self._duck_typed_as.__name__ - raise TypeError( - "Incompatible collection type: %s is not %s-like" - % (given, wanted) - ) + setting_type = util.duck_type_collection(iterable) + receiving_type = self._duck_typed_as - # If the object is an adapted collection, return the (iterable) - # adapter. - if hasattr(iterable, "_sa_iterator"): - iterable = iterable._sa_iterator() - elif setting_type is dict: - new_keys = list(iterable) - iterable = iterable.values() - else: - iterable = iter(iterable) + if setting_type is not receiving_type: + given = ( + "None" if iterable is None else iterable.__class__.__name__ + ) + wanted = ( + "None" + if self._duck_typed_as is None + else self._duck_typed_as.__name__ + ) + raise TypeError( + "Incompatible collection type: %s is not %s-like" + % (given, wanted) + ) + + # If the object is an adapted collection, return the (iterable) + # adapter. + if hasattr(iterable, "_sa_iterator"): + iterable = iterable._sa_iterator() + elif setting_type is dict: + new_keys = list(iterable) + iterable = iterable.values() + else: + iterable = iter(iterable) elif util.duck_type_collection(iterable) is dict: new_keys = list(value) diff --git a/lib/sqlalchemy/orm/collections.py b/lib/sqlalchemy/orm/collections.py index c765f59d3c..1b6cfbc087 100644 --- a/lib/sqlalchemy/orm/collections.py +++ b/lib/sqlalchemy/orm/collections.py @@ -179,7 +179,6 @@ class _AdaptedCollectionProtocol(Protocol): _sa_appender: Callable[..., Any] _sa_remover: Callable[..., Any] _sa_iterator: Callable[..., Iterable[Any]] - _sa_converter: _CollectionConverterProtocol class collection: @@ -187,7 +186,7 @@ class collection: The decorators fall into two groups: annotations and interception recipes. - The annotating decorators (appender, remover, iterator, converter, + The annotating decorators (appender, remover, iterator, internally_instrumented) indicate the method's purpose and take no arguments. They are not written with parens:: @@ -318,46 +317,6 @@ class collection: fn._sa_instrumented = True return fn - @staticmethod - @util.deprecated( - "1.3", - "The :meth:`.collection.converter` handler is deprecated and will " - "be removed in a future release. Please refer to the " - ":class:`.AttributeEvents.bulk_replace` listener interface in " - "conjunction with the :func:`.event.listen` function.", - ) - def converter(fn): - """Tag the method as the collection converter. - - This optional method will be called when a collection is being - replaced entirely, as in:: - - myobj.acollection = [newvalue1, newvalue2] - - The converter method will receive the object being assigned and should - return an iterable of values suitable for use by the ``appender`` - method. A converter must not assign values or mutate the collection, - its sole job is to adapt the value the user provides into an iterable - of values for the ORM's use. - - The default converter implementation will use duck-typing to do the - conversion. A dict-like collection will be convert into an iterable - of dictionary values, and other types will simply be iterated:: - - @collection.converter - def convert(self, other): ... - - If the duck-typing of the object does not match the type of this - collection, a TypeError is raised. - - Supply an implementation of this method if you want to expand the - range of possible types that can be assigned in bulk or perform - validation on the values about to be assigned. - - """ - fn._sa_instrument_role = "converter" - return fn - @staticmethod def adds(arg): """Mark the method as adding an entity to the collection. @@ -478,7 +437,6 @@ class CollectionAdapter: "_key", "_data", "owner_state", - "_converter", "invalidated", "empty", ) @@ -490,7 +448,6 @@ class CollectionAdapter: _data: Callable[..., _AdaptedCollectionProtocol] owner_state: InstanceState[Any] - _converter: _CollectionConverterProtocol invalidated: bool empty: bool @@ -512,7 +469,6 @@ class CollectionAdapter: self.owner_state = owner_state data._sa_adapter = self - self._converter = data._sa_converter self.invalidated = False self.empty = False @@ -770,7 +726,6 @@ class CollectionAdapter: # see note in constructor regarding this type: ignore self._data = weakref.ref(d["data"]) # type: ignore - self._converter = d["data"]._sa_converter d["data"]._sa_adapter = self self.invalidated = d["invalidated"] self.attr = getattr(d["owner_cls"], self._key).impl @@ -905,12 +860,7 @@ def _locate_roles_and_methods(cls): # note role declarations if hasattr(method, "_sa_instrument_role"): role = method._sa_instrument_role - assert role in ( - "appender", - "remover", - "iterator", - "converter", - ) + assert role in ("appender", "remover", "iterator") roles.setdefault(role, name) # transfer instrumentation requests from decorated function @@ -1009,8 +959,6 @@ def _set_collection_attributes(cls, roles, methods): cls._sa_adapter = None - if not hasattr(cls, "_sa_converter"): - cls._sa_converter = None cls._sa_instrumented = id(cls) diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index f736d65f89..28aa1bf327 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -1152,11 +1152,6 @@ class Mapper( c: ReadOnlyColumnCollection[str, Column[Any]] """A synonym for :attr:`_orm.Mapper.columns`.""" - @util.non_memoized_property - @util.deprecated("1.3", "Use .persist_selectable") - def mapped_table(self): - return self.persist_selectable - @util.memoized_property def _path_registry(self) -> _CachingEntityRegistry: return PathRegistry.per_mapper(self) diff --git a/lib/sqlalchemy/orm/scoping.py b/lib/sqlalchemy/orm/scoping.py index a8cf03c517..ba9899a5f9 100644 --- a/lib/sqlalchemy/orm/scoping.py +++ b/lib/sqlalchemy/orm/scoping.py @@ -103,7 +103,7 @@ __all__ = ["scoped_session"] Session, ":class:`_orm.Session`", ":class:`_orm.scoping.scoped_session`", - classmethods=["close_all", "object_session", "identity_key"], + classmethods=["object_session", "identity_key"], methods=[ "__contains__", "__iter__", @@ -2160,21 +2160,6 @@ class scoped_session(Generic[_S]): return self._proxied.info - @classmethod - def close_all(cls) -> None: - r"""Close *all* sessions in memory. - - .. container:: class_bases - - Proxied for the :class:`_orm.Session` class on - behalf of the :class:`_orm.scoping.scoped_session` class. - - .. deprecated:: 1.3 The :meth:`.Session.close_all` method is deprecated and will be removed in a future release. Please refer to :func:`.session.close_all_sessions`. - - """ # noqa: E501 - - return Session.close_all() - @classmethod def object_session(cls, instance: object) -> Optional[Session]: r"""Return the :class:`.Session` to which an object belongs. diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py index b0634c4ee9..2896ebe2f9 100644 --- a/lib/sqlalchemy/orm/session.py +++ b/lib/sqlalchemy/orm/session.py @@ -207,18 +207,6 @@ def _state_session(state: InstanceState[Any]) -> Optional[Session]: class _SessionClassMethods: """Class-level methods for :class:`.Session`, :class:`.sessionmaker`.""" - @classmethod - @util.deprecated( - "1.3", - "The :meth:`.Session.close_all` method is deprecated and will be " - "removed in a future release. Please refer to " - ":func:`.session.close_all_sessions`.", - ) - def close_all(cls) -> None: - """Close *all* sessions in memory.""" - - close_all_sessions() - @classmethod @util.preload_module("sqlalchemy.orm.util") def identity_key( diff --git a/lib/sqlalchemy/orm/strategy_options.py b/lib/sqlalchemy/orm/strategy_options.py index 04987b16fb..154f8430a9 100644 --- a/lib/sqlalchemy/orm/strategy_options.py +++ b/lib/sqlalchemy/orm/strategy_options.py @@ -2454,35 +2454,18 @@ def defaultload(*keys: _AttrType) -> _AbstractLoad: @loader_unbound_fn -def defer( - key: _AttrType, *addl_attrs: _AttrType, raiseload: bool = False -) -> _AbstractLoad: - if addl_attrs: - util.warn_deprecated( - "The *addl_attrs on orm.defer is deprecated. Please use " - "method chaining in conjunction with defaultload() to " - "indicate a path.", - version="1.3", - ) - +def defer(key: _AttrType, *, raiseload: bool = False) -> _AbstractLoad: if raiseload: kw = {"raiseload": raiseload} else: kw = {} - return _generate_from_keys(Load.defer, (key,) + addl_attrs, False, kw) + return _generate_from_keys(Load.defer, (key,), False, kw) @loader_unbound_fn -def undefer(key: _AttrType, *addl_attrs: _AttrType) -> _AbstractLoad: - if addl_attrs: - util.warn_deprecated( - "The *addl_attrs on orm.undefer is deprecated. Please use " - "method chaining in conjunction with defaultload() to " - "indicate a path.", - version="1.3", - ) - return _generate_from_keys(Load.undefer, (key,) + addl_attrs, False, {}) +def undefer(key: _AttrType) -> _AbstractLoad: + return _generate_from_keys(Load.undefer, (key,), False, {}) @loader_unbound_fn diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index 20073a3afa..768a906d6a 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -7618,7 +7618,7 @@ class IdentifierPreparer: not taking case convention into account.""" return not self.legal_characters.match(str(value)) - def quote_schema(self, schema: str, force: Any = None) -> str: + def quote_schema(self, schema: str) -> str: """Conditionally quote a schema name. @@ -7630,34 +7630,10 @@ class IdentifierPreparer: quoting behavior for schema names. :param schema: string schema name - :param force: unused - - .. deprecated:: 0.9 - - The :paramref:`.IdentifierPreparer.quote_schema.force` - parameter is deprecated and will be removed in a future - release. This flag has no effect on the behavior of the - :meth:`.IdentifierPreparer.quote` method; please refer to - :class:`.quoted_name`. - """ - if force is not None: - # not using the util.deprecated_params() decorator in this - # case because of the additional function call overhead on this - # very performance-critical spot. - util.warn_deprecated( - "The IdentifierPreparer.quote_schema.force parameter is " - "deprecated and will be removed in a future release. This " - "flag has no effect on the behavior of the " - "IdentifierPreparer.quote method; please refer to " - "quoted_name().", - # deprecated 0.9. warning from 1.3 - version="0.9", - ) - return self.quote(schema) - def quote(self, ident: str, force: Any = None) -> str: + def quote(self, ident: str) -> str: """Conditionally quote an identifier. The identifier is quoted if it is a reserved word, contains @@ -7668,31 +7644,7 @@ class IdentifierPreparer: quoting behavior for identifier names. :param ident: string identifier - :param force: unused - - .. deprecated:: 0.9 - - The :paramref:`.IdentifierPreparer.quote.force` - parameter is deprecated and will be removed in a future - release. This flag has no effect on the behavior of the - :meth:`.IdentifierPreparer.quote` method; please refer to - :class:`.quoted_name`. - """ - if force is not None: - # not using the util.deprecated_params() decorator in this - # case because of the additional function call overhead on this - # very performance-critical spot. - util.warn_deprecated( - "The IdentifierPreparer.quote.force parameter is " - "deprecated and will be removed in a future release. This " - "flag has no effect on the behavior of the " - "IdentifierPreparer.quote method; please refer to " - "quoted_name().", - # deprecated 0.9. warning from 1.3 - version="0.9", - ) - force = getattr(ident, "quote", None) if force is None: diff --git a/lib/sqlalchemy/util/deprecations.py b/lib/sqlalchemy/util/deprecations.py index 0c74079599..c64d3474ea 100644 --- a/lib/sqlalchemy/util/deprecations.py +++ b/lib/sqlalchemy/util/deprecations.py @@ -203,7 +203,7 @@ def deprecated_params(**specs: Tuple[str, str]) -> Callable[[_F], _F]: @deprecated_params( weak_identity_map=( - "0.7", + "2.0", "the :paramref:`.Session.weak_identity_map parameter " "is deprecated.", ) diff --git a/test/dialect/oracle/test_dialect.py b/test/dialect/oracle/test_dialect.py index 1f8a23f70d..05f7fa6497 100644 --- a/test/dialect/oracle/test_dialect.py +++ b/test/dialect/oracle/test_dialect.py @@ -995,19 +995,6 @@ class BaseConnectArgsTest: arg, kw = dialect.create_connect_args(url_obj) assert key not in kw - def _test_dialect_param_from_url(self, url_string, key, value): - url_obj = url.make_url(url_string) - dialect = self.dialect_cls(dbapi=self.dbapi) - with testing.expect_deprecated( - f"{self.name} dialect option %r should" % key - ): - arg, kw = dialect.create_connect_args(url_obj) - eq_(getattr(dialect, key), value) - - # test setting it on the dialect normally - dialect = self.dialect_cls(dbapi=self.dbapi, **{key: value}) - eq_(getattr(dialect, key), value) - def test_mode(self): self._test_db_opt( f"oracle+{self.name}://scott:tiger@host/?mode=sYsDBA", @@ -1060,30 +1047,6 @@ class BaseConnectArgsTest: True, ) - def test_threaded_deprecated_at_dialect_level(self): - with testing.expect_deprecated( - "The 'threaded' parameter to the cx_oracle/oracledb dialect" - ): - dialect = self.dialect_cls(threaded=False) - arg, kw = dialect.create_connect_args( - url.make_url(f"oracle+{self.name}://scott:tiger@dsn") - ) - eq_(kw["threaded"], False) - - def test_deprecated_use_ansi(self): - self._test_dialect_param_from_url( - f"oracle+{self.name}://scott:tiger@host/?use_ansi=False", - "use_ansi", - False, - ) - - def test_deprecated_auto_convert_lobs(self): - self._test_dialect_param_from_url( - f"oracle+{self.name}://scott:tiger@host/?auto_convert_lobs=False", - "auto_convert_lobs", - False, - ) - class CXOracleConnectArgsTest(BaseConnectArgsTest, fixtures.TestBase): __only_on__ = "oracle+cx_oracle" diff --git a/test/dialect/test_sqlite.py b/test/dialect/test_sqlite.py index c5b4f62e29..b68e3b979d 100644 --- a/test/dialect/test_sqlite.py +++ b/test/dialect/test_sqlite.py @@ -321,23 +321,17 @@ class JSONTest(fixtures.TestBase): connection.scalar(select(sqlite_json.c.foo["json"])), value["json"] ) - def test_deprecated_serializer_args(self, metadata): + def test_serializer_args(self, metadata): sqlite_json = Table("json_test", metadata, Column("foo", sqlite.JSON)) data_element = {"foo": "bar"} js = mock.Mock(side_effect=json.dumps) jd = mock.Mock(side_effect=json.loads) - with testing.expect_deprecated( - "The _json_deserializer argument to the SQLite " - "dialect has been renamed", - "The _json_serializer argument to the SQLite " - "dialect has been renamed", - ): - engine = engines.testing_engine( - options=dict(_json_serializer=js, _json_deserializer=jd) - ) - metadata.create_all(engine) + engine = engines.testing_engine( + options=dict(json_serializer=js, json_deserializer=jd) + ) + metadata.create_all(engine) with engine.begin() as conn: conn.execute(sqlite_json.insert(), {"foo": data_element}) diff --git a/test/ext/test_extendedattr.py b/test/ext/test_extendedattr.py index 6452c7e344..403d2dd41c 100644 --- a/test/ext/test_extendedattr.py +++ b/test/ext/test_extendedattr.py @@ -79,7 +79,6 @@ class MyListLike(list): # add @appender, @remover decorators as needed _sa_iterator = list.__iter__ _sa_linker = None - _sa_converter = None def _sa_appender(self, item, _sa_initiator=None): if _sa_initiator is not False: diff --git a/test/orm/test_collection.py b/test/orm/test_collection.py index 90c12fc772..9cb81baa56 100644 --- a/test/orm/test_collection.py +++ b/test/orm/test_collection.py @@ -2788,6 +2788,40 @@ class CustomCollectionsTest(fixtures.MappedTest): class InstrumentationTest(fixtures.ORMTest): + def test_name_setup(self): + + class Base: + @collection.iterator + def base_iterate(self, x): + return "base_iterate" + + @collection.appender + def base_append(self, x): + return "base_append" + + @collection.remover + def base_remove(self, x): + return "base_remove" + + from sqlalchemy.orm.collections import _instrument_class + + _instrument_class(Base) + + eq_(Base._sa_remover(Base(), 5), "base_remove") + eq_(Base._sa_appender(Base(), 5), "base_append") + eq_(Base._sa_iterator(Base(), 5), "base_iterate") + + class Sub(Base): + @collection.remover + def sub_remove(self, x): + return "sub_remove" + + _instrument_class(Sub) + + eq_(Sub._sa_appender(Sub(), 5), "base_append") + eq_(Sub._sa_remover(Sub(), 5), "sub_remove") + eq_(Sub._sa_iterator(Sub(), 5), "base_iterate") + def test_uncooperative_descriptor_in_sweep(self): class DoNotTouch: def __get__(self, obj, owner): diff --git a/test/orm/test_deprecations.py b/test/orm/test_deprecations.py index 211c8c3dc2..a52a5ddacd 100644 --- a/test/orm/test_deprecations.py +++ b/test/orm/test_deprecations.py @@ -23,7 +23,6 @@ from sqlalchemy.engine import result_tuple from sqlalchemy.orm import aliased from sqlalchemy.orm import attributes from sqlalchemy.orm import clear_mappers -from sqlalchemy.orm import collections from sqlalchemy.orm import column_property from sqlalchemy.orm import contains_alias from sqlalchemy.orm import contains_eager @@ -44,7 +43,6 @@ from sqlalchemy.orm import subqueryload from sqlalchemy.orm import synonym from sqlalchemy.orm import undefer from sqlalchemy.orm import with_polymorphic -from sqlalchemy.orm.collections import collection from sqlalchemy.orm.strategy_options import lazyload from sqlalchemy.orm.strategy_options import noload from sqlalchemy.testing import assert_raises_message @@ -72,7 +70,6 @@ from .test_default_strategies import DefaultStrategyOptionsTestFixtures from .test_deferred import InheritanceTest as _deferred_InheritanceTest from .test_dynamic import _DynamicFixture from .test_dynamic import _WriteOnlyFixture -from .test_options import PathTest as OptionsPathTest from .test_options import PathTest from .test_options import QueryTest as OptionsQueryTest from .test_query import QueryTest @@ -823,194 +820,6 @@ class DeprecatedMapperTest( m.add_property(key, new_prop) -class DeprecatedOptionAllTest(OptionsPathTest, _fixtures.FixtureTest): - run_inserts = "once" - run_deletes = None - - def _mapper_fixture_one(self): - users, User, addresses, Address, orders, Order = ( - self.tables.users, - self.classes.User, - self.tables.addresses, - self.classes.Address, - self.tables.orders, - self.classes.Order, - ) - keywords, items, item_keywords, Keyword, Item = ( - self.tables.keywords, - self.tables.items, - self.tables.item_keywords, - self.classes.Keyword, - self.classes.Item, - ) - self.mapper_registry.map_imperatively( - User, - users, - properties={ - "addresses": relationship(Address), - "orders": relationship(Order), - }, - ) - self.mapper_registry.map_imperatively(Address, addresses) - self.mapper_registry.map_imperatively( - Order, - orders, - properties={ - "items": relationship(Item, secondary=self.tables.order_items) - }, - ) - self.mapper_registry.map_imperatively( - Keyword, - keywords, - properties={ - "keywords": column_property(keywords.c.name + "some keyword") - }, - ) - self.mapper_registry.map_imperatively( - Item, - items, - properties=dict( - keywords=relationship(Keyword, secondary=item_keywords) - ), - ) - - def _assert_eager_with_entity_exception( - self, entity_list, options, message - ): - assert_raises_message( - sa.exc.ArgumentError, - message, - fixture_session() - .query(*entity_list) - .options(*options) - ._compile_context, - ) - - def test_defer_addtl_attrs(self): - users, User, Address, addresses = ( - self.tables.users, - self.classes.User, - self.classes.Address, - self.tables.addresses, - ) - - self.mapper_registry.map_imperatively(Address, addresses) - self.mapper_registry.map_imperatively( - User, - users, - properties={ - "addresses": relationship( - Address, lazy="selectin", order_by=addresses.c.id - ) - }, - ) - - sess = fixture_session() - - with testing.expect_deprecated(undefer_needs_chaining): - sess.query(User).options( - defer(User.addresses, Address.email_address) - ) - - with testing.expect_deprecated(undefer_needs_chaining): - sess.query(User).options( - undefer(User.addresses, Address.email_address) - ) - - -class InstrumentationTest(fixtures.ORMTest): - def test_dict_subclass4(self): - # tests #2654 - with testing.expect_deprecated( - r"The collection.converter\(\) handler is deprecated and will " - "be removed in a future release. Please refer to the " - "AttributeEvents" - ): - - class MyDict(collections.KeyFuncDict): - def __init__(self): - super().__init__(lambda value: "k%d" % value) - - @collection.converter - def _convert(self, dictlike): - for key, value in dictlike.items(): - yield value + 5 - - class Foo: - pass - - instrumentation.register_class(Foo) - attributes._register_attribute( - Foo, - "attr", - parententity=object(), - comparator=object(), - uselist=True, - typecallable=MyDict, - useobject=True, - ) - - f = Foo() - f.attr = {"k1": 1, "k2": 2} - - eq_(f.attr, {"k7": 7, "k6": 6}) - - def test_name_setup(self): - with testing.expect_deprecated( - r"The collection.converter\(\) handler is deprecated and will " - "be removed in a future release. Please refer to the " - "AttributeEvents" - ): - - class Base: - @collection.iterator - def base_iterate(self, x): - return "base_iterate" - - @collection.appender - def base_append(self, x): - return "base_append" - - @collection.converter - def base_convert(self, x): - return "base_convert" - - @collection.remover - def base_remove(self, x): - return "base_remove" - - from sqlalchemy.orm.collections import _instrument_class - - _instrument_class(Base) - - eq_(Base._sa_remover(Base(), 5), "base_remove") - eq_(Base._sa_appender(Base(), 5), "base_append") - eq_(Base._sa_iterator(Base(), 5), "base_iterate") - eq_(Base._sa_converter(Base(), 5), "base_convert") - - with testing.expect_deprecated( - r"The collection.converter\(\) handler is deprecated and will " - "be removed in a future release. Please refer to the " - "AttributeEvents" - ): - - class Sub(Base): - @collection.converter - def base_convert(self, x): - return "sub_convert" - - @collection.remover - def sub_remove(self, x): - return "sub_remove" - - _instrument_class(Sub) - - eq_(Sub._sa_appender(Sub(), 5), "base_append") - eq_(Sub._sa_remover(Sub(), 5), "sub_remove") - eq_(Sub._sa_iterator(Sub(), 5), "base_iterate") - eq_(Sub._sa_converter(Sub(), 5), "sub_convert") - - class ViewonlyFlagWarningTest(fixtures.MappedTest): """test for #4993. @@ -1777,61 +1586,6 @@ class RequirementsTest(fixtures.MappedTest): ) -class DeferredOptionsTest(AssertsCompiledSQL, _fixtures.FixtureTest): - __dialect__ = "default" - - def test_deep_options(self): - users, items, order_items, Order, Item, User, orders = ( - self.tables.users, - self.tables.items, - self.tables.order_items, - self.classes.Order, - self.classes.Item, - self.classes.User, - self.tables.orders, - ) - - self.mapper_registry.map_imperatively( - Item, - items, - properties=dict(description=deferred(items.c.description)), - ) - self.mapper_registry.map_imperatively( - Order, - orders, - properties=dict(items=relationship(Item, secondary=order_items)), - ) - self.mapper_registry.map_imperatively( - User, - users, - properties=dict(orders=relationship(Order, order_by=orders.c.id)), - ) - - sess = fixture_session() - q = sess.query(User).order_by(User.id) - result = q.all() - item = result[0].orders[1].items[1] - - def go(): - eq_(item.description, "item 4") - - self.sql_count_(1, go) - eq_(item.description, "item 4") - - sess.expunge_all() - with assertions.expect_deprecated(undefer_needs_chaining): - result = q.options( - undefer(User.orders, Order.items, Item.description) - ).all() - item = result[0].orders[1].items[1] - - def go(): - eq_(item.description, "item 4") - - self.sql_count_(0, go) - eq_(item.description, "item 4") - - class SubOptionsTest(PathTest, OptionsQueryTest): run_create_tables = False run_inserts = None diff --git a/test/orm/test_session.py b/test/orm/test_session.py index 83a935435f..7f61b6ce7b 100644 --- a/test/orm/test_session.py +++ b/test/orm/test_session.py @@ -465,11 +465,7 @@ class SessionUtilTest(_fixtures.FixtureTest): assert u1 in s1 assert u2 in s2 - with assertions.expect_deprecated( - r"The Session.close_all\(\) method is deprecated and will " - "be removed in a future release. " - ): - Session.close_all() + close_all_sessions() assert u1 not in s1 assert u2 not in s2 diff --git a/test/sql/test_deprecations.py b/test/sql/test_deprecations.py index 4cd5c6402a..7f95e7ab0b 100644 --- a/test/sql/test_deprecations.py +++ b/test/sql/test_deprecations.py @@ -45,30 +45,6 @@ class ToMetaDataTest(fixtures.TestBase): class DeprecationWarningsTest(fixtures.TestBase, AssertsCompiledSQL): __backend__ = True - def test_ident_preparer_force(self): - preparer = testing.db.dialect.identifier_preparer - preparer.quote("hi") - with testing.expect_deprecated( - "The IdentifierPreparer.quote.force parameter is deprecated" - ): - preparer.quote("hi", True) - - with testing.expect_deprecated( - "The IdentifierPreparer.quote.force parameter is deprecated" - ): - preparer.quote("hi", False) - - preparer.quote_schema("hi") - with testing.expect_deprecated( - "The IdentifierPreparer.quote_schema.force parameter is deprecated" - ): - preparer.quote_schema("hi", True) - - with testing.expect_deprecated( - "The IdentifierPreparer.quote_schema.force parameter is deprecated" - ): - preparer.quote_schema("hi", True) - def test_empty_and_or(self): with testing.expect_deprecated( r"Invoking and_\(\) without arguments is deprecated, and " diff --git a/test/typing/plain_files/orm/scoped_session.py b/test/typing/plain_files/orm/scoped_session.py index 9809901902..f937361ec3 100644 --- a/test/typing/plain_files/orm/scoped_session.py +++ b/test/typing/plain_files/orm/scoped_session.py @@ -18,7 +18,6 @@ class X(Base): scoped_session.object_session(object()) scoped_session.identity_key() -scoped_session.close_all() ss = scoped_session(sessionmaker()) value: bool = "foo" in ss list(ss)