From: David B. <db...@fi...> - 2004-08-12 23:09:47
|
In using PyDispatcher, I was surprised to find that although the docs mention the use of weak references to automatically clean up when senders or receivers go away, it didn't seem to work in the first case I was using, where my receivers were all connected with the default Any sender. For example: Python 2.3.4 (#53, May 25 2004, 21:17:02) [MSC v.1200 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> from dispatch import dispatcher >>> class Foo: ... def __init__(self): ... dispatcher.connect(self.callback, 'TEST') ... def callback(self): ... print 'callback' ... >>> x = Foo() >>> dispatcher.connections {8252872: {'TEST': [BoundMethodWeakref( <__main__.Foo instance at 0x007D7030>.callback )]}} >>> dispatcher.sendersBack {} >>> del x >>> dispatcher.connections {8252872: {'TEST': [BoundMethodWeakref( None.callback )]}} >>> id(dispatcher.Any) 8252872 I would have expected the link to x.callback to have been removed along when x was destroyed. I traced it down to the fact that there is a specific exclusion in connect() for senders of (None, Any, Anonymous) in installing them in the sendersBack dictionary. However, _removeReceiver requires that the sender be in sendersBack before it will prune the receiver from the connections list. So it's impossible to prune any receivers that may be accepting signals from None (not sure what this does), Any or Anonymous. Adding the excluded senders into the list of senders that _removeReceiver works through seems to handle the case, but since I wasn't positive why they were being excluded in the first place (the comment in connect() seems to indicate an uncertainty about Anonymous, but my case is Any), I'm interested if anyone thinks this would cause a problem. Thanks. -- David PS: Here's the change I tried .. in real use I'd probably build the list of Any/Anonymous ids at the point they are instantiated, since that will never change. *** dispatcher.py.orig Sun Jun 20 21:01:34 2004 --- dispatcher.py Thu Aug 12 19:05:15 2004 *************** *** 359,365 **** def _removeReceiver(receiver): """Remove receiver from connections.""" backKey = id(receiver) ! for senderkey in sendersBack.get(backKey,()): try: for signal in connections[senderkey].keys(): try: --- 359,365 ---- def _removeReceiver(receiver): """Remove receiver from connections.""" backKey = id(receiver) ! for senderkey in (id(Any),id(Anonymous))+sendersBack.get(backKey,()): try: for signal in connections[senderkey].keys(): try: |