Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/tutorius/TProbe.py
diff options
context:
space:
mode:
Diffstat (limited to 'tutorius/TProbe.py')
-rw-r--r--tutorius/TProbe.py140
1 files changed, 105 insertions, 35 deletions
diff --git a/tutorius/TProbe.py b/tutorius/TProbe.py
index dbab86a..0c79690 100644
--- a/tutorius/TProbe.py
+++ b/tutorius/TProbe.py
@@ -38,45 +38,65 @@ class TProbe(dbus.service.Object):
a DBUS Interface.
"""
- def __init__(self, activity_name, activity):
+ def __init__(self, activity, service_proxy=None):
"""
Create and register a TProbe for an activity.
- @param activity_name unique activity_id
@param activity activity reference, must be a gtk container
+ @param service_proxy A Service proxy object to do the registering
"""
- LOGGER.debug("TProbe :: Creating TProbe for %s (%d)", activity_name, os.getpid())
- LOGGER.debug("TProbe :: Current gobject context: %s", str(gobject.main_context_default()))
- LOGGER.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
# that requires it
self._activity = activity
+
+ if service_proxy == None:
+ from .service import ServiceProxy
+
+ self._service_proxy = service_proxy or ServiceProxy()
ObjectStore().activity = activity
- self._activity_name = activity_name
+ self._activity_name = activity.get_bundle_id()
+ self._unique_id = activity.get_id()
+
+ LOGGER.debug("TProbe :: Creating TProbe for %s (%d)", self._activity_name, os.getpid())
+ LOGGER.debug("TProbe :: Current gobject context: %s", str(gobject.main_context_default()))
+ LOGGER.debug("TProbe :: Current gobject depth: %s", str(gobject.main_depth()))
self._session_bus = dbus.SessionBus()
# Giving a new name because _name is already used by dbus
- self._name2 = dbus.service.BusName(activity_name, self._session_bus)
- dbus.service.Object.__init__(self, self._session_bus, "/tutorius/Probe")
+ self._name2 = dbus.service.BusName(self._activity_name, self._session_bus)
+ dbus.service.Object.__init__(self, self._session_bus, "/tutorius/Probe/"+str(self._unique_id))
# Add the dictionary we will use to store which actions and events
# are known
self._installedActions = {}
self._subscribedEvents = {}
+ LOGGER.debug("TProbe :: registering '%s' with unique_id '%s'", self._activity_name, activity.get_id())
+ self._service_proxy.register_probe(self._activity_name, self._unique_id)
+
+
+
def start(self):
"""
Optional method to call if the probe is not inserted into an
existing activity. Starts a gobject mainloop
"""
mainloop = gobject.MainLoop()
- print "Starting Probe for " + self._activity_name
mainloop.run()
+ def stop(self):
+ """
+ Clean up the probe when finished. Should be called just
+ before a process ends
+ """
+ from .service import ServiceProxy
+ LOGGER.debug("TProbe :: unregistering '%s' with unique_id '%s'", self._activity_name, self._unique_id)
+ ServiceProxy().unregister_probe(self._unique_id)
+
@dbus.service.method("org.tutorius.ProbeInterface",
in_signature='s', out_signature='')
def registered(self, service):
@@ -234,16 +254,17 @@ class ProbeProxy:
It provides an object interface to the TProbe, which requires pickled
strings, across a DBus communication.
"""
- def __init__(self, activityName):
+ def __init__(self, activityName, unique_id):
"""
Constructor
- @param activityName unique activity id. Must be a valid dbus bus name.
+ @param activityName generic activity name. Must be a valid dbus bus name.
+ @param unique_id unique id specific to an instance of an activity
"""
LOGGER.debug("ProbeProxy :: Creating ProbeProxy for %s (%d)", activityName, os.getpid())
LOGGER.debug("ProbeProxy :: Current gobject context: %s", str(gobject.main_context_default()))
LOGGER.debug("ProbeProxy :: Current gobject depth: %s", str(gobject.main_depth()))
bus = dbus.SessionBus()
- self._object = bus.get_object(activityName, "/tutorius/Probe")
+ self._object = bus.get_object(activityName, "/tutorius/Probe/"+str(unique_id))
self._probe = dbus.Interface(self._object, "org.tutorius.ProbeInterface")
self._actions = {}
@@ -397,7 +418,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 +439,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")
@@ -437,23 +464,6 @@ class ProbeManager(object):
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")
-
- 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!"
- else:
- print "FAil!"
-
- def detach(self, activity_id):
- if activity_id in self._probes:
- probe = self._probes.pop(activity_id)
- probe.detach()
- if self._current_activity == activity_id:
- self._current_activity = None
def install(self, action, block=False):
"""
@@ -463,7 +473,7 @@ class ProbeManager(object):
@return None
"""
if self.currentActivity:
- return self._probes[self.currentActivity].install(action, block)
+ return self._first_proxy(self.currentActivity).install(action, block)
else:
raise RuntimeWarning("No activity attached")
@@ -476,7 +486,7 @@ class ProbeManager(object):
@return None
"""
if self.currentActivity:
- return self._probes[self.currentActivity].update(action, newaction, block)
+ return self._first_proxy(self.currentActivity).update(action, newaction, block)
else:
raise RuntimeWarning("No activity attached")
@@ -487,7 +497,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._first_proxy(self.currentActivity).uninstall(action, block)
else:
raise RuntimeWarning("No activity attached")
@@ -499,7 +509,7 @@ class ProbeManager(object):
@return address identifier used for unsubscribing
"""
if self.currentActivity:
- return self._probes[self.currentActivity].subscribe(event, callback)
+ return self._first_proxy(self.currentActivity).subscribe(event, callback)
else:
raise RuntimeWarning("No activity attached")
@@ -510,7 +520,67 @@ class ProbeManager(object):
@return None
"""
if self.currentActivity:
- return self._probes[self.currentActivity].unsubscribe(address)
+ return self._first_proxy(self.currentActivity).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)
+ if process_name not in self._probes:
+ self._probes[process_name] = [(unique_id,self._ProxyClass(process_name, unique_id))]
+ else:
+ self._probes[process_name].append((unique_id,self._ProxyClass(process_name, unique_id)))
+
+
+ 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 process_name, proxies in self._probes.items():
+ for id, proxy in proxies:
+ if unique_id == id:
+ proxy.detach()
+ proxies.remove((id,proxy))
+ if len(proxies) == 0:
+ self._probes.pop(process_name)
+
+ def get_registered_probes_list(self, process_name=None):
+ if process_name == None:
+ probe_list = []
+ for probes in self._probes.itervalues():
+ probe_list.extend(probes)
+ return probe_list
+ else:
+ if process_name in self._probes:
+ return self._probes[process_name]
+ else:
+ return []
+
+
+
+ def _first_proxy(self, process_name):
+ """
+ Returns the oldest probe connected under the process_name
+ @param process_name The generic process name under which the probe
+ is connected
+ """
+ if process_name in self._probes:
+ return self._probes[process_name][0][1]
+ else:
+ raise RuntimeWarning("No activity attached under '%s'", process_name)
+
+