From 37ca6bf77ef3b4479d5c4d53a141e6466cdf6d90 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Thu, 14 Feb 2013 13:14:15 -0500 Subject: [PATCH] Move our specialization of safe_exec into a new module to avoid circular imports. --- common/lib/capa/capa/capa_problem.py | 54 +-------------------------- common/lib/capa/capa/responsetypes.py | 11 ++++-- common/lib/capa/capa/safe_exec.py | 20 ++++++++++ 3 files changed, 30 insertions(+), 55 deletions(-) create mode 100644 common/lib/capa/capa/safe_exec.py diff --git a/common/lib/capa/capa/capa_problem.py b/common/lib/capa/capa/capa_problem.py index 6973deb4a0..5518da8318 100644 --- a/common/lib/capa/capa/capa_problem.py +++ b/common/lib/capa/capa/capa_problem.py @@ -13,8 +13,6 @@ Main module which shows problems (of "capa" type). This is used by capa_module. ''' -from __future__ import division - from datetime import datetime import logging import math @@ -29,17 +27,6 @@ from lxml import etree from xml.sax.saxutils import unescape from copy import deepcopy -<<<<<<< HEAD -import chem -import chem.miller -import chem.chemcalc -import chem.chemtools -import verifiers -import verifiers.draganddrop - -import calc -======= ->>>>>>> Work in progress to sandbox the uses of eval in LMS. from .correctmap import CorrectMap import inputtypes import customrender @@ -48,8 +35,7 @@ import xqueue_interface # to be replaced with auto-registering import responsetypes - -from codejail.safe_exec import safe_exec +import safe_exec # dict of tagname, Response Class -- this should come from auto-registering response_tag_dict = dict([(x.response_tag, x) for x in responsetypes.__all__]) @@ -66,32 +52,6 @@ html_transforms = {'problem': {'tag': 'div'}, "math": {'tag': 'span'}, } -<<<<<<< HEAD -global_context = {'random': random, - 'numpy': numpy, - 'math': math, - 'scipy': scipy, - 'calc': calc, - 'eia': eia, - 'chemcalc': chem.chemcalc, - 'chemtools': chem.chemtools, - 'miller': chem.miller, - 'draganddrop': verifiers.draganddrop} -======= -safe_exec_assumed_imports = [ - "random", - "numpy", - "math", - "scipy", - "calc", - "eia", - ("chemcalc", "chem.chemcalc"), - ("chemtools", "chem.chemtools"), - ("miller", "chem.miller"), - ("draganddrop", "verifiers.draganddrop"), -] ->>>>>>> Work in progress to sandbox the uses of eval in LMS. - # These should be removed from HTML output, including all subelements html_problem_semantics = ["codeparam", "responseparam", "answer", "script", "hintgroup", "openendedparam", "openendedrubric"] @@ -479,16 +439,6 @@ class LoncapaProblem(object): ''' random.seed(self.seed) - # TODO: REMOVE THIS COMMENTED OUT CODE. - ## save global context in here also - #context = {'global_context': global_context} - # - ## initialize context to have stuff in global_context - #context.update(global_context) - # - # put globals there also - #context['__builtins__'] = globals()['__builtins__'] - context = {} # pass instance of LoncapaProblem in @@ -523,7 +473,7 @@ class LoncapaProblem(object): context['script_code'] += code try: # use "context" for global context; thus defs in code are global within code - safe_exec(code, context, future_division=True, assumed_imports=safe_exec_assumed_imports) + safe_exec.safe_exec(code, context) except Exception as err: log.exception("Error while execing script code: " + code) msg = "Error while executing script code: %s" % str(err).replace('<', '<') diff --git a/common/lib/capa/capa/responsetypes.py b/common/lib/capa/capa/responsetypes.py index f732c9fc84..1b40742419 100644 --- a/common/lib/capa/capa/responsetypes.py +++ b/common/lib/capa/capa/responsetypes.py @@ -37,7 +37,7 @@ from lxml import etree from lxml.html.soupparser import fromstring as fromstring_bs # uses Beautiful Soup!!! FIXME? import xqueue_interface -from codejail.safe_exec import safe_exec +import safe_exec log = logging.getLogger(__name__) @@ -971,6 +971,11 @@ def sympy_check2(): if cfn: log.debug("cfn = %s" % cfn) + # This is a bit twisty. We used to grab the cfn function from + # the context, but now that we sandbox Python execution, we + # can't get functions from previous executions. So we make an + # actual function that will re-execute the original script, + # and invoke the function with the data needed. def make_check_function(script_code, cfn): def check_function(expect, ans): code = (script_code + "\n" + @@ -979,7 +984,7 @@ def sympy_check2(): 'expect': expect, 'ans': ans, } - safe_exec(code, globals_dict) + safe_exec.safe_exec(code, globals_dict) return globals_dict['cfn_return'] return check_function @@ -1924,7 +1929,7 @@ class SchematicResponse(LoncapaResponse): json.loads(student_answers[k]) for k in sorted(self.answer_ids) ] self.context.update({'submission': submission}) - safe_exec(self.code, {}, self.context) + safe_exec.safe_exec(self.code, {}, self.context) cmap = CorrectMap() cmap.set_dict(dict(zip(sorted( self.answer_ids), self.context['correct']))) diff --git a/common/lib/capa/capa/safe_exec.py b/common/lib/capa/capa/safe_exec.py new file mode 100644 index 0000000000..0f57ece529 --- /dev/null +++ b/common/lib/capa/capa/safe_exec.py @@ -0,0 +1,20 @@ +"""Capa's specialized use of codejail.safe_exec.""" + +import codejail.safe_exec + +def safe_exec(code, globals_dict, locals_dict=None): + codejail.safe_exec.safe_exec( + code, globals_dict, locals_dict, future_division=True, + assumed_imports=[ + "random", + "numpy", + "math", + "scipy", + "calc", + "eia", + ("chemcalc", "chem.chemcalc"), + ("chemtools", "chem.chemtools"), + ("miller", "chem.miller"), + ("draganddrop", "verifiers.draganddrop"), + ], + )