Update webpython.py
This commit is contained in:
@ -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'})
|
|
||||||
|
Reference in New Issue
Block a user