issue #408: 2.4 compat: replace iter_read with explicit generator

Can't use yield inside try/finally on 2.4.
issue510
David Wilson 6 years ago
parent 41626b82dd
commit 51ac309647

@ -505,6 +505,48 @@ def write_all(fd, s, deadline=None):
poller.close() poller.close()
class IteratingRead(object):
def __init__(self, fds, deadline=None):
self.deadline = deadline
self.poller = PREFERRED_POLLER()
for fd in fds:
self.poller.start_receive(fd)
self.bits = []
self.timeout = None
def close(self):
self.poller.close()
def __iter__(self):
return self
def next(self):
while self.poller.readers:
if self.deadline is not None:
timeout = max(0, self.deadline - time.time())
if timeout == 0:
break
for fd in self.poller.poll(timeout):
s, disconnected = mitogen.core.io_op(os.read, fd, 4096)
if disconnected or not s:
IOLOG.debug('iter_read(%r) -> disconnected', fd)
self.poller.stop_receive(fd)
else:
IOLOG.debug('iter_read(%r) -> %r', fd, s)
self.bits.append(s)
return s
if not poller.readers:
raise EofError(u'EOF on stream; last 300 bytes received: %r' %
(b('').join(self.bits)[-300:].decode('latin1'),))
raise mitogen.core.TimeoutError('read timed out')
__next__ = next
def iter_read(fds, deadline=None): def iter_read(fds, deadline=None):
"""Return a generator that arranges for up to 4096-byte chunks to be read """Return a generator that arranges for up to 4096-byte chunks to be read
at a time from the file descriptor `fd` until the generator is destroyed. at a time from the file descriptor `fd` until the generator is destroyed.
@ -522,36 +564,7 @@ def iter_read(fds, deadline=None):
:raises mitogen.core.StreamError: :raises mitogen.core.StreamError:
Attempt to read past end of file. Attempt to read past end of file.
""" """
poller = PREFERRED_POLLER() return IteratingRead(fds=fds, deadline=deadline)
for fd in fds:
poller.start_receive(fd)
bits = []
timeout = None
try:
while poller.readers:
if deadline is not None:
timeout = max(0, deadline - time.time())
if timeout == 0:
break
for fd in poller.poll(timeout):
s, disconnected = mitogen.core.io_op(os.read, fd, 4096)
if disconnected or not s:
IOLOG.debug('iter_read(%r) -> disconnected', fd)
poller.stop_receive(fd)
else:
IOLOG.debug('iter_read(%r) -> %r', fd, s)
bits.append(s)
yield s
finally:
poller.close()
if not poller.readers:
raise EofError(u'EOF on stream; last 300 bytes received: %r' %
(b('').join(bits)[-300:].decode('latin1'),))
raise mitogen.core.TimeoutError('read timed out')
def discard_until(fd, s, deadline): def discard_until(fd, s, deadline):

Loading…
Cancel
Save