text: import traceback
  
  from eventlet.support import greenlets as greenlet, six
  from eventlet.hubs import get_hub
  
  """ If true, captures a stack trace for each timer when constructed.  This is
  useful for debugging leaking timers, to find out where the timer was set up. """
  _g_debug = False
  
  
  class Timer(object):
      def __init__(self, seconds, cb, *args, **kw):
          """Create a timer.
              seconds: The minimum number of seconds to wait before calling
              cb: The callback to call when the timer has expired
              *args: The arguments to pass to cb
              **kw: The keyword arguments to pass to cb
  
          This timer will not be run unless it is scheduled in a runloop by
          calling timer.schedule() or runloop.add_timer(timer).
          """
          self.seconds = seconds
          self.tpl = cb, args, kw
          self.called = False
          if _g_debug:
              self.traceback = six.StringIO()
              traceback.print_stack(file=self.traceback)
  
      @property
      def pending(self):
          return not self.called
  
      def __repr__(self):
          secs = getattr(self, 'seconds', None)
          cb, args, kw = getattr(self, 'tpl', (None, None, None))
          retval = "Timer(%s, %s, *%s, **%s)" % (
              secs, cb, args, kw)
          if _g_debug and hasattr(self, 'traceback'):
              retval += '\n' + self.traceback.getvalue()
          return retval
  
      def copy(self):
          cb, args, kw = self.tpl
          return self.__class__(self.seconds, cb, *args, **kw)
  
      def schedule(self):
          """Schedule this timer to run in the current runloop.
          """
          self.called = False
          self.scheduled_time = get_hub().add_timer(self)
          return self
  
      def __call__(self, *args):
          if not self.called:
              self.called = True
              cb, args, kw = self.tpl
              try:
                  cb(*args, **kw)
              finally:
                  try:
                      del self.tpl
                  except AttributeError:
                      pass
  
      def cancel(self):
          """Prevent this timer from being called. If the timer has already
          been called or canceled, has no effect.
          """
          if not self.called:
              self.called = True
              get_hub().timer_canceled(self)
              try:
                  del self.tpl
              except AttributeError:
                  pass
  
      # No default ordering in 3.x. heapq uses <
      # FIXME should full set be added?
      def __lt__(self, other):
          return id(self) < id(other)
  
  
  class LocalTimer(Timer):
  
      def __init__(self, *args, **kwargs):
          self.greenlet = greenlet.getcurrent()
          Timer.__init__(self, *args, **kwargs)
  
      @property
      def pending(self):
          if self.greenlet is None or self.greenlet.dead:
              return False
          return not self.called
  
      def __call__(self, *args):
          if not self.called:
              self.called = True
              if self.greenlet is not None and self.greenlet.dead:
                  return
              cb, args, kw = self.tpl
              cb(*args, **kw)
  
      def cancel(self):
          self.greenlet = None
          Timer.cancel(self)
  