Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions pythonwhat/check_funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ def parse_tree(n):

return state

def has_expr(incorrect_msg="FMT:Unexpected expression {test}: expected `{sol_eval}`, got `{stu_eval}` with values{extra_env}.",
def has_expr(incorrect_msg="__JINJA__:Unexpected expression {{test}}: expected `{{sol_eval}}`, got `{{stu_eval}}`{{' with values ' + extra_env if extra_env}}.",
error_msg="Running an expression in the student process caused an issue.",
undefined_msg="FMT:Have you defined `{name}` without errors?",
extra_env=None,
Expand All @@ -451,6 +451,7 @@ def has_expr(incorrect_msg="FMT:Unexpected expression {test}: expected `{sol_eva
keep_objs_in_env=None,
name=None,
highlight=None,
copy=True,
state=None,
test=None):
"""Run student and solution code, compare returned value, printed output, or errors.
Expand Down Expand Up @@ -496,6 +497,7 @@ def has_expr(incorrect_msg="FMT:Unexpected expression {test}: expected `{sol_eva
expr_code = expr_code,
keep_objs_in_env = keep_objs_in_env,
name=name,
copy=copy,
do_exec = True if test == 'output' else False)

eval_sol, str_sol = get_func(tree = state.solution_tree,
Expand All @@ -515,7 +517,7 @@ def has_expr(incorrect_msg="FMT:Unexpected expression {test}: expected `{sol_eva
# kwargs ---
fmt_kwargs = {'stu_part': state.student_parts, 'sol_part': state.solution_parts,
'name': name, 'test': test,
'extra_env': " "+str(extra_env or ""), 'context_vals': context_vals}
'extra_env': str(extra_env) if extra_env else "", 'context_vals': context_vals}
fmt_kwargs['stu_eval'] = utils.shorten_str(str(eval_stu))
fmt_kwargs['sol_eval'] = utils.shorten_str(str(eval_sol))

Expand Down
31 changes: 20 additions & 11 deletions pythonwhat/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import pythonwhat
import ast
import inspect
import copy
from copy import deepcopy
from pickle import PicklingError
from pythonwhat.utils_env import set_context_vals, assign_from_ast
from contextlib import contextmanager
Expand Down Expand Up @@ -330,17 +330,10 @@ def get_error(f, *args, **kwargs):
def taskRunEval(tree,
process, shell,
keep_objs_in_env = None, extra_env = None, context=None, context_vals=None,
pre_code = "", expr_code = "", name="", tempname='_evaluation_object_', do_exec=False,
call=None):
new_env = utils.copy_env(get_env(shell.user_ns), keep_objs_in_env)
if extra_env is not None:
new_env.update(copy.deepcopy(extra_env))
if context is not None:
set_context_vals(new_env, context, context_vals)
pre_code = "", expr_code = "", name="", copy=True, tempname='_evaluation_object_',
do_exec=False, call=None):
try:
# Execute pre_code if specified
if pre_code: exec(pre_code, new_env)

# Prepare code --------------------------------------------------------
# If no name given, the object of interest is the output of eval
# otherwise, we'll use name to get the object from the environment
if not (name or do_exec):
Expand All @@ -353,6 +346,22 @@ def taskRunEval(tree,
if expr_code: code = expr_code
else: code = compile(tree, "<script>", mode)

# Set up environment --------------------------------------------------
# avoid deepy copy if specified, or just looking up variable by name
if not copy or (isinstance(tree, ast.Name) and isinstance(tree.ctx, ast.Load)):
new_env = dict(get_env(shell.user_ns))
else:
new_env = utils.copy_env(get_env(shell.user_ns), keep_objs_in_env)

if extra_env is not None:
new_env.update(deepcopy(extra_env))
if context is not None:
set_context_vals(new_env, context, context_vals)

# Execute code --------------------------------------------------------
# Run pre_code if specified
if pre_code: exec(pre_code, new_env)

if mode == 'eval':
obj = eval(code, new_env)
else:
Expand Down
14 changes: 14 additions & 0 deletions tests/test_test_expression_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,19 @@ def test_pass(self):
sct_payload = helper.run(self.data)
self.assertTrue(sct_payload['correct'])

def test_no_copy_bad_sct_passes(self):
self.data["DC_SOLUTION"] = "a = [2]"
self.data["DC_CODE"] = "a = [1]"
self.data["DC_SCT"] = "Ex().has_equal_value(expr_code = 'a[0] = 3', name = 'a', copy = False).has_equal_value(expr_code = 'a', name = 'a')"
sct_payload = helper.run(self.data)
self.assertTrue(sct_payload['correct'])

def test_copy_sct_fails(self):
self.data["DC_SOLUTION"] = "a = [2]"
self.data["DC_CODE"] = "a = [1]"
self.data["DC_SCT"] = "Ex().has_equal_value(expr_code = 'a[0] = 3', name = 'a', copy = True).has_equal_value(name = 'a')"
sct_payload = helper.run(self.data)
self.assertFalse(sct_payload['correct'])

if __name__ == "__main__":
unittest.main()