# coding=utf-8 import threading import python.engine from db.models import Problem from . import problems __all__ = ['PythonSession'] class PythonSession(object): """Abstracts a Python session. Only public methods are available to the outside world due to the use of multiprocessing managers. Therefore prefix any private methods with an underscore (_). No properties are accessible; use getters and setters instead. Values are passed by value instead of by reference (deep copy!). """ def __init__(self): self._access_lock = threading.Lock() self._interpreter = None def create(self): with self._access_lock: if not self._interpreter: self._interpreter = python.engine.create() def pull(self): with self._access_lock: if self._interpreter is None: return 'Python is not running' return python.engine.pull(self._interpreter) def push(self, stdin): with self._access_lock: if self._interpreter is not None: python.engine.push(self._interpreter, stdin) def destroy(self): with self._access_lock: if self._interpreter is not None: python.engine.destroy(self._interpreter) self._interpreter = None def __del__(self): if hasattr(self, '_interpreter') and self._interpreter is not None: python.engine.destroy(self._interpreter) self._interpreter = None def hint(self, user_id, problem_id, program): language, problem_group, problem = Problem.identifier(problem_id) # Try problem-specific hints. problem_module = problems.load_problem(language, problem_group, problem, 'common') if hasattr(problem_module, 'hint'): hints = problem_module.hint(program) if hints: return hints # Finally return a generic "try thinking a bit" message. return [{'id': 'no_hint'}] def test(self, user_id, problem_id, program): language, problem_group, problem = Problem.identifier(problem_id) problem_module = problems.load_problem(language, problem_group, problem, 'common') try: n_correct, n_all = problem_module.test(program) return [{'id': 'test_results', 'args': {'passed': n_correct, 'total': n_all}}] except AttributeError as ex: return [{'id': 'test_results', 'args': {'passed': 0, 'total': 0}}]