diff options
author | Vincent Vinet <vince.vinet@gmail.com> | 2009-09-30 12:40:42 (GMT) |
---|---|---|
committer | Vincent Vinet <vince.vinet@gmail.com> | 2009-09-30 12:40:42 (GMT) |
commit | c22371ef8af9b2aff165e801119912532a5edf08 (patch) | |
tree | c41d93fbb376601da1c1c5de957919c338f3dd52 /tutorius/TProbe.py | |
parent | 56aa5ada82c014ca0c7cdc6675b93496e0a6967a (diff) |
WIP for running tutorials with the ProbeProxy
Diffstat (limited to 'tutorius/TProbe.py')
-rw-r--r-- | tutorius/TProbe.py | 169 |
1 files changed, 147 insertions, 22 deletions
diff --git a/tutorius/TProbe.py b/tutorius/TProbe.py index 6dd3afb..c4fae81 100644 --- a/tutorius/TProbe.py +++ b/tutorius/TProbe.py @@ -1,6 +1,10 @@ +import logging +import os + import gobject import dbus +import dbus.service import cPickle as pickle import sugar.tutorius.addon as addon @@ -10,10 +14,13 @@ from sugar.tutorius.services import ObjectStore import copy """ -The TProbe module defines two connected classes, TProbe and ProbeProxy. - + -------------------- + | ProbeManager | + -------------------- + | + V -------------------- ---------- - | ProbeProxy |----- DBus ---->| TProbe | + | ProbeProxy |<---- DBus ---->| TProbe | -------------------- ---------- """ @@ -45,6 +52,9 @@ class TProbe(dbus.service.Object): @param activity_name unique activity_id @param activity activity reference, must be a gtk container """ + logging.debug("TProbe :: Creating TProbe for %s (%d)", activity_name, os.getpid()) + logging.debug("TProbe :: Current gobject context: %s", str(gobject.main_context_default())) + logging.debug("TProbe :: Current gobject depth: %s", str(gobject.main_depth())) # Moving the ObjectStore assignment here, in the meantime # the reference to the activity shouldn't be share as a # global variable but passed by the Probe to the objects @@ -230,8 +240,6 @@ class TProbe(dbus.service.Object): return name + str(suffix) - - class ProbeProxy: """ ProbeProxy is a Proxy class for connecting to a remote TProbe. @@ -241,21 +249,28 @@ class ProbeProxy: Public Methods: ProbeProxy(string activityName) :: Constructor - string install(Action action) -> action address - void update(string address, Action action) - void uninstall(string address) - string subscribe(Event event, callable callback) -> event address - void unsubscribe(string address) + string install(Action action) + void update(Action action) + void uninstall(Action action) + void uninstall_all() + string subscribe(Event event, callable callback) + void unsubscribe(Event event, callable callback) + void unsubscribe_all() """ def __init__(self, activityName): """ Constructor @param activityName unique activity id """ + logging.debug("ProbeProxy :: Creating ProbeProxy for %s (%d)", activityName, os.getpid()) + logging.debug("ProbeProxy :: Current gobject context: %s", str(gobject.main_context_default())) + logging.debug("ProbeProxy :: Current gobject depth: %s", str(gobject.main_depth())) bus = dbus.SessionBus() self._object = bus.get_object(activityName, "/tutorius/Probe") self._probe = dbus.Interface(self._object, "org.tutorius.ProbeInterface") + self._actions = {} + self._events = {} # We keep those two data structures to be able to have multiple callbacks # for the same event and be able to remove them independently self._subscribedEvents = {} @@ -269,31 +284,47 @@ class ProbeProxy: self._object.connect_to_signal("eventOccured", _handle_signal, dbus_interface="org.tutorius.ProbeInterface") + def isAlive(self): + try: + return self._probe.ping() == "alive" + except: + return False + def install(self, action): """ Install an action on the TProbe's activity @param action Action to install - @return address identifier used for update and uninstall + @return None """ address = str(self._probe.install(pickle.dumps(action))) - return address + self._actions[action] = address def update(self, address, action): """ Update an already installed action's properties and run it again - @param address identifier returned by the action install - @param action Action to get properties from + @param action Action to update @return None """ - self._probe.update(address, pickle.dumps(action._props)) + if not action in self._actions: + raise RuntimeWarning("Action not installed") + return + self._probe.update(self._actions[action], pickle.dumps(action._props)) - def uninstall(self, address): + def uninstall(self, action): + """ + Uninstall an installed action + @param action Action to uninstall + """ + if action in self._actions: + self._probe.uninstall(self._actions.pop(action)) + + def uninstall_all(self): """ - Uninstall an installd action - @param address identifier returned by the action install + Uninstall all installed actions @return None """ - self._probe.uninstall(address) + for action in self._actions.keys(): + self.uninstall(action) def subscribe(self, event, callback): """ @@ -305,7 +336,9 @@ class ProbeProxy: # TODO elavoie 2009-07-25 When we will allow for patterns both # for event types and sources, we will need to revise the lookup # mecanism for which callback function to call - + if (event, callback) in self._events: + raise RuntimeError("event already registered for callback") + return # Since multiple callbacks could be associated to the same # event signature, we will store multiple callbacks @@ -314,6 +347,8 @@ class ProbeProxy: # dictionary from another one indexed by event address = str(self._probe.subscribe(pickle.dumps(event))) + self._events[(event, callback)] = address + # We use the event object as a key if not self._registeredCallbacks.has_key(event): self._registeredCallbacks[event] = {} @@ -336,13 +371,18 @@ class ProbeProxy: return address - def unsubscribe(self, address): + def unsubscribe(self, event, callback): """ Unregister an event listener @param address identifier given by subscribe() @return None """ - self._probe.unsubscribe(address) + if not (event, callback) in self._events: + raise RuntimeWarning("callback/event not subscribed") + return + + address = self._events.pop((event, callback)) + self._probe.unsubscribe() # Cleanup everything if self._subscribedEvents.has_key(address): @@ -357,4 +397,89 @@ class ProbeProxy: self._subscribedEvents.pop(address) + def unsubscribe_all(self): + """ + Unregister all event listeners + @return None + """ + for event, callback in self._events.keys(): + self.unsubscribe(event, callback) + +class ProbeManager(object): + """ + The ProbeManager provides multiplexing across multiple activity ProbeProxies + + For now, it only handles one at a time, though. + """ + def __init__(self): + self._probes = {} + self._current_activity = None + + def setCurrentActivity(self, activity_id): + if not activity_id in self._probes: + raise RuntimeError("Activity not attached") + self._current_activity = activity_id + + def getCurrentActivity(self): + return self._current_activity + + currentActivity = property(fget=getCurrentActivity, fset=setCurrentActivity) + def attach(self, activity_id): + if activity_id in self._probes: + raise RuntimeWarning("Activity already attached") + return + + self._probes[activity_id] = ProbeProxy(activity_id) + if self._probes[activity_id].isAlive(): + print "Alive!" + else: + print "FAil!" + + def detach(self, activity_id): + if activity_id in self._probes: + probe = self._probes.pop(activity_id) + probe.unsubscribe_all() + probe.uninstall_all() + + def install(self, action): + if self.currentActivity: + return self._probes[self.currentActivity].install(action) + else: + raise RuntimeWarning("No activity attached") + + def update(self, action): + if self.currentActivity: + return self._probes[self.currentActivity].update(action) + else: + raise RuntimeWarning("No activity attached") + + def uninstall(self, action): + if self.currentActivity: + return self._probes[self.currentActivity].uninstall(action) + else: + raise RuntimeWarning("No activity attached") + + def uninstall_all(self): + if self.currentActivity: + return self._probes[self.currentActivity].uninstall_all() + else: + raise RuntimeWarning("No activity attached") + + def subscribe(self, event, callback): + if self.currentActivity: + return self._probes[self.currentActivity].subscribe(event, callback) + else: + raise RuntimeWarning("No activity attached") + + def unsubscribe(self, event, callback): + if self.currentActivity: + return self._probes[self.currentActivity].unsubscribe(event, callback) + else: + raise RuntimeWarning("No activity attached") + + def unsubscribe_all(self): + if self.currentActivity: + return self._probes[self.currentActivity].unsubscribe_all() + else: + raise RuntimeWarning("No activity attached") |