From: Mike Bayer Date: Sat, 6 Nov 2010 21:34:54 +0000 (-0400) Subject: - attempting system of propagation. getting stuck on attempting to use instance... X-Git-Tag: rel_0_7b1~253^2~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1f2423d23cc3e8bf8db60b56436752fbd3d83f9d;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - attempting system of propagation. getting stuck on attempting to use instance methods as listeners. --- diff --git a/lib/sqlalchemy/event.py b/lib/sqlalchemy/event.py index 5f46a11537..955c33797c 100644 --- a/lib/sqlalchemy/event.py +++ b/lib/sqlalchemy/event.py @@ -18,6 +18,8 @@ def listen(fn, identifier, target, *args, **kw): for evt_cls in _registrars[identifier]: tgt = evt_cls.accept_with(target) if tgt is not None: + if kw.pop('propagate', False): + fn._sa_event_propagate = True tgt.dispatch.listen(fn, identifier, tgt, *args, **kw) return raise exc.InvalidRequestError("No such event %s for target %s" % @@ -63,12 +65,12 @@ class _Dispatch(object): def descriptors(self): return (getattr(self, k) for k in dir(self) if k.startswith("on_")) - def update(self, other): + def update(self, other, only_propagate=True): """Populate from the listeners in another :class:`_Dispatch` object.""" for ls in other.descriptors: - getattr(self, ls.name).update(ls) + getattr(self, ls.name).update(ls, only_propagate=only_propagate) class _EventMeta(type): """Intercept new Event subclasses and create @@ -195,7 +197,7 @@ class _ListenerCollection(object): def __nonzero__(self): return bool(self.listeners or self.parent_listeners) - def update(self, other): + def update(self, other, only_propagate=True): """Populate from the listeners in another :class:`_Dispatch` object.""" @@ -203,7 +205,9 @@ class _ListenerCollection(object): existing_listener_set = set(existing_listeners) existing_listeners.extend([l for l in other.listeners - if l not in existing_listener_set]) + if l not in existing_listener_set + and not only_propagate or getattr(l, '_sa_event_propagate', False) + ]) def append(self, obj, target): if obj not in self.listeners: diff --git a/lib/sqlalchemy/orm/deprecated_interfaces.py b/lib/sqlalchemy/orm/deprecated_interfaces.py index 3817dc2eee..76e023701e 100644 --- a/lib/sqlalchemy/orm/deprecated_interfaces.py +++ b/lib/sqlalchemy/orm/deprecated_interfaces.py @@ -71,7 +71,7 @@ class MapperExtension(object): ls_meth(self, instance) return reconstruct event.listen(go(ls_meth), 'on_load', - self.class_manager, raw=False) + self.class_manager, raw=False, propagate=True) elif meth == 'init_instance': def go(ls_meth): def init_instance(instance, args, kwargs): @@ -80,7 +80,7 @@ class MapperExtension(object): instance, args, kwargs) return init_instance event.listen(go(ls_meth), 'on_init', - self.class_manager, raw=False) + self.class_manager, raw=False, propagate=True) elif meth == 'init_failed': def go(ls_meth): def init_failed(instance, args, kwargs): @@ -90,10 +90,10 @@ class MapperExtension(object): return init_failed event.listen(go(ls_meth), 'on_init_failure', - self.class_manager, raw=False) + self.class_manager, raw=False, propagate=True) else: event.listen(ls_meth, "on_%s" % meth, self, - raw=False, retval=True) + raw=False, retval=True, propagate=True) def instrument_class(self, mapper, class_): diff --git a/test/base/test_events.py b/test/base/test_events.py index 9099619e5f..995569c60f 100644 --- a/test/base/test_events.py +++ b/test/base/test_events.py @@ -227,5 +227,52 @@ class TestListenOverride(TestBase): ] ) +class TestPropagate(TestBase): + def setUp(self): + global Target + + class TargetEvents(event.Events): + def on_event_one(self, arg): + pass + + def on_event_two(self, arg): + pass + + class Target(object): + dispatch = event.dispatcher(TargetEvents) + + + def test_propagate(self): + result = [] + def listen_one(target, arg): + result.append((target, arg)) + + def listen_two(target, arg): + result.append((target, arg)) + + t1 = Target() + event.listen(listen_one, "on_event_one", t1, propagate=True) + event.listen(listen_two, "on_event_two", t1) + + t2 = Target() + + t2.dispatch.update(t1.dispatch) + + t2.dispatch.on_event_one(t2, 1) + t2.dispatch.on_event_two(t2, 2) + eq_(result, [(t2, 1)]) + + + + + + + + + + + + + \ No newline at end of file