forked from datacamp/pythonwhat
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcheck_function.py
More file actions
72 lines (61 loc) · 3.15 KB
/
check_function.py
File metadata and controls
72 lines (61 loc) · 3.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
from pythonwhat.Reporter import Reporter
from pythonwhat.check_funcs import part_to_child
from pythonwhat.test_funcs.test_function import bind_args
from pythonwhat.tasks import getSignatureInProcess
from pythonwhat.utils import get_ord
from pythonwhat.Test import Test
from pythonwhat.Feedback import Feedback
from pythonwhat.parsing import IndexedDict
from functools import partial
def bind_args(signature, args_part):
pos_args = []; kw_args = {}
for k, arg in args_part.items():
if isinstance(k, int): pos_args.append(arg)
else: kw_args[k] = arg
bound_args = signature.bind(*pos_args, **kw_args)
return (IndexedDict(bound_args.arguments), signature)
MSG_PREPEND = "__JINJA__:Check your code in the {{child['part']+ ' of the' if child['part']}} {{typestr}}. "
def check_function(name, index,
missing_msg = "FMT:Did you define the {typestr}?",
params_not_matched_msg = "FMT:Something went wrong in figuring out how you specified the "
"arguments for `{name}`; have another look at your code and its output.",
expand_msg = MSG_PREPEND,
signature=True,
typestr = "{ordinal} function call `{name}()`",
state=None):
rep = Reporter.active_reporter
stu_out = state.student_function_calls
sol_out = state.solution_function_calls
fmt_kwargs = {'ordinal': get_ord(index+1),
'index': index,
'name': name}
fmt_kwargs['typestr'] = typestr.format(**fmt_kwargs)
# Get Parts ----
try:
stu_parts = stu_out[name][index]
except (KeyError, IndexError):
_msg = state.build_message(missing_msg, fmt_kwargs)
rep.do_test(Test(Feedback(_msg, state.highlight)))
sol_parts = sol_out[name][index]
# Signatures -----
if signature:
signature = None if isinstance(signature, bool) else signature
get_sig = partial(getSignatureInProcess, name=name, signature=signature,
manual_sigs = state.get_manual_sigs())
try:
sol_sig = get_sig(mapped_name=sol_parts['name'], process=state.solution_process)
sol_parts['args'], _ = bind_args(sol_sig, sol_parts['args'])
except:
raise ValueError("Something went wrong in matching call index {index} of {name} to its signature. "
"You might have to manually specify or correct the signature."
.format(index=index, name=name))
try:
stu_sig = get_sig(mapped_name=stu_parts['name'], process=state.student_process)
stu_parts['args'], _ = bind_args(stu_sig, stu_parts['args'])
except Exception as e:
_msg = state.build_message(params_not_matched_msg, fmt_kwargs)
rep.do_test(Test(Feedback(_msg, stu_parts['node'])))
# three types of parts: pos_args, keywords, args (e.g. these are bound to sig)
append_message = {'msg': expand_msg, 'kwargs': fmt_kwargs}
child = part_to_child(stu_parts, sol_parts, append_message, state, node_name='function_calls')
return child