From 7c81300e2e183c8f4bffe06a7541b46fb2635cae Mon Sep 17 00:00:00 2001 From: erick Date: Sun, 01 Nov 2009 01:05:47 +0000 Subject: Added a ProbeManager to the service and added a minimal but working automatic registering for Probes on activity startup --- diff --git a/tutorius/TProbe.py b/tutorius/TProbe.py index dbab86a..7f68b42 100644 --- a/tutorius/TProbe.py +++ b/tutorius/TProbe.py @@ -68,6 +68,15 @@ class TProbe(dbus.service.Object): self._installedActions = {} self._subscribedEvents = {} + LOGGER.debug("TProbe :: registering '%s'", activity_name) + # TODO: Once multiple probes are supported by the ProbeManager, + # pass the unique_id associated with this process instead + # of the activity_name twice + from .service import ServiceProxy + ServiceProxy().register_probe(activity_name, activity_name) + + + def start(self): """ Optional method to call if the probe is not inserted into an @@ -397,7 +406,7 @@ class ProbeProxy: return_cb=save_args(self.__clear_event, address), block=block) else: - LOGGER.debug("ProbeProxy :: unsubsribe address %s failed : not registered", address) + LOGGER.debug("ProbeProxy :: unsubscribe address %s failed : not registered", address) def detach(self, block=False): """ @@ -418,16 +427,22 @@ class ProbeManager(object): For now, it only handles one at a time, though. Actually it doesn't do much at all. But it keeps your encapsulation happy """ + _LOGGER = logging.getLogger("sugar.tutorius.ProbeManager") + def __init__(self, proxy_class=ProbeProxy): """Constructor @param proxy_class Class to use for creating Proxies to activities. The class should support the same interface as ProbeProxy. Exists to make this class unit-testable by replacing the Proxy with a mock """ + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + self._ProxyClass = proxy_class self._probes = {} self._current_activity = None + ProbeManager._LOGGER.debug("__init__()") + def setCurrentActivity(self, activity_id): if not activity_id in self._probes: raise RuntimeError("Activity not attached") @@ -441,7 +456,7 @@ class ProbeManager(object): if activity_id in self._probes: raise RuntimeWarning("Activity already attached") - self._probes[activity_id] = self._ProxyClass(activity_id) + self._probes[activity_id] = [self._ProxyClass(activity_id)] #TODO what do we do with this? Raise something? if self._probes[activity_id].isAlive(): print "Alive!" @@ -463,7 +478,7 @@ class ProbeManager(object): @return None """ if self.currentActivity: - return self._probes[self.currentActivity].install(action, block) + return self._probes[self.currentActivity][0].install(action, block) else: raise RuntimeWarning("No activity attached") @@ -476,7 +491,7 @@ class ProbeManager(object): @return None """ if self.currentActivity: - return self._probes[self.currentActivity].update(action, newaction, block) + return self._probes[self.currentActivity][0].update(action, newaction, block) else: raise RuntimeWarning("No activity attached") @@ -487,7 +502,7 @@ class ProbeManager(object): @param block Force a synchroneous dbus call if True """ if self.currentActivity: - return self._probes[self.currentActivity].uninstall(action, block) + return self._probes[self.currentActivity][0].uninstall(action, block) else: raise RuntimeWarning("No activity attached") @@ -499,7 +514,7 @@ class ProbeManager(object): @return address identifier used for unsubscribing """ if self.currentActivity: - return self._probes[self.currentActivity].subscribe(event, callback) + return self._probes[self.currentActivity][0].subscribe(event, callback) else: raise RuntimeWarning("No activity attached") @@ -510,7 +525,40 @@ class ProbeManager(object): @return None """ if self.currentActivity: - return self._probes[self.currentActivity].unsubscribe(address) + return self._probes[self.currentActivity][0].unsubscribe(address) else: raise RuntimeWarning("No activity attached") + def register_probe(self, process_name, unique_id): + """ Adds a probe to the known probes, to be used by a tutorial. + + A generic name for a process (like an Activity) is passed + so that the execution of a tutorial will use that generic + name. However, a unique id is also passed to differentiate + between many instances of the same process. + + @param process_name The generic name of a process + @param unique_id The unique identification associated to this + process + """ + ProbeManager._LOGGER.debug("register_probe(%s,%s)", process_name, unique_id) + # For now make sure the process_name and unique_id are the same, + # until we support multiple probes for the same activity + assert process_name == unique_id + self._probes[process_name] = [self._ProxyClass(process_name)] + + + def unregister_probe(self, unique_id): + """ Remove a probe from the known probes. + + @param unique_id The unique identification associated to this + process + """ + ProbeManager._LOGGER.debug("unregister_probe(%s)", unique_id) + # For now simply assume the unique_id is the same as the process_name + # TODO: search through the dictionary to remove all probes with + # the unique_id name + if unique_id in self._probes: + probe = self._probes.pop(unique_id) + probe.detach() + diff --git a/tutorius/service.py b/tutorius/service.py index eb246a1..70efc80 100644 --- a/tutorius/service.py +++ b/tutorius/service.py @@ -2,6 +2,9 @@ import dbus from .engine import Engine from .dbustools import remote_call +from .TProbe import ProbeManager +import logging +LOGGER = logging.getLogger("sugar.tutorius.service") _DBUS_SERVICE = "org.tutorius.Service" _DBUS_PATH = "/org/tutorius/Service" @@ -19,11 +22,13 @@ class Service(dbus.service.Object): self._engine = None + self._probeMgr = ProbeManager() + def start(self): """ Start the service itself """ # For the moment there is nothing to do - pass + LOGGER.debug("Service.start()") @dbus.service.method(_DBUS_SERVICE_IFACE, @@ -50,6 +55,35 @@ class Service(dbus.service.Object): """ self._engine.pause() + @dbus.service.method(_DBUS_SERVICE_IFACE, + in_signature="ss", out_signature="") + def register_probe(self, process_name, unique_id): + """ Adds a probe to the known probes, to be used by a tutorial. + + A generic name for a process (like an Activity) is passed + so that the execution of a tutorial will use that generic + name. However, a unique id is also passed to differentiate + between many instances of the same process. + + @param process_name The generic name of a process + @param unique_id The unique identification associated to this + process + """ + LOGGER.debug("Service.register_probe(%s,%s)", process_name, unique_id) + self._probeMgr.register_probe(process_name, unique_id) + + @dbus.service.method(_DBUS_SERVICE_IFACE, + in_signature="s", out_signature="") + def unregister_probe(self, unique_id): + """ Remove a probe from the known probes. + + @param process_name The generic name of a process + @param unique_id The unique identification associated to this + process + """ + LOGGER.debug("Service.unregister_probe(%s)", unique_id) + self._probeMgr.unregister_probe(unique_id) + class ServiceProxy: """ Proxy to connect to the Service object, abstracting the DBus interface""" @@ -74,6 +108,29 @@ class ServiceProxy: """ remote_call(self._service.pause, (), block=False) + def register_probe(self, process_name, unique_id): + """ Adds a probe to the known probes, to be used by a tutorial. + + A generic name for a process (like an Activity) is passed + so that the execution of a tutorial will use that generic + name. However, a unique id is also passed to differentiate + between many instances of the same process. + + @param process_name The generic name of a process + @param unique_id The unique identification associated to this + process + """ + self._service.register_probe(process_name,unique_id) + + def unregister_probe(self, unique_id): + """ Remove a probe from the known probes. + + @param process_name The generic name of a process + @param unique_id The unique identification associated to this + process + """ + self._service.unregister_probe(unique_id) + if __name__ == "__main__": import dbus.mainloop.glib import gobject -- cgit v0.9.1