From: Mike Bayer Date: Tue, 10 Jun 2025 18:51:57 +0000 (-0400) Subject: remove util.portable_instancemethod X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8f6a33dc5078249bf92e13c8032e50175cb53801;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git remove util.portable_instancemethod python seems to be able to pickle instance methods since version 3.4. Doing a bisect shows it's https://github.com/python/cpython/commit/c9dc4a2a8a6dcfe1674685bea4a4af935c0e37ca where pickle protocol 4 was added, however we can see that protocols 0 through 4 also support pickling of methods. None of this documented. Change-Id: I9e73a35e9ab2ffd2050daf819265fc6b4ddb9019 --- diff --git a/lib/sqlalchemy/sql/ddl.py b/lib/sqlalchemy/sql/ddl.py index d6bd57d1b7..8bd37454e1 100644 --- a/lib/sqlalchemy/sql/ddl.py +++ b/lib/sqlalchemy/sql/ddl.py @@ -780,9 +780,7 @@ class AddConstraint(_CreateBase["Constraint"]): super().__init__(element) if isolate_from_table: - element._create_rule = util.portable_instancemethod( - self._create_rule_disable - ) + element._create_rule = self._create_rule_disable class DropConstraint(_DropBase["Constraint"]): @@ -821,9 +819,7 @@ class DropConstraint(_DropBase["Constraint"]): super().__init__(element, if_exists=if_exists, **kw) if isolate_from_table: - element._create_rule = util.portable_instancemethod( - self._create_rule_disable - ) + element._create_rule = self._create_rule_disable class SetTableComment(_CreateDropBase["Table"]): diff --git a/lib/sqlalchemy/sql/sqltypes.py b/lib/sqlalchemy/sql/sqltypes.py index 1c32450175..02f7c02dea 100644 --- a/lib/sqlalchemy/sql/sqltypes.py +++ b/lib/sqlalchemy/sql/sqltypes.py @@ -13,6 +13,7 @@ import collections.abc as collections_abc import datetime as dt import decimal import enum +import functools import json import pickle from typing import Any @@ -1077,19 +1078,19 @@ class SchemaType(SchemaEventTarget, TypeEngineMixin): if inherit_schema is not NO_ARG else (schema is None and metadata is None) ) - # breakpoint() + self._create_events = _create_events if _create_events and self.metadata: event.listen( self.metadata, "before_create", - util.portable_instancemethod(self._on_metadata_create), + self._on_metadata_create, ) event.listen( self.metadata, "after_drop", - util.portable_instancemethod(self._on_metadata_drop), + self._on_metadata_drop, ) if _adapted_from: @@ -1109,7 +1110,7 @@ class SchemaType(SchemaEventTarget, TypeEngineMixin): # on_table/metadata_create/drop in this method, which is used by # "native" types with a separate CREATE/DROP e.g. Postgresql.ENUM - parent._on_table_attach(util.portable_instancemethod(self._set_table)) + parent._on_table_attach(self._set_table) def _variant_mapping_for_set_table(self, column): if column.type._variant_mapping: @@ -1136,15 +1137,15 @@ class SchemaType(SchemaEventTarget, TypeEngineMixin): event.listen( table, "before_create", - util.portable_instancemethod( - self._on_table_create, {"variant_mapping": variant_mapping} + functools.partial( + self._on_table_create, variant_mapping=variant_mapping ), ) event.listen( table, "after_drop", - util.portable_instancemethod( - self._on_table_drop, {"variant_mapping": variant_mapping} + functools.partial( + self._on_table_drop, variant_mapping=variant_mapping ), ) if self.metadata is None: @@ -1154,17 +1155,17 @@ class SchemaType(SchemaEventTarget, TypeEngineMixin): event.listen( table.metadata, "before_create", - util.portable_instancemethod( + functools.partial( self._on_metadata_create, - {"variant_mapping": variant_mapping}, + variant_mapping=variant_mapping, ), ) event.listen( table.metadata, "after_drop", - util.portable_instancemethod( + functools.partial( self._on_metadata_drop, - {"variant_mapping": variant_mapping}, + variant_mapping=variant_mapping, ), ) @@ -1840,9 +1841,9 @@ class Enum(String, SchemaType, Emulated, TypeEngine[Union[str, enum.Enum]]): e = schema.CheckConstraint( type_coerce(column, String()).in_(self.enums), name=_NONE_NAME if self.name is None else self.name, - _create_rule=util.portable_instancemethod( + _create_rule=functools.partial( self._should_create_constraint, - {"variant_mapping": variant_mapping}, + variant_mapping=variant_mapping, ), _type_bound=True, ) @@ -2076,9 +2077,9 @@ class Boolean(SchemaType, Emulated, TypeEngine[bool]): e = schema.CheckConstraint( type_coerce(column, self).in_([0, 1]), name=_NONE_NAME if self.name is None else self.name, - _create_rule=util.portable_instancemethod( + _create_rule=functools.partial( self._should_create_constraint, - {"variant_mapping": variant_mapping}, + variant_mapping=variant_mapping, ), _type_bound=True, ) diff --git a/lib/sqlalchemy/util/__init__.py b/lib/sqlalchemy/util/__init__.py index 0b8170ebb7..a2110c4ec5 100644 --- a/lib/sqlalchemy/util/__init__.py +++ b/lib/sqlalchemy/util/__init__.py @@ -136,7 +136,6 @@ from .langhelpers import ( parse_user_argument_for_enum as parse_user_argument_for_enum, ) from .langhelpers import PluginLoader as PluginLoader -from .langhelpers import portable_instancemethod as portable_instancemethod from .langhelpers import quoted_token_parser as quoted_token_parser from .langhelpers import ro_memoized_property as ro_memoized_property from .langhelpers import ro_non_memoized_property as ro_non_memoized_property diff --git a/lib/sqlalchemy/util/langhelpers.py b/lib/sqlalchemy/util/langhelpers.py index 666b059eed..f82ab5cde8 100644 --- a/lib/sqlalchemy/util/langhelpers.py +++ b/lib/sqlalchemy/util/langhelpers.py @@ -901,36 +901,6 @@ def generic_repr( return "%s(%s)" % (obj.__class__.__name__, ", ".join(output)) -class portable_instancemethod: - """Turn an instancemethod into a (parent, name) pair - to produce a serializable callable. - - """ - - __slots__ = "target", "name", "kwargs", "__weakref__" - - def __getstate__(self): - return { - "target": self.target, - "name": self.name, - "kwargs": self.kwargs, - } - - def __setstate__(self, state): - self.target = state["target"] - self.name = state["name"] - self.kwargs = state.get("kwargs", ()) - - def __init__(self, meth, kwargs=()): - self.target = meth.__self__ - self.name = meth.__name__ - self.kwargs = kwargs - - def __call__(self, *arg, **kw): - kw.update(self.kwargs) - return getattr(self.target, self.name)(*arg, **kw) - - def class_hierarchy(cls): """Return an unordered sequence of all classes related to cls.