Skip to content

Commit

Permalink
got async input to work
Browse files Browse the repository at this point in the history
  • Loading branch information
benhoff committed Aug 30, 2015
1 parent be26a6d commit e99fb71
Showing 1 changed file with 21 additions and 80 deletions.
101 changes: 21 additions & 80 deletions vex/adapters/shell.py
Original file line number Diff line number Diff line change
@@ -1,94 +1,35 @@
import os
import sys
import asyncio
if sys.platform == 'win32'
from asyncio.windows_utils import Popen, PIPE
else:
from subprocess import Popen, PIPE
from asyncio.streams import StreamWriter, FlowControlMixin

from adapter import Adapter

class Shell(Adapter):
def __init__(self):
super(Shell, self).__init__()
self._writer = None
self._reader = None

def _stdio(self, loop=None):
if loop is None:
loop = asyncio.get_event_loop()
self._reader = asyncio.StreamReader()
reader_protocol = asyncio.StreamReaderProtocol(self._reader)
writer_transport, writer_protocol = yield from loop.connect_write_pipe(FlowControlMixin, os.fdopen(0, 'wb'))
self._writer = StreamWriter(writer_transport, writer_protocol, None, loop)
yield from loop.connect_read_pipe(lambda: reader_protocol, sys.stdin)

def send(self, message):
if self._writer is not None:
self._writer.write(message)

@asyncio.coroutine
def run(self, loop=None):
# TODO: Figure out how to get the shell that's already running
# instead of making a new one
code = r'''if 1:
import os
def writeall(fd, buf):
while buf:
n = os.write(fd, buf)
buf = buf[n:]
while True:
s = os.read(0, 1024)
if not s:
break
s = s.decode('ascii')
s = repr(eval(s)) + '\n'
s = s.encode('ascii')
writeall(1, s)
'''

commands = iter([b"1+1\n",
b"2**16\n",
b"1/3\n",
b"'x'*50",
b"1/0\n"])

p = Popen([sys.executable, '-c', code],
stdin=PIPE, stdout=PIPE, stderr=PIPE)

stdin = yield from self._connect_write_pipe(p.stdin)
stdout, stdout_transport = yield from self._connect_read_pipe(p.stdout)
stderr, stderr_transport = yield from self._connect_read_pipe(p.stderr)

name = {stdout: 'OUT', stderr: 'ERR'}
registered = {asyncio.Task(stderr.readline()): stderr,
asyncio.Task(stdout.readline()): stdout}

while registered:
cmd = next(commands, None)
if cmd is None:
stdin.close()
else:
print('>>>', cmd.decode('ascii').rstrip())
stdin.write(cmd)

timeout = None
while registered:
done, pending = yield from asyncio.wait(
registered, timeout=timeout,
return_when=asyncio.FIRST_COMPLETED)
if not done:
break
for f in done:
stream = registered.pop(f)
res = f.result()
print(name[stream], res.decode('ascii').rstrip())
if res != b'':
registered[asyncio.Task(stream.readline())] = stream

timeout = 0.0

stdout_transport.close()
stderr_transport.close()

@asyncio.coroutine
def _connect_read_pipe(self, file):
loop = asyncio.get_event_loop()
stream_reader = asyncio.StreamReader(loop=loop)
def factory():
return asyncio.StreamReaderProtocol(stream_reader)
transport, _= yield from loop.connect_read_pipe(factory, file)
return stream_reader, transport

@asyncio.coroutine
def _connect_write_pipe(self, file):
loop = asyncio.get_event_loop()
transport, _ = yield from loop.connect_write_pipe(asyncio.Protocol, file)
return transport
yield from self._stdio()
self._writer.write(b'>>>')
line = yield from self._reader.readline()
print(line.decode('ascii'))

if __name__ == '__main__':
shell = Shell()
Expand Down

0 comments on commit e99fb71

Please sign in to comment.