class BaseComponent(PublishingElement): """ """ cls_add_component_hooks = EventHook() listeners = [] _init_hooks = EventHook() def __init__(self): super(BaseComponent, self).__init__() self.obj_listeners = [] self.gen_id = generate_id(self) self.router = Router() self._internal_router = Router() # This was init because I couldn't figure out how to append to a cls variable # in the subclass definitions. The mixin can do it, but I'd need a metaclass # to do it for the Series and Listening Component # also was done to bind to self self.add_component_hooks = EventHook() self.components = [] self.broadcast_hooks = EventHook() self.broadcast_hooks += self.publish self.broadcast_hooks += self.send self.front = self self._init_hooks.fire(self) def broadcast(self, event): self.broadcast_hooks.fire(event) def add_component(self, component, contained=True, **kwargs): if not contained: raise Exception("Defaulted to contained always True") # always contained component.front = self self.components.append(component) self.add_component_hooks.fire(component, **kwargs) # TODO add check to see if hook is unbound. Which I think it will always be self.cls_add_component_hooks.fire(self, component, **kwargs) # shortcut for end and start end_func = getattr(component, 'end', None) if end_func and callable(end_func): self.bind(EndEvent, end_func, 'event') # delegate to router def bind(self, key, callback, exchange='event'): if self.router is None: self.router = Router() self.router.bind(key, callback, exchange) def send(self, message): # note that front isn't always a bouncebox self.front.router.send(message)
class BounceBox(Component): """ This class contains everything """ def __init__(self): super(BounceBox, self).__init__() self.end_hooks = EventHook() self.start_hooks = EventHook() self.sources = [] def start_box(self, autorun=True, interactive=False): """ Starts the bounce box and calls start on the sources autorun: iterate through sources until completion interactive: starts prompt """ if len(self.sources) == 0: print("No Sources Attached. Exiting...") return self.start_hooks.fire(StartEvent()) if interactive: self.start_interactive() elif autorun: self.start_auto() def start_auto(self): while True: try: self.send_next() except EndOfSources: print('Done Running Sources') break def start_interactive(self): print(""" Interactive Mode Press Enter for one iteration Press a number for that many iterations Type stop to end session""") while True: key = raw_input('\nNext ') if key == 'stop': break if key is '': key = 1 try: key = int(key) except: print('Input is wrong') continue for x in range(key): self.send_next() def send_next(self): """ Grab next event and send it """ event = next(self) self.send(event) return event def sender_iter(self): """ Returns an iterator that will return """ while 1: yield self.send_next() def __next__(self): """ Out of multiple sources this will send the next of chronological order """ #TODO right now this doesn't do the chronological sort # currently only supports one source try: for source in self.sources: event = next(source) return event except StopIteration: # send End event self.end_box() raise EndOfSources next = __next__ def __iter__(self): return self def end_box(self): """ Let everyone know the box is done """ self.end_hooks.fire(EndEvent()) def send(self, message): self.router.send(message) def add_component(self, component): if hasattr(component, 'handle_end_box'): self.end_hooks += component.handle_end_box if hasattr(component, 'handle_start_box'): self.start_hooks += component.handle_start_box super(BounceBox, self).add_component(component) def add_source(self, component): self.sources.append(component) self.add_component(component)