docs: def emit_signal(sender=None, namespace=None):
      """
      @emit_signal
      A decorator to mark a method or function as a signal emitter
      It will turn the function into a decorator that can be used to 
      receive signal with: $fn_name.pre.connect, $fn_name.post.connect 
      *pre will execute before running the function
      *post will run after running the function
      
      **observe is an alias to post.connect
      
      :param sender: string  to be the sender.
      If empty, it will use the function __module__+__fn_name,
      or method __module__+__class_name__+__fn_name__
      :param namespace: The namespace. If None, it will use the global namespace
      :return:
  
      """
      if not namespace:
          namespace = __signals_namespace
  
      def decorator(fn):
          fname = sender
          if not fname:
              fnargs = inspect.getargspec(fn).args
              fname = fn.__module__
              if 'self' in fnargs or 'cls' in fnargs:
                  caller = inspect.currentframe().f_back
                  fname += "_" + caller.f_code.co_name
              fname += "__" + fn.__name__
  
          # pre and post
          fn.pre = namespace.signal('pre_%s' % fname)
          fn.post = namespace.signal('post_%s' % fname)
          # alias to post.connect
          fn.observe = fn.post.connect
  
          def send(action, *a, **kw):
              sig_name = "%s_%s" % (action, fname)
              result = kw.pop("result", None)
              kw.update(inspect.getcallargs(fn, *a, **kw))
              sendkw = {
                  "kwargs": {k: v for k, v in kw.items() if k in kw.keys()},
                  "sender": fn.__name__,
                  "emitter": kw.get('self', kw.get('cls', fn))
              }
              if action == 'post':
                  namespace.signal(sig_name).send(result, **sendkw)
              else:
                  namespace.signal(sig_name).send(**sendkw)
  
          @functools.wraps(fn)
          def wrapper(*args, **kwargs):
              send('pre', *args, **kwargs)
              result = fn(*args, **kwargs)
              kwargs["result"] = result
              send('post', *args, **kwargs)
              return result
          return wrapper
      return decorator