From: Mike Bayer Date: Tue, 1 Oct 2013 16:14:34 +0000 (-0400) Subject: - add support for removal of instance methods as event listeners, taking X-Git-Tag: rel_0_9_0b1~67 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3d4d93332951a790e7d74afc5a3e13ed2523fe90;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - add support for removal of instance methods as event listeners, taking into account the id() of the function itself and self, [ticket:2832] --- diff --git a/lib/sqlalchemy/event/registry.py b/lib/sqlalchemy/event/registry.py index 330650e562..868dc28edc 100644 --- a/lib/sqlalchemy/event/registry.py +++ b/lib/sqlalchemy/event/registry.py @@ -12,6 +12,7 @@ from __future__ import absolute_import import weakref import collections +import types from .. import exc @@ -130,13 +131,16 @@ class _EventKey(object): self.target = target self.identifier = identifier self.fn = fn + if isinstance(fn, types.MethodType): + self.fn_key = id(fn.__func__), id(fn.__self__) + else: + self.fn_key = id(fn) self.fn_wrap = _fn_wrap self.dispatch_target = dispatch_target @property def _key(self): - return (id(self.target), self.identifier, id(self.fn)) - + return (id(self.target), self.identifier, self.fn_key) def with_wrapper(self, fn_wrap): if fn_wrap is self._listen_fn: diff --git a/test/base/test_events.py b/test/base/test_events.py index d2bfb0932c..8673c9baf0 100644 --- a/test/base/test_events.py +++ b/test/base/test_events.py @@ -966,6 +966,32 @@ class RemovalTest(fixtures.TestBase): eq_(m1.mock_calls, [call("x")]) + def test_instance(self): + Target = self._fixture() + + class Foo(object): + def __init__(self): + self.mock = Mock() + + def evt(self, arg): + self.mock(arg) + + f1 = Foo() + f2 = Foo() + + event.listen(Target, "event_one", f1.evt) + event.listen(Target, "event_one", f2.evt) + + t1 = Target() + t1.dispatch.event_one("x") + + event.remove(Target, "event_one", f1.evt) + + t1.dispatch.event_one("y") + + eq_(f1.mock.mock_calls, [call("x")]) + eq_(f2.mock.mock_calls, [call("x"), call("y")]) + def test_propagate(self): Target = self._fixture()