+++ /dev/null
-__select = __import__('select')
-error = __select.error
-from eventlet.greenthread import getcurrent
-from eventlet.hubs import get_hub
-from eventlet.support import six
-
-
-__patched__ = ['select']
-
-
-def get_fileno(obj):
- # The purpose of this function is to exactly replicate
- # the behavior of the select module when confronted with
- # abnormal filenos; the details are extensively tested in
- # the stdlib test/test_select.py.
- try:
- f = obj.fileno
- except AttributeError:
- if not isinstance(obj, six.integer_types):
- raise TypeError("Expected int or long, got %s" % type(obj))
- return obj
- else:
- rv = f()
- if not isinstance(rv, six.integer_types):
- raise TypeError("Expected int or long, got %s" % type(rv))
- return rv
-
-
-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()