| Index: third_party/pexpect/pexpect/async.py
|
| diff --git a/third_party/pexpect/pexpect/async.py b/third_party/pexpect/pexpect/async.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ad759947232c51b492b57d99fa974aeeb60b82c9
|
| --- /dev/null
|
| +++ b/third_party/pexpect/pexpect/async.py
|
| @@ -0,0 +1,72 @@
|
| +import asyncio
|
| +import errno
|
| +
|
| +from pexpect import EOF
|
| +
|
| +@asyncio.coroutine
|
| +def expect_async(expecter, timeout=None):
|
| + # First process data that was previously read - if it maches, we don't need
|
| + # async stuff.
|
| + previously_read = expecter.spawn.buffer
|
| + expecter.spawn.buffer = expecter.spawn.string_type()
|
| + idx = expecter.new_data(previously_read)
|
| + if idx is not None:
|
| + return idx
|
| +
|
| + transport, pw = yield from asyncio.get_event_loop()\
|
| + .connect_read_pipe(lambda: PatternWaiter(expecter), expecter.spawn)
|
| +
|
| + try:
|
| + return (yield from asyncio.wait_for(pw.fut, timeout))
|
| + except asyncio.TimeoutError as e:
|
| + transport.pause_reading()
|
| + return expecter.timeout(e)
|
| +
|
| +class PatternWaiter(asyncio.Protocol):
|
| + def __init__(self, expecter):
|
| + self.expecter = expecter
|
| + self.fut = asyncio.Future()
|
| +
|
| + def found(self, result):
|
| + if not self.fut.done():
|
| + self.fut.set_result(result)
|
| +
|
| + def error(self, exc):
|
| + if not self.fut.done():
|
| + self.fut.set_exception(exc)
|
| +
|
| + def data_received(self, data):
|
| + spawn = self.expecter.spawn
|
| + s = spawn._decoder.decode(data)
|
| + spawn._log(s, 'read')
|
| +
|
| + if self.fut.done():
|
| + spawn.buffer += data
|
| + return
|
| +
|
| + try:
|
| + index = self.expecter.new_data(data)
|
| + if index is not None:
|
| + # Found a match
|
| + self.found(index)
|
| + except Exception as e:
|
| + self.expecter.errored()
|
| + self.error(e)
|
| +
|
| + def eof_received(self):
|
| + # N.B. If this gets called, async will close the pipe (the spawn object)
|
| + # for us
|
| + try:
|
| + self.expecter.spawn.flag_eof = True
|
| + index = self.expecter.eof()
|
| + except EOF as e:
|
| + self.error(e)
|
| + else:
|
| + self.found(index)
|
| +
|
| + def connection_lost(self, exc):
|
| + if isinstance(exc, OSError) and exc.errno == errno.EIO:
|
| + # We may get here without eof_received being called, e.g on Linux
|
| + self.eof_received()
|
| + elif exc is not None:
|
| + self.error(exc)
|
|
|