diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2020-12-01 16:03:35 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2020-12-01 16:04:06 -0500 |
commit | 14c08d18885e16611b884bd76ba2811375de1731 (patch) | |
tree | 66cd6a944896bcb65377c74552cfcc4b08da6a93 | |
parent | 1de02c9f3f5085e125a6f79230ee7b98f0e30ddb (diff) | |
download | sqlalchemy-14c08d18885e16611b884bd76ba2811375de1731.tar.gz |
Pass along other keyword args in _EventsHold.populate
Fixed bug involving the ``restore_load_context`` option of ORM events such
as :meth:`_orm.InstanceEvents.load` such that the flag would not be carried
along to subclasses which were mapped after the event handler were first
established.
Fixes: #5737
Change-Id: Ie65fbeac7ab223d24993cff0b34094d4928ff113
-rw-r--r-- | doc/build/changelog/unreleased_13/5737.rst | 11 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/events.py | 18 | ||||
-rw-r--r-- | test/orm/test_events.py | 26 |
3 files changed, 52 insertions, 3 deletions
diff --git a/doc/build/changelog/unreleased_13/5737.rst b/doc/build/changelog/unreleased_13/5737.rst new file mode 100644 index 000000000..7a1c3b527 --- /dev/null +++ b/doc/build/changelog/unreleased_13/5737.rst @@ -0,0 +1,11 @@ +.. change:: + :tags: bug, orm + :tickets: 5737 + :versions: 1.4.0b2 + + Fixed bug involving the ``restore_load_context`` option of ORM events such + as :meth:`_orm.InstanceEvents.load` such that the flag would not be carried + along to subclasses which were mapped after the event handler were first + established. + + diff --git a/lib/sqlalchemy/orm/events.py b/lib/sqlalchemy/orm/events.py index a0e100a81..9f9ebd461 100644 --- a/lib/sqlalchemy/orm/events.py +++ b/lib/sqlalchemy/orm/events.py @@ -550,7 +550,13 @@ class _EventsHold(event.RefCollection): collection = target.all_holds[target.class_] = {} event.registry._stored_in_collection(event_key, target) - collection[event_key._key] = (event_key, raw, propagate, retval) + collection[event_key._key] = ( + event_key, + raw, + propagate, + retval, + kw, + ) if propagate: stack = list(target.class_.__subclasses__()) @@ -577,7 +583,13 @@ class _EventsHold(event.RefCollection): for subclass in class_.__mro__: if subclass in cls.all_holds: collection = cls.all_holds[subclass] - for event_key, raw, propagate, retval in collection.values(): + for ( + event_key, + raw, + propagate, + retval, + kw, + ) in collection.values(): if propagate or subclass is class_: # since we can't be sure in what order different # classes in a hierarchy are triggered with @@ -585,7 +597,7 @@ class _EventsHold(event.RefCollection): # assignment, instead of using the generic propagate # flag. event_key.with_dispatch_target(subject).listen( - raw=raw, propagate=False, retval=retval + raw=raw, propagate=False, retval=retval, **kw ) diff --git a/test/orm/test_events.py b/test/orm/test_events.py index 285162241..f8600894f 100644 --- a/test/orm/test_events.py +++ b/test/orm/test_events.py @@ -900,6 +900,32 @@ class RestoreLoadContextTest(fixtures.DeclarativeMappedTest): s.query(A).all() s.close() + @testing.combinations( + ("load", lambda instance, context: instance.unloaded), + ( + "refresh", + lambda instance, context, attrs: instance.unloaded, + ), + ) + def test_flag_resolves_existing_for_subclass(self, event_name, fn): + Base = declarative_base() + + event.listen( + Base, event_name, fn, propagate=True, restore_load_context=True + ) + + class A(Base): + __tablename__ = "a" + id = Column(Integer, primary_key=True) + unloaded = deferred(Column(String(50))) + + s = Session(testing.db) + + a1 = s.query(A).all()[0] + if event_name == "refresh": + s.refresh(a1) + s.close() + @_combinations def test_flag_resolves(self, target, event_name, fn): A = self.classes.A |