old_contents: import traceback
  import logging
  logger = logging.getLogger("vaex.events")
  
  
  class Signal(object):
      def __init__(self, name=None):
          """
  
          :type name: str
          :return:
          """
          self.name = name or repr(self)
          self.callbacks = []
          self.extra_args = {}
  
      def connect(self, callback, prepend=False, *args, **kwargs):
          logger.debug("(%s) connected %s", self.name, callback)
          if prepend:
              self.callbacks.insert(0, callback)
          else:
              self.callbacks.append(callback)
          self.extra_args[callback] = (args, kwargs)
          return callback
  
      def emit(self, *args, **kwargs):
          results = []
          for callback in list(self.callbacks):  # copy it because handlers van add or remove items
              extra_args, extra_kwargs = self.extra_args[callback]
              final_args = args + extra_args
              final_kwargs = {}
              final_kwargs.update(extra_kwargs)
              final_kwargs.update(kwargs)
              try:
                  logger.debug("(%s) calling %r with arguments %r and kwargs %r", self.name, callback, final_args, final_kwargs)
                  value = callback(*final_args, **final_kwargs)
                  results.append(value)
              except Exception:
                  logger.exception("error in handling callback %r with arguments %r and kwargs %r", callback, final_args, final_kwargs)
                  raise
                  # tb = traceback.format_exc()
                  # raise Exception("error while calling callback: %r with arguments %r and kwargs %r" % (callback, final_args, final_kwargs), tb)
          return results
  
      def disconnect(self, callback):
          self.callbacks.remove(callback)
          del self.extra_args[callback]
  
new_contents: import traceback
  import logging
  logger = logging.getLogger("vaex.events")
  
  
  class Signal(object):
      def __init__(self, name=None):
          """
  
          :type name: str
          :return:
          """
          self.name = name or repr(self)
          self.callbacks = []
          self.extra_args = {}
  
      def connect(self, callback, prepend=False, *args, **kwargs):
          logger.debug("(%s) connected %s", self.name, callback)
          # insert first, otherwise emit may get a keyerror in multithreaded cases
          self.extra_args[callback] = (args, kwargs)
          if prepend:
              self.callbacks.insert(0, callback)
          else:
              self.callbacks.append(callback)
          return callback
  
      def emit(self, *args, **kwargs):
          results = []
          for callback in list(self.callbacks):  # copy it because handlers van add or remove items
              extra_args, extra_kwargs = self.extra_args[callback]
              final_args = args + extra_args
              final_kwargs = {}
              final_kwargs.update(extra_kwargs)
              final_kwargs.update(kwargs)
              try:
                  logger.debug("(%s) calling %r with arguments %r and kwargs %r", self.name, callback, final_args, final_kwargs)
                  value = callback(*final_args, **final_kwargs)
                  results.append(value)
              except Exception:
                  logger.exception("error in handling callback %r with arguments %r and kwargs %r", callback, final_args, final_kwargs)
                  raise
                  # tb = traceback.format_exc()
                  # raise Exception("error while calling callback: %r with arguments %r and kwargs %r" % (callback, final_args, final_kwargs), tb)
          return results
  
      def disconnect(self, callback):
          self.callbacks.remove(callback)
          del self.extra_args[callback]
  
subject: make event thread save