Skip to content

Commit

Permalink
setup JoinedDispatch to support pickling
Browse files Browse the repository at this point in the history
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
(cherry picked from commit 93cfb49)
  • Loading branch information
zzzeek committed May 8, 2024
1 parent 3848aa9 commit 039c684
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 1 deletion.
9 changes: 9 additions & 0 deletions doc/build/changelog/unreleased_20/11365.rst
Original file line number Diff line number Diff line change
@@ -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.
7 changes: 7 additions & 0 deletions lib/sqlalchemy/event/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,10 @@ def _join(self, other: _DispatchCommon[_ET]) -> _JoinedDispatcher[_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, ...]]:
Expand Down Expand Up @@ -398,6 +402,9 @@ def __init__(
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.
Expand Down
9 changes: 8 additions & 1 deletion test/sql/test_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 039c684

Please sign in to comment.