docs: def run_op(self, op, sched):
          """
          Handle the operation:
  
          * if coro is in STATE_RUNNING, send or throw the given op
  
          * if coro is in STATE_NEED_INIT, call the init function and if it
            doesn't return a generator, set STATE_COMPLETED and set the result
            to whatever the function returned.
  
            * if StopIteration is raised, set STATE_COMPLETED and return self.
  
            * if any other exception is raised, set STATE_FAILED, handle error
              or send it to the caller, return self
  
          Return self is used as a optimization. Coroutine is also a Operation
          which handles it's own completion (resuming the caller and the waiters).
          """
          if op is self:
              import warnings
              warnings.warn("Running coro %s with itself. Something is fishy."%op)
          assert self.state < self.STATE_COMPLETED, \
              "%s called with %s op %r, coroutine state (%s) should be less than %s!" % (
                  self, isinstance(op, CoroutineException) and op or
                  (hasattr(op, 'state') and {0:'RUNNING', 1:'FINALIZED', 2:'ERRORED'}[op.state] or 'NOP'), op,
                  self._state_names[self.state],
                  self._state_names[self.STATE_COMPLETED]
              )
          #~ assert self.state < self.STATE_COMPLETED, \
              #~ "%s called with:%s, last one:%s, expected state less than %s!" % (
                  #~ self,
                  #~ op,
                  #~ isinstance(self.lastop, CoroutineException) and ''.join(traceback.format_exception(*self.lastop.message)) or self.lastop,
                  #~ self._state_names[self.STATE_COMPLETED]
              #~ )
          #~ self.lastop = op
          if self.debug:
              print
              if isinstance(op, CoroutineException):
                  print 'Running %r with exception:' % self,
                  if len(op.args) == 3:
                      print '[[['
                      traceback.print_exception(*op.args)
                      print ']]]'
                  else:
                      print op.args
              else:
                  print 'Running %r with: %r' % (self, op)
          global ident
          ident = self
          try:
              if self.state == self.STATE_RUNNING:
                  if self.debug:
                      traceback.print_stack(self.coro.gi_frame)
                  if isinstance(op, CoroutineException):
                      rop = self.coro.throw(*op.args)
                  else:
                      rop = self.coro.send(op and op.finalize(sched))
              elif self.state == self.STATE_NEED_INIT:
                  assert op is None
                  self.coro = self.coro(*self.f_args, **self.f_kws)
                  del self.f_args
                  del self.f_kws
                  if self._valid_gen(self.coro):
                      self.state = self.STATE_RUNNING
                      rop = None
                  else:
                      self.state = self.STATE_COMPLETED
                      self.result = self.coro
                      self.coro = None
                      rop = self
              else:
                  return None
  
          except StopIteration, e:
              self.state = self.STATE_COMPLETED
              self.result = e.args and e.args[0]
              if hasattr(self.coro, 'close'):
                  self.coro.close()
              rop = self
          except (KeyboardInterrupt, GeneratorExit, SystemExit):
              raise
          except:
              self.state = self.STATE_FAILED
              self.result = None
              self.exception = sys.exc_info()
              if hasattr(self.coro, 'close'):
                  self.coro.close()
              if not self.caller:
                  self.handle_error(op)
              rop = self
              sys.exc_clear()
          finally:
              ident = None
          if self.debug:
              print "Yields %s." % rop
          return rop