diff --git a/sleekxmpp/basexmpp.py b/sleekxmpp/basexmpp.py index fb2b30cd..46626bac 100644 --- a/sleekxmpp/basexmpp.py +++ b/sleekxmpp/basexmpp.py @@ -246,7 +246,7 @@ class BaseXMPP(XMLStream): spec = "(RFC-%s) " % self.plugin[plugin].rfc desc = (spec, self.plugin[plugin].description) - log.debug("Loaded Plugin %s%s", desc) + log.debug("Loaded Plugin %s", desc) except: log.exception("Unable to load plugin: %s", plugin) diff --git a/sleekxmpp/xmlstream/xmlstream.py b/sleekxmpp/xmlstream/xmlstream.py index 2e244c19..cf7e0892 100644 --- a/sleekxmpp/xmlstream/xmlstream.py +++ b/sleekxmpp/xmlstream/xmlstream.py @@ -873,20 +873,25 @@ class XMLStream(object): event queue. All event handlers will run in the same thread. """ - for handler in self.__event_handlers.get(name, []): + handlers = self.__event_handlers.get(name, []) + for handler in handlers: + #TODO: Data should not be copied, but should be read only, + # but this might break current code so it's left for future. + + out_data = copy.copy(data) if len(handlers) > 1 else data + old_exception = getattr(data, 'exception', None) if direct: try: - handler[0](copy.copy(data)) + handler[0](out_data) except Exception as e: error_msg = 'Error processing event handler: %s' - log.exception(error_msg, str(handler[0])) - if hasattr(data, 'exception'): - data.exception(e) + log.exception(error_msg, str(handler[0])) + if old_exception: + old_exception(e) else: self.exception(e) else: - self.event_queue.put(('event', handler, copy.copy(data))) - + self.event_queue.put(('event', handler, out_data)) if handler[2]: # If the handler is disposable, we will go ahead and # remove it now instead of waiting for it to be @@ -1200,17 +1205,17 @@ class XMLStream(object): # to run "in stream" will be executed immediately; the rest will # be queued. unhandled = True - for handler in self.__handlers: - if handler.match(stanza): - stanza_copy = copy.copy(stanza) - handler.prerun(stanza_copy) - self.event_queue.put(('stanza', handler, stanza_copy)) - try: - if handler.check_delete(): - self.__handlers.remove(handler) - except: - pass # not thread safe - unhandled = False + matched_handlers = filter(lambda h: h.match(stanza), self.__handlers) + for handler in matched_handlers: + stanza_copy = copy.copy(stanza) if len(matched_handlers) > 1 else stanza + handler.prerun(stanza_copy) + self.event_queue.put(('stanza', handler, stanza_copy)) + try: + if handler.check_delete(): + self.__handlers.remove(handler) + except: + pass # not thread safe + unhandled = False # Some stanzas require responses, such as Iq queries. A default # handler will be executed immediately for this case. @@ -1226,7 +1231,8 @@ class XMLStream(object): func -- The event handler to execute. args -- Arguments to the event handler. """ - orig = copy.copy(args[0]) + # this is always already copied before this is invoked + orig = args[0] try: func(*args) except Exception as e: @@ -1278,7 +1284,6 @@ class XMLStream(object): self.exception(e) elif etype == 'event': func, threaded, disposable = handler - orig = copy.copy(args[0]) try: if threaded: x = threading.Thread(