Coroutine bug fixes and gtk helpers
authorEd Page <eopage@byu.net>
Fri, 24 Apr 2009 02:43:53 +0000 (21:43 -0500)
committerEd Page <eopage@byu.net>
Fri, 24 Apr 2009 02:43:53 +0000 (21:43 -0500)
src/coroutines.py

index 9ab75bf..e43c6f1 100755 (executable)
@@ -25,6 +25,7 @@ import functools
 import itertools
 import xml.sax
 import xml.parsers.expat
+import uuid
 
 
 def autostart(func):
@@ -288,11 +289,60 @@ class CoTee(object):
                while True:
                        try:
                                item = yield
+                       except StandardError, e:
+                               for target in self._targets:
+                                       target.throw(e.__class__, e.message)
+                       else:
                                for target in self._targets:
                                        target.send(item)
+
+
+class CoSwitch(object):
+       """
+       >>> apr = printer_sink("a %r")
+       >>> bpr = printer_sink("b %r")
+       >>> cs = CoSwitch(["a", "b"])
+       >>> cs.register_sink("a", apr)
+       >>> cs.register_sink("b", bpr)
+       >>> cs.stage.send(("a", 1, 2, 3))
+       a ('a', 1, 2, 3)
+       >>> cs.stage.send(("b", 1, 2, 3))
+       b ('b', 1, 2, 3)
+       >>> cs.stage.send(("b", 1, 2, 3))
+       b ('b', 1, 2, 3)
+       """
+
+       def __init__(self, signalKeys, key = (lambda eventData: eventData[0])):
+               self.stage = self._stage()
+               self._key = key
+               self._targets = {}
+
+               for signalKey in signalKeys:
+                       self._targets[signalKey] = {}
+
+       def register_sink(self, signalKey, sink):
+               id = uuid.uuid4()
+               self._targets[signalKey][id] = sink
+               return id
+
+       def unregister_sink(self, signalKey, id):
+               del self._targets[signalKey][id]
+
+       def restart(self):
+               self.stage = self._stage()
+
+       @autostart
+       def _stage(self):
+               while True:
+                       try:
+                               item = yield
                        except StandardError, e:
                                for target in self._targets:
                                        target.throw(e.__class__, e.message)
+                       else:
+                               key = self._key(item)
+                               for target in self._targets[key].itervalues():
+                                       target.send(item)
 
 
 def _flush_queue(queue):
@@ -606,6 +656,21 @@ def expat_parse(f, target):
        parser.ParseFile(f)
 
 
+def gtk_source(widget, signalName, target):
+       """
+       >>> import gtk
+       >>> widget = gtk.Button("Source")
+       >>> pr = printer_sink("%r")
+       >>> gtk_source(widget, "clicked", pr)
+       """
+
+       def on_signal(*args):
+               targetArgs = [signalName]
+               targetArgs.extend(args)
+               target.send(targetArgs)
+
+       return widget.connect(signalName, on_signal)
+
 if __name__ == "__main__":
        import doctest
        doctest.testmod()