[kupfer] helplib: Specialize WeakCallback in two subclasses
- From: Ulrik Sverdrup <usverdrup src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [kupfer] helplib: Specialize WeakCallback in two subclasses
- Date: Wed, 16 Sep 2009 14:22:08 +0000 (UTC)
commit ed8540c744b50126855814d8c6919300edb1dd95
Author: Ulrik Sverdrup <ulrik sverdrup gmail com>
Date: Tue Sep 15 05:23:39 2009 +0200
helplib: Specialize WeakCallback in two subclasses
WeakCallback is a general superclass, and DBus and GObject behavior
are moved out to subclasses. Also, GobjectWeakCallback saves a class
attribute dictionary of all senders so that it can disconnect
immediately when an object is deleted.
kupfer/helplib.py | 59 +++++++++++++++++++++++++++++++++++++---------------
1 files changed, 42 insertions(+), 17 deletions(-)
---
diff --git a/kupfer/helplib.py b/kupfer/helplib.py
index 6fbe533..14b873b 100644
--- a/kupfer/helplib.py
+++ b/kupfer/helplib.py
@@ -88,12 +88,8 @@ class WeakCallback (object):
"""A Weak Callback object that will keep a reference to
the connecting object with weakref semantics.
- This allows to connect to gobject signals without it keeping
- the connecting object alive forever.
-
- Will use @gobject_token or @dbus_token if set as follows:
- sender.disconnect(gobject_token)
- dbus_token.remove()
+ This allows object A to pass a callback method to object S,
+ without object S keeping A alive.
"""
def __init__(self, mcallback):
"""Create a new Weak Callback calling the method @mcallback"""
@@ -101,27 +97,56 @@ class WeakCallback (object):
attr = mcallback.im_func.__name__
self.wref = weakref.ref(obj, self.object_deleted)
self.callback_attr = attr
- self.gobject_token = None
- self.dbus_token = None
+ self.token = None
def __call__(self, *args, **kwargs):
obj = self.wref()
if obj:
attr = getattr(obj, self.callback_attr)
attr(*args, **kwargs)
- elif self.gobject_token:
- sender = args[0]
- sender.disconnect(self.gobject_token)
- self.gobject_token = None
+ else:
+ self.default_callback(*args, **kwargs)
+
+ def default_callback(self, *args, **kwargs):
+ """Called instead of callback when expired"""
+ pass
+
+ def object_deleted(self, wref):
+ """Called when callback expires"""
+ pass
+
+class DbusWeakCallback (WeakCallback):
+ """
+ Will use @token if set as follows:
+ token.remove()
+ """
+ def object_deleted(self, wref):
+ if self.token:
+ self.token.remove()
+ self.token = None
+
+class GobjectWeakCallback (WeakCallback):
+ """
+ Will use @token if set as follows:
+ sender.disconnect(token)
+ """
+ __senders = {}
def object_deleted(self, wref):
- if self.dbus_token:
- self.dbus_token.remove()
- self.dbus_token = None
+ sender = self.__senders.pop(self.token, None)
+ if sender:
+ sender.disconnect(self.token)
+
+ @classmethod
+ def _connect(cls, sender, signal, mcallback, *user_args):
+ # We save references to the sender in a class variable,
+ # this is the only way to have it accessible when obj expires.
+ wc = cls(mcallback)
+ wc.token = sender.connect(signal, wc, *user_args)
+ cls.__senders[wc.token] = sender
def gobject_connect_weakly(sender, signal, mcallback, *user_args):
"""Connect weakly to GObject @sender's @signal,
with a callback method @mcallback
"""
- wc = WeakCallback(mcallback)
- wc.gobject_token = sender.connect(signal, wc, *user_args)
+ GobjectWeakCallback._connect(sender, signal, mcallback, *user_args)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]