codekingpro/portable-devtools
114k
1import eventlet2from eventlet.hubs import get_hub3import six4__select = eventlet.patcher.original('select')5error = __select.error6 7 8__patched__ = ['select']9__deleted__ = ['devpoll', 'poll', 'epoll', 'kqueue', 'kevent']10 11 12def get_fileno(obj):13 # The purpose of this function is to exactly replicate14 # the behavior of the select module when confronted with15 # abnormal filenos; the details are extensively tested in16 # the stdlib test/test_select.py.17 try:18 f = obj.fileno19 except AttributeError:20 if not isinstance(obj, six.integer_types):21 raise TypeError("Expected int or long, got %s" % type(obj))22 return obj23 else:24 rv = f()25 if not isinstance(rv, six.integer_types):26 raise TypeError("Expected int or long, got %s" % type(rv))27 return rv28 29 30def select(read_list, write_list, error_list, timeout=None):31 # error checking like this is required by the stdlib unit tests32 if timeout is not None:33 try:34 timeout = float(timeout)35 except ValueError:36 raise TypeError("Expected number for timeout")37 hub = get_hub()38 timers = []39 current = eventlet.getcurrent()40 assert hub.greenlet is not current, 'do not call blocking functions from the mainloop'41 ds = {}42 for r in read_list:43 ds[get_fileno(r)] = {'read': r}44 for w in write_list:45 ds.setdefault(get_fileno(w), {})['write'] = w46 for e in error_list:47 ds.setdefault(get_fileno(e), {})['error'] = e48 49 listeners = []50 51 def on_read(d):52 original = ds[get_fileno(d)]['read']53 current.switch(([original], [], []))54 55 def on_write(d):56 original = ds[get_fileno(d)]['write']57 current.switch(([], [original], []))58 59 def on_timeout2():60 current.switch(([], [], []))61 62 def on_timeout():63 # ensure that BaseHub.run() has a chance to call self.wait()64 # at least once before timed out. otherwise the following code65 # can time out erroneously.66 #67 # s1, s2 = socket.socketpair()68 # print(select.select([], [s1], [], 0))69 timers.append(hub.schedule_call_global(0, on_timeout2))70 71 if timeout is not None:72 timers.append(hub.schedule_call_global(timeout, on_timeout))73 try:74 for k, v in six.iteritems(ds):75 if v.get('read'):76 listeners.append(hub.add(hub.READ, k, on_read, current.throw, lambda: None))77 if v.get('write'):78 listeners.append(hub.add(hub.WRITE, k, on_write, current.throw, lambda: None))79 try:80 return hub.switch()81 finally:82 for l in listeners:83 hub.remove(l)84 finally:85 for t in timers:86 t.cancel()87 