Extending functionality ======================= The design of **pysig** is flexible so that the user can override most of it's functionality. We will show a couple of examples of how that can be useful. The basics ********** Each router object can be instructed to use different classes. when constructing **Sender**, **Event** or **Signal** objects. This can be done when a new router object is created, likewise: :: import sig class MySender(sig.Sender): pass class MySignal(sig.Signal): pass class MyEvent(sig.Event): pass router = sig.Router(class_sender= MySender, class_event= MyEvent, class_signal= MySignal) Or it can be done on the fly, like this: :: router.class_sender = MySender router.class_event = MyEvent router.class_signal = MySignal If you intend to modify the behavior of the **Signal** class, just for a particular **Sender**, this is how you may proceed: :: # find my sender sender = router.getSender("my_sender") # all signals created by this sender, from now on, will be # instances of MySignal class sender.class_signal = MySignal Exteding Signal class ********************* The **Signal** class is responsible for triggering events in **pysig**. The **Signal** object is created by the **Sender** class using the method **getSignal**, just like you've seen above. By overriding the **trigger** method of the **Signal** class, we can add or modify the **data** parameter or we may even add other types of information to the **info** parameter. Due to the fact that the **info** parameter passed to the callback of a listener, is a dictionary object, we may add additional information if we *hook* the **Signal** class and override the **trigger** method. The information we've decided to add to the **info** parameter in the following example, is the number of occurences of each event sent by any sender. For that matter, we've registered a listener to the router broadcast event, in order to capture all events and we've used it to print the number of occurrences of that particular event, whenever is triggered. The number of occurrences is stored globaly and added to the **info** parameter by our new **Signal** class called **MySignal**. The full example looks like this: Example ------- :: import sig # counts the number of occurrences for each key count_dict = {} def count_message_from(key): global count_dict value = count_dict.get(key,0) value += 1 count_dict[key] = value return value # my own signal class class MySignal(sig.Signal): def __init__(self, objevent, broad_events): sig.Signal.__init__(self, objevent, broad_events) def trigger(self, data): event_name = self.objevent.getName() sender_name = self.objsender.getName() # count each message occurrence count value = count_message_from("%s:%s" % (sender_name, event_name)) self.event_info["count"] = value # call super sig.Signal.trigger(self, data) # listener callback def listen_to_any(info, data): sender = info.get("sender") event = info.get("event") occur = info.get("count") print "Sender: %17.17s Event: %12.12s Occurrence: %u times" % (sender, event, occur) # print statistics def print_statistics(): print "\nEvent statistics:" for key, value in count_dict.iteritems(): print "%30.30s was triggered %u times" % (key, value) # create router and instruct it to use a custom Signal class router = sig.Router(class_signal= MySignal) # register broadcast listener router.addListener(listen_to_any) # create sender (connect event will be triggered) my_events = ["my_event_1", "my_event_2"] sender = router.addSender("my_sender", my_events) # disconnect sender (disconnect event will be triggered) router.removeSender(sender) # connect sender again (connect event will be triggered) sender = router.addSender("my_sender", my_events) # connect another sender sender2 = router.addSender("my_second_sender", my_events) # trigger some events sender.getSignal(my_events[0]).trigger(None) sender2.getSignal(my_events[1]).trigger(None) # remove senders router.removeSender(sender) router.removeSender(sender2) # print statistics print_statistics() And the output: :: Sender: my_sender Event: #connect Occurrence: 1 times Sender: my_sender Event: #disconnect Occurrence: 1 times Sender: my_sender Event: #connect Occurrence: 2 times Sender: my_second_sender Event: #connect Occurrence: 1 times Sender: my_sender Event: my_event_1 Occurrence: 1 times Sender: my_second_sender Event: my_event_2 Occurrence: 1 times Sender: my_sender Event: #disconnect Occurrence: 2 times Sender: my_second_sender Event: #disconnect Occurrence: 1 times Event statistics: my_second_sender:#connect was triggered 1 times my_sender:#disconnect was triggered 2 times my_second_sender:#disconnect was triggered 1 times my_sender:#connect was triggered 2 times my_second_sender:my_event_2 was triggered 1 times my_sender:my_event_1 was triggered 1 times By modifying only the **class_signal** member of a **Sender** object, we can achieve the same effect but just for a particular sender.