]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
setup JoinedDispatch to support pickling
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 7 May 2024 22:03:51 +0000 (18:03 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 8 May 2024 15:12:08 +0000 (11:12 -0400)
Fixed issue where a :class:`.MetaData` collection would not be
serializable, if an :class:`.Enum` or :class:`.Boolean` datatype were
present which had been adapted. This specific scenario in turn could occur
when using the :class:`.Enum` or :class:`.Boolean` within ORM Annotated
Declarative form where type objects frequently get copied.

Fixes: #11365
Change-Id: Iaaa64baad79c41075d37cf53dade744d79e600a3

doc/build/changelog/unreleased_20/11365.rst [new file with mode: 0644]
lib/sqlalchemy/event/base.py
test/sql/test_types.py

diff --git a/doc/build/changelog/unreleased_20/11365.rst b/doc/build/changelog/unreleased_20/11365.rst
new file mode 100644 (file)
index 0000000..d2b353e
--- /dev/null
@@ -0,0 +1,9 @@
+.. change::
+    :tags: bug, orm
+    :tickets: 11365
+
+    Fixed issue where a :class:`.MetaData` collection would not be
+    serializable, if an :class:`.Enum` or :class:`.Boolean` datatype were
+    present which had been adapted. This specific scenario in turn could occur
+    when using the :class:`.Enum` or :class:`.Boolean` within ORM Annotated
+    Declarative form where type objects frequently get copied.
index 1f52e2eb799337cf7f0920296aa92e539bc5505a..434886316f007d53f342106e191ee9bcbe2b7ada 100644 (file)
@@ -198,6 +198,10 @@ class _Dispatch(_DispatchCommon[_ET]):
                 {"__slots__": self._event_names},
             )
             self.__class__._joined_dispatch_cls = cls
+
+            # establish pickle capability by adding it to this module
+            globals()[cls.__name__] = cls
+
         return self._joined_dispatch_cls(self, other)
 
     def __reduce__(self) -> Union[str, Tuple[Any, ...]]:
@@ -398,6 +402,9 @@ class _JoinedDispatcher(_DispatchCommon[_ET]):
         self.parent = parent
         self._instance_cls = self.local._instance_cls
 
+    def __reduce__(self) -> Any:
+        return (self.__class__, (self.local, self.parent))
+
     def __getattr__(self, name: str) -> _JoinedListener[_ET]:
         # Assign _JoinedListeners as attributes on demand
         # to reduce startup time for new dispatch objects.
index 0127004438cdfbd1aedcaf6cd3ccd3827046b642..5214ebac53c71a332572b782e6528910f085d2fa 100644 (file)
@@ -507,15 +507,22 @@ class PickleTypesTest(fixtures.TestBase):
         ("Big", BigInteger()),
         ("Num", Numeric()),
         ("Flo", Float()),
+        ("Enu", Enum("one", "two", "three")),
         ("Dat", DateTime()),
         ("Dat", Date()),
         ("Tim", Time()),
         ("Lar", LargeBinary()),
         ("Pic", PickleType()),
         ("Int", Interval()),
+        argnames="name,type_",
         id_="ar",
     )
-    def test_pickle_types(self, name, type_):
+    @testing.variation("use_adapt", [True, False])
+    def test_pickle_types(self, name, type_, use_adapt):
+
+        if use_adapt:
+            type_ = type_.copy()
+
         column_type = Column(name, type_)
         meta = MetaData()
         Table("foo", meta, column_type)