Files
deb-python-eventlet/eventlet/green/select.py
Jakub Stasiak 614a20462a Remove select.poll and improve subprocess
green select: Delete unpatched poll once again

https://github.com/eventlet/eventlet/pull/317

Previously attempted in f63165c, had to be reverted in 8ea9df6 because
subprocess was failing after monkey patching.

Turns out we haven't been monkey patching the subprocess module at all,
this patch adds that in order for the tests to pass.

This part is changed because otherwise Popen class instantiation would
cause an infinite loop when monkey patching is applied:

    -subprocess_orig = __import__("subprocess")
    +subprocess_orig = patcher.original("subprocess")

This patch is contributed by Smarkets Limited.

* green subprocess: Provide green check_output

This patch is contributed by Smarkets Limited.
2016-05-20 13:23:36 +05:00

91 lines
2.8 KiB
Python

__select = __import__('select')
error = __select.error
from eventlet.greenthread import getcurrent
from eventlet.hubs import get_hub
from eventlet.support import six
__patched__ = ['select']
__deleted__ = ['devpoll', 'poll', 'epoll', 'kqueue', 'kevent']
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()