code: def decorate(func, caller, extras=()):
      
      evaldict = dict(_call_=caller, _func_=func)
      es = ''
      for i, extra in enumerate(extras):
          ex = '_e%d_' % i
          evaldict[ex] = extra
          es += ex + ', '
  
      if '3.5' <= sys.version < '3.6':
          # with Python 3.5 isgeneratorfunction returns True for all coroutines
          # however we know that it is NOT possible to have a generator
          # coroutine in python 3.5: PEP525 was not there yet
          generatorcaller = isgeneratorfunction(
              caller) and not iscoroutinefunction(caller)
      else:
          generatorcaller = isgeneratorfunction(caller)
      if generatorcaller:
          fun = FunctionMaker.create(
              func, "for res in _call_(_func_, %s%%(shortsignature)s):\n"
                    "    yield res" % es, evaldict, __wrapped__=func)
      else:
          fun = FunctionMaker.create(
              func, "return _call_(_func_, %s%%(shortsignature)s)" % es,
              evaldict, __wrapped__=func)
      if hasattr(func, '__qualname__'):
          fun.__qualname__ = func.__qualname__
      return fun
docs: decorate(func, caller) decorates a function using a caller.
      If the caller is a generator function, the resulting function
      will be a generator function.