docs: def no_coroutine(f):
      """
      This is not a coroutine ;)
  
      Use as a decorator:
      @no_coroutine
      def foo():
          five = yield 5
          print(yield "hello")
  
      The function passed should be a generator yielding whatever you feel like.
      The yielded values instantly get passed back into the generator.
      It's basically the same as if you didn't use yield at all.
      The example above is equivalent to:
      def foo():
          five = 5
          print("hello")
  
      Why?
      This is the counterpart to coroutine used by maybe_coroutine below.
      """
  
      @functools.wraps(f)
      def _no_coroutine(*args, **kwargs):
          generator = f(*args, **kwargs)
  
          # Special case for a function that returns immediately
          if not isinstance(generator, types.GeneratorType):
              return generator
  
          previous = None
          first    = True
  
          while True:
              element = None
  
              try:
                  if first:
                      element = next(generator)
                  else:
                      element = generator.send(previous)
              except StopIteration as e:
                  return getattr(e, "value", None)
              except ReturnValueException as e:
                  return e.value
              else:
                  previous = element
                  first    = False
  
      return _no_coroutine