From 15f35dc1c2eb50a8140f1a0abf45d5aa25fdf66b Mon Sep 17 00:00:00 2001 From: Timotej Lazar Date: Tue, 22 Sep 2015 11:33:43 +0200 Subject: Add support for execing the user's Python program --- server/handlers.py | 24 +++++++++++++++++++++++- server/python_session.py | 15 ++++++++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) (limited to 'server') diff --git a/server/handlers.py b/server/handlers.py index 52a33f5..08994a0 100644 --- a/server/handlers.py +++ b/server/handlers.py @@ -106,7 +106,27 @@ class Query(CodeqService): request.reply(result) -# Push stdin to the session's Python interpreter. TODO: convert to async handling +# Push user program to the Python interpreter to be exec'd. +class PythonExec(CodeqService): + def process(self, request): + program = request.data.get('program') + if program is None: + request.reply({'code': 1, 'message': 'No program specified'}) + else: + python = request.session.get_python() + python.exec(program) + request.reply({'code': 0, 'message': 'ok'}) + + +# Send an interrupt to the Python interpreter. +class PythonStop(CodeqService): + def process(self, request): + python = request.session.get_python() + python.stop() + request.reply({'code': 0, 'message': 'ok'}) + + +# Push stdin to the Python interpreter. class PythonPush(CodeqService): def process(self, request): text = request.data.get('text') @@ -194,7 +214,9 @@ incoming_handlers = { 'logout': None, 'activity': Activity(), 'query': Query(), + 'python_exec': PythonExec(), 'python_push': PythonPush(), + 'python_stop': PythonStop(), 'hint': Hint(), 'test': Test() } diff --git a/server/python_session.py b/server/python_session.py index 62fcbf8..6f2c999 100644 --- a/server/python_session.py +++ b/server/python_session.py @@ -6,6 +6,7 @@ import io import multiprocessing import os import queue +import signal import subprocess import sys import threading @@ -55,9 +56,15 @@ class PythonSession(object): p.terminate() return results + def exec(self, program): + self._control.put_nowait(('exec', program)) + def push(self, stdin): self._control.put_nowait(('push', stdin)) + def stop(self): + self._control.put_nowait(('stop', None)) + def destroy(self): self._control.put_nowait(('done', None)) @@ -125,9 +132,15 @@ def _interpreter(control, callback): # Get a control command. try: cmd, data = control.get_nowait() - if cmd == 'push': + if cmd == 'exec': + exec_str = 'exec("""\\\n{}\n""")\n'.format(data.replace('"', '\\"')) + proc.stdin.write(exec_str.encode('utf-8')) + proc.stdin.flush() + elif cmd == 'push': proc.stdin.write(data.encode('utf-8')) proc.stdin.flush() + elif cmd == 'stop': + proc.send_signal(signal.SIGINT) elif cmd == 'done': break except: -- cgit v1.2.1