Skip to content

Commit 70ab866

Browse files
authored
Merge pull request #214 from datacamp/fix-has-expr-msg
Fix has expr msg to not always say "with values"
2 parents ac40f02 + 4cf1786 commit 70ab866

3 files changed

Lines changed: 38 additions & 13 deletions

File tree

pythonwhat/check_funcs.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ def parse_tree(n):
441441

442442
return state
443443

444-
def has_expr(incorrect_msg="FMT:Unexpected expression {test}: expected `{sol_eval}`, got `{stu_eval}` with values{extra_env}.",
444+
def has_expr(incorrect_msg="__JINJA__:Unexpected expression {{test}}: expected `{{sol_eval}}`, got `{{stu_eval}}`{{' with values ' + extra_env if extra_env}}.",
445445
error_msg="Running an expression in the student process caused an issue.",
446446
undefined_msg="FMT:Have you defined `{name}` without errors?",
447447
extra_env=None,
@@ -451,6 +451,7 @@ def has_expr(incorrect_msg="FMT:Unexpected expression {test}: expected `{sol_eva
451451
keep_objs_in_env=None,
452452
name=None,
453453
highlight=None,
454+
copy=True,
454455
state=None,
455456
test=None):
456457
"""Run student and solution code, compare returned value, printed output, or errors.
@@ -496,6 +497,7 @@ def has_expr(incorrect_msg="FMT:Unexpected expression {test}: expected `{sol_eva
496497
expr_code = expr_code,
497498
keep_objs_in_env = keep_objs_in_env,
498499
name=name,
500+
copy=copy,
499501
do_exec = True if test == 'output' else False)
500502

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

pythonwhat/tasks.py

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import pythonwhat
66
import ast
77
import inspect
8-
import copy
8+
from copy import deepcopy
99
from pickle import PicklingError
1010
from pythonwhat.utils_env import set_context_vals, assign_from_ast
1111
from contextlib import contextmanager
@@ -330,17 +330,10 @@ def get_error(f, *args, **kwargs):
330330
def taskRunEval(tree,
331331
process, shell,
332332
keep_objs_in_env = None, extra_env = None, context=None, context_vals=None,
333-
pre_code = "", expr_code = "", name="", tempname='_evaluation_object_', do_exec=False,
334-
call=None):
335-
new_env = utils.copy_env(get_env(shell.user_ns), keep_objs_in_env)
336-
if extra_env is not None:
337-
new_env.update(copy.deepcopy(extra_env))
338-
if context is not None:
339-
set_context_vals(new_env, context, context_vals)
333+
pre_code = "", expr_code = "", name="", copy=True, tempname='_evaluation_object_',
334+
do_exec=False, call=None):
340335
try:
341-
# Execute pre_code if specified
342-
if pre_code: exec(pre_code, new_env)
343-
336+
# Prepare code --------------------------------------------------------
344337
# If no name given, the object of interest is the output of eval
345338
# otherwise, we'll use name to get the object from the environment
346339
if not (name or do_exec):
@@ -353,6 +346,22 @@ def taskRunEval(tree,
353346
if expr_code: code = expr_code
354347
else: code = compile(tree, "<script>", mode)
355348

349+
# Set up environment --------------------------------------------------
350+
# avoid deepy copy if specified, or just looking up variable by name
351+
if not copy or (isinstance(tree, ast.Name) and isinstance(tree.ctx, ast.Load)):
352+
new_env = dict(get_env(shell.user_ns))
353+
else:
354+
new_env = utils.copy_env(get_env(shell.user_ns), keep_objs_in_env)
355+
356+
if extra_env is not None:
357+
new_env.update(deepcopy(extra_env))
358+
if context is not None:
359+
set_context_vals(new_env, context, context_vals)
360+
361+
# Execute code --------------------------------------------------------
362+
# Run pre_code if specified
363+
if pre_code: exec(pre_code, new_env)
364+
356365
if mode == 'eval':
357366
obj = eval(code, new_env)
358367
else:

tests/test_test_expression_result.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,19 @@ def test_pass(self):
2121
sct_payload = helper.run(self.data)
2222
self.assertTrue(sct_payload['correct'])
2323

24+
def test_no_copy_bad_sct_passes(self):
25+
self.data["DC_SOLUTION"] = "a = [2]"
26+
self.data["DC_CODE"] = "a = [1]"
27+
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')"
28+
sct_payload = helper.run(self.data)
29+
self.assertTrue(sct_payload['correct'])
30+
31+
def test_copy_sct_fails(self):
32+
self.data["DC_SOLUTION"] = "a = [2]"
33+
self.data["DC_CODE"] = "a = [1]"
34+
self.data["DC_SCT"] = "Ex().has_equal_value(expr_code = 'a[0] = 3', name = 'a', copy = True).has_equal_value(name = 'a')"
35+
sct_payload = helper.run(self.data)
36+
self.assertFalse(sct_payload['correct'])
37+
2438
if __name__ == "__main__":
2539
unittest.main()

0 commit comments

Comments
 (0)