def run(self): self.irc = IRC() self.irc.add_global_handler(event='all_events', handler=self.process_events, priority=-1) self.network_config = Dotfile('networks', use_defaults=False) self.connections = {} self.networks = {} log.info('starting engine') irc_thread = threading.Thread(target=self.process_irc) irc_thread.start() command_thread = threading.Thread(target=self.process_commands) command_thread.start() while command_thread.is_alive(): command_thread.join() log.debug('command_thread stopped') while irc_thread.is_alive(): irc_thread.join() log.debug('irc_thread stopped') async_ui_message('stopped')
class Engine(threading.Thread): def __init__(self): super(Engine, self).__init__() self.running = True self.commands = Queue.Queue() def async_command(self, command, network=None, params=None): """Send an asynchronous command to engine thread, for the given network with the given parameters. This is generally meant to be called from the UI thread, but can also be used to queue a command from the engine. A network value of '*' will send the command to all networks that are currently connected.""" self.commands.put((command, network, params)) def next_command(self, block=False, timeout=None): """Get the next command from the queue, return a three-tuple with the command, network, and parameters. If the queue is empty and block is false, None will be returned for all values.""" try: command, network, params = self.commands.get(block=block) return command, network, params except Queue.Empty: return None, None, None def run(self): self.irc = IRC() self.irc.add_global_handler(event='all_events', handler=self.process_events, priority=-1) self.network_config = Dotfile('networks', use_defaults=False) self.connections = {} self.networks = {} log.info('starting engine') irc_thread = threading.Thread(target=self.process_irc) irc_thread.start() command_thread = threading.Thread(target=self.process_commands) command_thread.start() while command_thread.is_alive(): command_thread.join() log.debug('command_thread stopped') while irc_thread.is_alive(): irc_thread.join() log.debug('irc_thread stopped') async_ui_message('stopped') def process_irc(self): while self.running: try: self.irc.process_once(timeout=1) except Exception as e: log.exception('exception in process_irc: {0}'.format(e)) def process_commands(self): while self.running: try: command, network, params = self.next_command(block=True) log.info('processing command {0} from {1} with parameters {2}'.format(command, network, params)) method = 'command_' + command if hasattr(self, method): getattr(self, method)(network, params) else: log.warning('method {0} not found, command discarded'.format(method)) except Exception as e: log.exception('exception processing command: {0}'.format(e)) def process_events(self, conn, event): try: network = self.connections[conn] if event.eventtype() != 'all_raw_messages': network.notify(event) except Exception as e: log.exception('exception during dispatch: {0}'.format(e)) def command_connect(self, name, params, explicit=True): if name is None: for name in self.network_config: self.command_connect(name, params, explicit=False) elif name in self.network_config: if explicit or self.network_config[name]['connect']: network = Network(name, self.network_config[name], self.irc) connection = network.connect() self.networks[name] = network self.connections[connection] = network else: log.warning('network {0} not found in configuration, could not connect'.format(name)) def command_send(self, network, (channel, message)): log.debug('send message to {0} {1}: {2}'.format(network, channel, message)) self.command_raw(network.name, message)