Update webpython.py

This commit is contained in:
tstaubitz
2015-10-16 15:58:38 +02:00
parent c6c958fca1
commit 5b5a5bf311

View File

@ -1,178 +1 @@
#!/usr/bin/python3 # moved to dockerfiles/ubuntu-python/webpython.py
# Main interpreter entry for webpython
import io, select, sys, os, threading, code
import pickle, struct, builtins, json
#, ressource
from queue import Queue
from argparse import ArgumentParser
# hard limit to 64M
#try:
# resource.setrlimit(resource.RLIMIT_AS, (1<<26, 1<<26))
#except ValueError:
# tried to raise it
# pass
# output limit 16MiB
output_capacity = 16*1024*1024
# adapted from IDLE (PyShell.py)
class PseudoFile(io.TextIOBase):
def __init__(self, shell, name):
self.shell = shell
self._name = name
@property
def encoding(self):
return "UTF-8"
@property
def name(self):
return '<%s>' % self._name
def isatty(self):
return True
class PseudoInputFile(PseudoFile):
def __init__(self, shell, name):
PseudoFile.__init__(self, shell, name)
self._line_buffer = ''
def readable(self):
return True
def read(self, size=-1):
if self.closed:
raise ValueError("read from closed file")
if size is None:
size = -1
elif not isinstance(size, int):
raise TypeError('must be int, not ' + type(size).__name__)
result = self._line_buffer
self._line_buffer = ''
if size < 0:
while True:
line = self.shell.readline()
if not line: break
result += line
else:
while len(result) < size:
line = self.shell.readline()
if not line: break
result += line
self._line_buffer = result[size:]
result = result[:size]
return result
def readline(self, size=-1):
if self.closed:
raise ValueError("read from closed file")
if size is None:
size = -1
elif not isinstance(size, int):
raise TypeError('must be int, not ' + type(size).__name__)
line = self._line_buffer or self.shell.readline()
if size < 0:
size = len(line)
self._line_buffer = line[size:]
return line[:size]
def close(self):
self.shell.close()
class PseudoOutputFile(PseudoFile):
def writable(self):
return True
def write(self, s):
if self.closed:
raise ValueError("write to closed file")
if not isinstance(s, str):
raise TypeError('must be str, not ' + type(s).__name__)
return self.shell.write(s, self._name)
# RPC proxy
orig_stdin = sys.stdin
orig_stdout = sys.stdout
orig_stderr = sys.stderr
class Shell:
def __init__(self):
self.stdin = io.FileIO(0)
self.buf = b''
self.canvas = []
self.messages = []
self.capacity = output_capacity
# PseudoFile interaction
#def readline(self):
# self.sendpickle({'cmd':'readline',
# 'stream':'stdin',
# })
# return self.inputq.get()
def write(self, data, name):
self.sendpickle({'cmd':'write',
'stream':name,
'data':data
})
def input(self, prompt=''):
self.sendpickle({'cmd':'input',
'stream':'stdin',
'data':prompt})
result = self.receivemsg()
return result['data']
# internal
def sendpickle(self, data):
data = json.dumps(data) + "\n\r"
self.capacity -= len(data)
if self.capacity < 0:
data = json.dumps({'cmd':'stop',
'timedout':True}, 2)
orig_stdout.write(data)
raise SystemExit
orig_stdout.write(data)
def receivepickle(self):
msg = json.loads(orig_stdin.readline())
if msg['cmd'] == 'canvasevent':
self.canvas.append(msg)
else:
self.messages.append(msg)
def receivemsg(self):
while not self.messages:
self.receivepickle()
return self.messages.pop()
def receivecanvas(self):
while not self.canvas:
self.receivepickle()
return self.canvas.pop(0)
# Hide 0/1 from sys
shell = Shell()
sys.__stdin__ = sys.stdin = PseudoInputFile(shell, 'stdin')
sys.__stdout__ = sys.stdout = PseudoOutputFile(shell, 'stdout')
#sys.__stderr__ = sys.stderr = PseudoOutputFile(shell, 'stderr')
builtins.input = shell.input
#iothread = threading.Thread(target=shell.run)
#iothread.start()
if __name__ == '__main__':
parser = ArgumentParser(description='A python interpreter that generates json commands based on the standard I/O streams.')
parser.add_argument('-f', '--filename', type=str, required=True, default='exercise.py', help='Python file to be interpreted.')
args = parser.parse_args()
filepath = os.path.join("/", "workspace", args.filename)
with open(filepath, "r", encoding='utf-8') as f:
script = f.read()
c = compile(script, args.filename, 'exec')
exec(c, {})
# work-around for docker not terminating properly
shell.sendpickle({'cmd':'exit'})