def test_cancel_proportion(self): # if fewer than half the pending timers are canceled, it should # not clean them out hub = hubs.get_hub() uncanceled_timers = [] stimers = hub.get_timers_count() scanceled = hub.timers_canceled for i in xrange(1000): # 2/3rds of new timers are uncanceled t = hubs.get_hub().schedule_call_global(60, noop) t2 = hubs.get_hub().schedule_call_global(60, noop) t3 = hubs.get_hub().schedule_call_global(60, noop) eventlet.sleep() self.assert_less_than_equal(hub.timers_canceled, hub.get_timers_count() + 1) t.cancel() self.assert_less_than_equal(hub.timers_canceled, hub.get_timers_count() + 1) uncanceled_timers.append(t2) uncanceled_timers.append(t3) # 3000 new timers, plus a few extras self.assert_less_than_equal(stimers + 3000, stimers + hub.get_timers_count()) self.assertEqual(hub.timers_canceled, 1000) for t in uncanceled_timers: t.cancel() self.assert_less_than_equal(hub.timers_canceled, hub.get_timers_count()) eventlet.sleep()
def acquire(self, blocking=True): """Acquire a semaphore. When invoked without arguments: if the internal counter is larger than zero on entry, decrement it by one and return immediately. If it is zero on entry, block, waiting until some other thread has called release() to make it larger than zero. This is done with proper interlocking so that if multiple acquire() calls are blocked, release() will wake exactly one of them up. The implementation may pick one at random, so the order in which blocked threads are awakened should not be relied on. There is no return value in this case. When invoked with blocking set to true, do the same thing as when called without arguments, and return true. When invoked with blocking set to false, do not block. If a call without an argument would block, return false immediately; otherwise, do the same thing as when called without arguments, and return true.""" if not blocking and self.locked(): return False if self.counter <= 0: self._waiters.add(greenthread.getcurrent()) try: while self.counter <= 0: hubs.get_hub().switch() finally: self._waiters.discard(greenthread.getcurrent()) self.counter -= 1 return True
def test_explicit_hub(self): oldhub = hubs.get_hub() try: hubs.use_hub(Foo) assert isinstance(hubs.get_hub(), Foo), hubs.get_hub() finally: hubs._threadlocal.hub = oldhub
def add(self, greenlet, name = None): ref = weakref.ref(greenlet) self.greenlets.append((ref, name)) try: get_hub()._addManagedGreenlets(greenlet) except AttributeError: pass
def close(self, linger=None): super(Socket, self).close(linger) if self._eventlet_listener is not None: hubs.get_hub().remove(self._eventlet_listener) self.__dict__['_eventlet_listener'] = None # wake any blocked threads self._eventlet_send_event.wake() self._eventlet_recv_event.wake()
def killall(self): if len(self.greenlets) == 0: return t = spawn(_killall_helper, self.greenlets) try: get_hub()._addManagedGreenlets(t) except: pass
def close(self): _Socket.close(self) if self._eventlet_listener is not None: hubs.get_hub().remove(self._eventlet_listener) self._eventlet_listener = None # wake any blocked threads self._eventlet_send_event.wake() self._eventlet_recv_event.wake()
def main(): cage = d6cage.d6Cage() sa = service_a.serviceA() sb = service_b.serviceB() cage.createservice(sa, "service a") cage.createservice(sb, "service b") hubs.get_hub().switch()
def hub_exceptions(state): """Toggles whether the hub prints exceptions that are raised from its timers. This can be useful to see how greenthreads are terminating. """ from eventlet import hubs hubs.get_hub().set_timer_exceptions(state) from eventlet import greenpool greenpool.DEBUG = state
def __call__(self, *args): if not self.called: self.called = True cb, args, kw = self.tpl try: cb(*args, **kw) finally: get_hub().timer_finished(self)
def spawn_greenlet(function, *args): """Create a new greenlet that will run ``function(*args)``. The current greenlet won't be unscheduled. Keyword arguments aren't supported (limitation of greenlet), use :func:`spawn` to work around that. """ g = api.Greenlet(function) g.parent = hubs.get_hub().greenlet hubs.get_hub().schedule_call_global(0, g.switch, *args) return g
def hub_listener_stacks(state): """Toggles whether or not the hub records the stack when clients register listeners on file descriptors. This can be useful when trying to figure out what the hub is up to at any given moment. To inspect the stacks of the current listeners, call :func:`format_hub_listeners` at critical junctures in the application logic. """ from eventlet import hubs hubs.get_hub().set_debug_listeners(state)
def test_explicit_hub(self): if getattr(hubs.get_hub(), 'uses_twisted_reactor', None): # doesn't work with twisted return oldhub = hubs.get_hub() try: hubs.use_hub(Foo) self.assert_(isinstance(hubs.get_hub(), Foo), hubs.get_hub()) finally: hubs._threadlocal.hub = oldhub
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 try: cb(*args, **kw) finally: get_hub().timer_finished(self)
def killall(procs, *throw_args, **kwargs): if not throw_args: throw_args = (ProcExit, ) wait = kwargs.pop('wait', False) if kwargs: raise TypeError('Invalid keyword argument for proc.killall(): %s' % ', '.join(kwargs.keys())) for g in procs: if not g.dead: hubs.get_hub().schedule_call_global(0, g.throw, *throw_args) if wait and api.getcurrent() is not hubs.get_hub().greenlet: api.sleep(0)
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().io_loop.remove_timeout(self.scheduled_time) try: del self.tpl except AttributeError: pass
def start(self, start_listeners=True): self.log("Server", "info", 'starting server "%s" (%s)' % (self.name, self.procid)) # setup ipc connections blisten = self.server_config.get("broker_listen", "") for i in blisten.split(","): if i: host, _, port = i.partition(":") port = int(port) self.broker.connections.listen((host, port)) conns = self.get_config_section("connections") for k, v in conns: host, _, port = v.partition(":") port = int(port) self.broker.connections.connect((host, port), target=k) self.broker.start() # wsgi server... self.wsgi = WSGIServer(self, self.name, config=self.get_config_section("http")) dirs = self.server_config.get("static_directories", None) if dirs is not None: from drivel.contrib.fileserver import StaticFileServer self.wsgi.app = StaticFileServer(dirs.split(","), self.wsgi.app, self) # components... components = self.get_config_section("components") for name in components: self.log("Server", "info", 'adding "%s" component to %s' % (name, self.procid)) self.components[name] = components.import_(name)(self, name) # start everything listening... if start_listeners and "backdoor_port" in self.config.server: # enable backdoor console bdport = self.server_config.getint("backdoor_port") self.log("Server", "info", "enabling backdoor on port %s" % bdport) eventlet.spawn( backdoor.backdoor_server, listen(("127.0.0.1", bdport)), locals={ "server": self, "debug": debug, "exit": safe_exit(), "quit": safe_exit(), "stats": lambda: pprint.pprint(self.stats()), }, ) if start_listeners and self.server_config.getboolean("start_www", True): self.wsgi.start(listen=listen) if start_listeners: try: hubs.get_hub().switch() except KeyboardInterrupt, e: pass
def release(self, blocking=True): """Release a semaphore, incrementing the internal counter by one. When it was zero on entry and another thread is waiting for it to become larger than zero again, wake up that thread. The *blocking* argument is for consistency with CappedSemaphore and is ignored""" self.counter += 1 if self._waiters: hubs.get_hub().schedule_call_global(0, self._do_acquire) return True
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
def test_cancel_immediate(self): hub = hubs.get_hub() stimers = hub.get_timers_count() scanceled = hub.timers_canceled for i in xrange(2000): t = hubs.get_hub().schedule_call_global(60, noop) t.cancel() self.assert_less_than_equal(hub.timers_canceled - scanceled, hub.get_timers_count() - stimers + 1) # there should be fewer than 1000 new timers and canceled self.assert_less_than_equal(hub.get_timers_count(), 1000 + stimers) self.assert_less_than_equal(hub.timers_canceled, 1000)
def wait(self): """Wait until send or send_exception is called. Return value passed into send() or raise exception passed into send_exception(). """ assert self.greenlet is None current = api.getcurrent() assert current is not hubs.get_hub().greenlet self.greenlet = current try: return hubs.get_hub().switch() finally: self.greenlet = None
def _do_send(self, links, consult): while links: listener, link = links.pop() try: if listener in consult: try: link(self) finally: consult.pop(listener, None) except: hubs.get_hub().schedule_call_global(0, self._do_send, links, consult) raise
def _dothrow(self, gt, cgt): #print 'throwing cancel from:%s to:%s current:%s' % (gt, cgt, # greenthread.getcurrent()) if isinstance(cgt, weakref.ref): cgt = cgt() if cgt is None: return if isinstance(cgt, greenthread.GreenThread): cgt.kill(CancelOperation, None, None) else: hubs.get_hub().schedule_call_local(0, greenthread.getcurrent().switch) cgt.throw(CancelOperation())
def kill(self, *throw_args): """ Raise an exception in the greenlet. Unschedule the current greenlet so that this :class:`Proc` can handle the exception (or die). The exception can be specified with *throw_args*. By default, :class:`ProcExit` is raised. """ if not self.dead: if not throw_args: throw_args = (ProcExit, ) hubs.get_hub().schedule_call_global(0, self.greenlet.throw, *throw_args) if api.getcurrent() is not hubs.get_hub().greenlet: api.sleep(0)
def test_cancel_accumulated(self): hub = hubs.get_hub() stimers = hub.get_timers_count() scanceled = hub.timers_canceled for i in xrange(2000): t = hubs.get_hub().schedule_call_global(60, noop) eventlet.sleep() self.assert_less_than_equal(hub.timers_canceled, hub.get_timers_count() + 1) t.cancel() self.assert_less_than_equal(hub.timers_canceled, hub.get_timers_count() + 1, hub.timers) # there should be fewer than 1000 new timers and canceled self.assert_less_than_equal(hub.get_timers_count(), 1000 + stimers) self.assert_less_than_equal(hub.timers_canceled, 1000)
def start(self): """Schedule the timeout. This is called on construction, so it should not be called explicitly, unless the timer has been canceled.""" assert not self.pending, \ '%r is already started; to restart it, cancel it first' % self if self.seconds is None: # "fake" timeout (never expires) self.timer = None elif self.exception is None or isinstance(self.exception, bool): # timeout that raises self self.timer = get_hub().schedule_call_global( self.seconds, greenlet.getcurrent().throw, self) else: # regular timeout with user-provided exception self.timer = get_hub().schedule_call_global( self.seconds, greenlet.getcurrent().throw, self.exception) return self
def callMethodInEventLoop(func, *args, **kwargs): if not get_hub().running or getcurrent() is get_hub().greenlet: return func(*args, **kwargs) done = Event() def wrapper(): assert getcurrent() is get_hub().greenlet try: result = func(*args, **kwargs) done.send(result) except Exception as e: done.send_exception(e) clear_sys_exc_info() QTimer.singleShot(0, wrapper) return done.wait()
def verify_hub_empty(): from eventlet import hubs hub = hubs.get_hub() num_readers = len(hub.get_readers()) num_writers = len(hub.get_writers()) num_timers = hub.get_timers_count() assert num_readers == 0 and num_writers == 0, "Readers: %s Writers: %s" % (num_readers, num_writers)
def wait(self): """Wait until another coroutine calls :meth:`send`. Returns the value the other coroutine passed to :meth:`send`. >>> from eventlet import event >>> import eventlet >>> evt = event.Event() >>> def wait_on(): ... retval = evt.wait() ... print("waited for {0}".format(retval)) >>> _ = eventlet.spawn(wait_on) >>> evt.send('result') >>> eventlet.sleep(0) waited for result Returns immediately if the event has already occured. >>> evt.wait() 'result' """ current = greenlet.getcurrent() if self._result is NOT_USED: self._waiters.add(current) try: return hubs.get_hub().switch() finally: self._waiters.discard(current) if self._exc is not None: current.throw(*self._exc) return self._result
def __init__(self, context, socket_type): super(Socket, self).__init__(context, socket_type) self.__dict__['_eventlet_send_event'] = _BlockedThread() self.__dict__['_eventlet_recv_event'] = _BlockedThread() self.__dict__['_eventlet_send_lock'] = _QueueLock() self.__dict__['_eventlet_recv_lock'] = _QueueLock() def event(fd): # Some events arrived at the zmq socket. This may mean # there's a message that can be read or there's space for # a message to be written. send_wake = self._eventlet_send_event.wake() recv_wake = self._eventlet_recv_event.wake() if not send_wake and not recv_wake: # if no waiting send or recv thread was woken up, then # force the zmq socket's events to be processed to # avoid repeated wakeups _Socket_getsockopt(self, EVENTS) hub = hubs.get_hub() self.__dict__['_eventlet_listener'] = hub.add(hub.READ, self.getsockopt(FD), event, lambda _: None, lambda: None)
def test_debug_listeners(self): hubs.get_hub().set_debug_listeners(True) hubs.get_hub().set_debug_listeners(False)
def __init__(self): self._waiters = deque() self._count = 0 self._holder = None self._hub = hubs.get_hub()
def _start_send_exception(self): hubs.get_hub().schedule_call_global(0, self._do_send, self._exception_links.items(), self._exception_links)
def main(): patcher.monkey_patch() hubs.get_hub().debug_exceptions = False conffile = '/etc/swift/dispersion.conf' parser = OptionParser(usage=''' Usage: %%prog [options] [conf_file] [conf_file] defaults to %s'''.strip() % conffile) parser.add_option('-j', '--dump-json', action='store_true', default=False, help='dump dispersion report in json format') parser.add_option('-d', '--debug', action='store_true', default=False, help='print 404s to standard error') parser.add_option('-p', '--partitions', action='store_true', default=False, help='print missing partitions to standard error') parser.add_option('--container-only', action='store_true', default=False, help='Only run container report') parser.add_option('--object-only', action='store_true', default=False, help='Only run object report') parser.add_option('--insecure', action='store_true', default=False, help='Allow accessing insecure keystone server. ' 'The keystone\'s certificate will not be verified.') parser.add_option('-P', '--policy-name', dest='policy_name', help="Specify storage policy name") options, args = parser.parse_args() if args: conffile = args.pop(0) if options.debug: global debug debug = True c = ConfigParser() if not c.read(conffile): exit('Unable to read config file: %s' % conffile) conf = dict(c.items('dispersion')) if options.dump_json: conf['dump_json'] = 'yes' if options.object_only: conf['container_report'] = 'no' if options.container_only: conf['object_report'] = 'no' if options.insecure: conf['keystone_api_insecure'] = 'yes' if options.partitions: conf['partitions'] = 'yes' output = generate_report(conf, options.policy_name) if json_output: print(json.dumps(output))
def setUp(self): self.orig_hub = zmq.get_hub_name_from_instance(get_hub()) use_hub('selects')
def some_work(): hubs.get_hub().schedule_call_local(0, fire_timer)
def get_hub(*a, **kw): warnings.warn("eventlet.api.get_hub has moved to eventlet.hubs.get_hub", DeprecationWarning, stacklevel=2) return hubs.get_hub(*a, **kw)
def using_epoll_hub(_f): try: return 'epolls' in type(get_hub()).__module__ except Exception: return False
def using_kqueue_hub(_f): try: return 'kqueue' in type(get_hub()).__module__ except Exception: return False
from eventlet import event from eventlet.support import greenlets as greenlet from eventlet import hubs import eventlet evt = event.Event() def waiter(): print "about to wait." result = evt.wait() print 'waited for, ', result hub = hubs.get_hub() g = eventlet.spawn(waiter) eventlet.sleep(0) evt.send('I am a event') eventlet.sleep(0)
def test_local(self): lst = [1] api.spawn(hubs.get_hub().schedule_call_local, DELAY, lst.pop) api.sleep(0) api.sleep(DELAY * 2) assert lst == [1], lst
def get_greentlet_hub(cls): from gevent import get_hub return get_hub()
def using_pyevent(_f): from eventlet.hubs import get_hub return 'pyevent' in type(get_hub()).__module__
def _schedule_unlock(self): if self._event_unlock is None: self._event_unlock = get_hub().schedule_call_global( 0, self._unlock)
def requirement(_f): from eventlet.hubs import get_hub try: return 'Twisted' in type(get_hub()).__name__ except Exception: return False
def _spawn_n(seconds, func, args, kwargs): hub = hubs.get_hub() g = greenlet.greenlet(func, parent=hub.greenlet) t = hub.schedule_call_global(seconds, g.switch, *args, **kwargs) return t, g
def select(read_list, write_list, error_list, timeout=None): # error checking like this is required by the stdlib unit tests if timeout is not None: try: timeout = float(timeout) except ValueError: raise TypeError("Expected number for timeout") hub = get_hub() timers = [] current = getcurrent() assert hub.greenlet is not current, 'do not call blocking functions from the mainloop' ds = {} for r in read_list: ds[get_fileno(r)] = {'read': r} for w in write_list: ds.setdefault(get_fileno(w), {})['write'] = w for e in error_list: ds.setdefault(get_fileno(e), {})['error'] = e listeners = [] def on_read(d): original = ds[get_fileno(d)]['read'] current.switch(([original], [], [])) def on_write(d): original = ds[get_fileno(d)]['write'] current.switch(([], [original], [])) def on_error(d, _err=None): original = ds[get_fileno(d)]['error'] current.switch(([], [], [original])) def on_timeout2(): current.switch(([], [], [])) def on_timeout(): # ensure that BaseHub.run() has a chance to call self.wait() # at least once before timed out. otherwise the following code # can time out erroneously. # # s1, s2 = socket.socketpair() # print(select.select([], [s1], [], 0)) timers.append(hub.schedule_call_global(0, on_timeout2)) if timeout is not None: timers.append(hub.schedule_call_global(timeout, on_timeout)) try: for k, v in six.iteritems(ds): if v.get('read'): listeners.append( hub.add(hub.READ, k, on_read, on_error, lambda x: None)) if v.get('write'): listeners.append( hub.add(hub.WRITE, k, on_write, on_error, lambda x: None)) try: return hub.switch() finally: for l in listeners: hub.remove(l) finally: for t in timers: t.cancel()
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 test_threadlocal_context(self): hub = get_hub() context = zmq.Context() self.assertEqual(context, _threadlocal.context) next_context = hub.get_context() self.assertTrue(context is next_context)
def stop_application(): get_hub().abort()
def _start_send(self): hubs.get_hub().schedule_call_global(0, self._do_send, self._value_links.items(), self._value_links)
timer_count = 100000 if len(sys.argv) >= 2: timer_count = int(sys.argv[1]) l = [] def work(n): l.append(n) timeouts = [random.uniform(0, 10) for x in xrange(timer_count)] hub = get_hub() start = time.time() scheduled = [] for timeout in timeouts: t = timer.Timer(timeout, work, timeout) t.schedule() scheduled.append(t) hub.prepare_timers() hub.fire_timers(time.time() + 11) hub.prepare_timers()
def __init__(self): self._blocked_thread = None self._wakeupper = None self._hub = hubs.get_hub()
from eventlet.hubs import hub from eventlet.patcher import slurp_properties import sys import six __all__ = dir(builtins_orig) __patched__ = ['open'] if six.PY2: __patched__ += ['file'] slurp_properties(builtins_orig, globals(), ignore=__patched__, srckeys=dir(builtins_orig)) hubs.get_hub() if six.PY2: __original_file = file class file(__original_file): def __init__(self, *args, **kwargs): super(file, self).__init__(*args, **kwargs) hubs.notify_opened(self.fileno()) __original_open = open __opening = False def open(*args, **kwargs):
def upload(self, user, group, ipaddr, port, rootpath, fileinfo, logfile, timeout): jsonutils.schema_validate(fileinfo, FILEINFOSCHEMA) if timeout: timeout = int(timeout) if timeout > 7200: raise ValueError('Timeout over 7200 seconds') with goperation.tlock(self.executer): logfile = logfile or os.devnull executable = systemutils.find_executable(self.executer) token = str(uuidutils.generate_uuid()).replace('-', '') args = [ executable, '--home', rootpath, '--token', token, '--port', str(port) ] ext = fileinfo.get('ext') or os.path.splitext( fileinfo.get('filename'))[1][1:] if ext.startswith('.'): ext = ext[1:] if not ext: raise exceptions.PreWebSocketError('ext is empty') filename = '%s.%s' % (fileinfo.get('md5'), ext) self.output = os.path.join(rootpath, filename) # 判断文件是否存在 if os.path.exists(self.output): raise exceptions.PreWebSocketError('file exist with same name') self.size = fileinfo.get('size') # 准备文件目录 path = os.path.dirname(self.output) if not os.path.exists(path): os.makedirs(path, mode=0o775) if user or group: os.chown(path, user, group) else: if not os.path.isdir(path): raise exceptions.PreWebSocketError( 'prefix path is not dir') if not ext or ext == 'tmp': raise exceptions.PreWebSocketError( 'Can not find file ext or ext is tmp') # 临时文件名 self.tmp = os.path.join( rootpath, '%s.tmp' % str(uuidutils.generate_uuid()).replace('-', '')) args.extend(['--outfile', self.tmp]) args.extend(['--md5', fileinfo.get('md5')]) args.extend(['--size', str(fileinfo.get('size'))]) args.extend(['--log-file', logfile]) args.extend(['--loglevel', 'info']) changeuser = functools.partial(systemutils.drop_privileges, user, group) with open(os.devnull, 'wb') as f: LOG.debug('Websocket command %s %s' % (executable, ' '.join(args))) if systemutils.WINDOWS: sub = subprocess.Popen(executable=executable, args=args, stdout=f.fileno(), stderr=f.fileno(), close_fds=True, preexec_fn=changeuser) pid = sub.pid else: pid = safe_fork(user=user, group=group) if pid == 0: os.dup2(f.fileno(), sys.stdout.fileno()) os.dup2(f.fileno(), sys.stderr.fileno()) os.closerange(3, systemutils.MAXFD) try: os.execv(executable, args) except OSError: os._exit(1) LOG.info('Websocket recver start with pid %d' % pid) def _kill(): try: p = psutil.Process(pid=pid) name = p.name() except psutil.NoSuchProcess: return if name == self.executer: LOG.warning('Websocket recver overtime, kill it') p.kill() self.pid = pid hub = hubs.get_hub() self.timer = hub.schedule_call_global(timeout or 3600, _kill) return dict(port=port, token=token, ipaddr=ipaddr, filename=filename)
def acquire(self, blocking=True, timeout=None): """Acquire a semaphore. When invoked without arguments: if the internal counter is larger than zero on entry, decrement it by one and return immediately. If it is zero on entry, block, waiting until some other thread has called release() to make it larger than zero. This is done with proper interlocking so that if multiple acquire() calls are blocked, release() will wake exactly one of them up. The implementation may pick one at random, so the order in which blocked threads are awakened should not be relied on. There is no return value in this case. When invoked with blocking set to true, do the same thing as when called without arguments, and return true. When invoked with blocking set to false, do not block. If a call without an argument would block, return false immediately; otherwise, do the same thing as when called without arguments, and return true. Timeout value must be strictly positive. """ if timeout == -1: timeout = None # timeout 不为None时,必须大于0 if timeout is not None and timeout < 0: raise ValueError("timeout value must be strictly positive") # 非阻塞 不能设置 timeout if not blocking: if timeout is not None: raise ValueError("can't specify timeout for non-blocking acquire") timeout = 0 # 非阻塞 且 没有信号量时 return False # 当 设置为非阻塞式,且目前信号量计数为0时, 直接返回False if not blocking and self.locked(): return False current_thread = eventlet.getcurrent() # 如果 没有信号量, 或者 有等待的协程 if self.counter <= 0 or self._waiters: # 先放入等待队列 if current_thread not in self._waiters: self._waiters.append(current_thread) try: # 设置超时时间,就在超时时间内获取尝试被调度 if timeout is not None: ok = False with eventlet.Timeout(timeout, False): while self.counter <= 0: hubs.get_hub().switch() ok = True if not ok: return False # 没有设置超时时间就一直尝试被调度 else: # If someone else is already in this wait loop, give them # a chance to get out. while True: hubs.get_hub().switch() if self.counter > 0: break finally: try: self._waiters.remove(current_thread) except ValueError: # Fine if its already been dropped. pass # 获取信号量成功,计数减一 self.counter -= 1 return True
def test_gt(sem): try: raise KeyError() except KeyError: sem.release() hubs.get_hub().switch()
def test_timer_exceptions(self): hubs.get_hub().set_timer_exceptions(True) hubs.get_hub().set_timer_exceptions(False)
def test_global(self): lst = [1] eventlet.spawn(hubs.get_hub().schedule_call_global, DELAY, lst.pop) eventlet.sleep(0) eventlet.sleep(DELAY * 2) assert lst == [], lst
def get_greentlet_hub(cls): from eventlet.hubs import get_hub return get_hub()