Skip to content

Commit b660541

Browse files
committed
Improve state creation to work better with has_code after check_file
- init more similar to protowhat State init - cleaner to_child code
1 parent e39c51e commit b660541

File tree

2 files changed

+89
-34
lines changed

2 files changed

+89
-34
lines changed

pythonwhat/State.py

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,11 @@ def __init__(
8686

8787
self.ast_dispatcher = self.get_dispatcher()
8888

89-
# parse code if didn't happen yet
90-
if student_ast is None:
89+
# Parse solution and student code
90+
# if possible, not done yet and wanted (ast arguments not False)
91+
if isinstance(self.student_code, str) and student_ast is None:
9192
self.student_ast = self.parse(student_code)
92-
if solution_ast is None:
93+
if isinstance(self.solution_code, str) and solution_ast is None:
9394
self.solution_ast = self.parse(solution_code, test=False)
9495

9596
if highlight is None: # todo: check parent_state? (move check to reporting?)
@@ -123,41 +124,36 @@ def to_child(self, append_message="", node_name="", **kwargs):
123124

124125
kwargs["messages"] = [*self.messages, append_message]
125126

126-
for kwarg in ["solution_context", "student_context"]:
127-
if kwarg in kwargs and not kwargs[kwarg]:
128-
kwargs.pop(kwarg, None)
129-
130127
def update_kwarg(name, func):
131128
kwargs[name] = func(kwargs[name])
132129

133130
def update_context(name):
134131
update_kwarg(name, getattr(self, name).update_ctx)
135132

136-
if isinstance(kwargs.get("student_ast", None), list):
137-
update_kwarg("student_ast", wrap_in_module)
138-
if isinstance(kwargs.get("solution_ast", None), list):
139-
update_kwarg("solution_ast", wrap_in_module)
133+
for ast_arg in ["student_ast", "solution_ast"]:
134+
if isinstance(kwargs.get(ast_arg), list):
135+
update_kwarg(ast_arg, wrap_in_module)
140136

141-
if "student_ast" in kwargs:
137+
if kwargs.get("student_ast") and kwargs.get("student_code") is None:
142138
kwargs["student_code"] = self.student_ast_tokens.get_text(
143139
kwargs["student_ast"]
144140
)
145-
if "solution_ast" in kwargs:
141+
if kwargs.get("solution_ast") and kwargs.get("solution_code") is None:
146142
kwargs["solution_code"] = self.solution_ast_tokens.get_text(
147143
kwargs["solution_ast"]
148144
)
149145

150-
# get new contexts
151-
if "solution_context" in kwargs:
152-
update_context("solution_context")
153-
if "student_context" in kwargs:
154-
update_context("student_context")
155-
156-
# get new envs
157-
if "solution_env" in kwargs:
158-
update_context("solution_env")
159-
if "student_env" in kwargs:
160-
update_context("student_env")
146+
for context in [
147+
"student_context",
148+
"solution_context",
149+
"student_env",
150+
"solution_env",
151+
]:
152+
if context in kwargs:
153+
if kwargs[context] is not None:
154+
update_context(context)
155+
else:
156+
kwargs.pop(context)
161157

162158
klass = self.SUBCLASSES[node_name] if node_name else State
163159
child = klass(**{**base_kwargs, **kwargs})

tests/test_check_files.py

Lines changed: 69 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,81 @@
88
from protowhat.checks import check_files as cf
99

1010

11-
@pytest.fixture(scope="function")
12-
def tf():
11+
@pytest.fixture
12+
def temp_py_file():
1313
with NamedTemporaryFile() as tmp:
14-
tmp.file.write(b"1 + 1")
14+
tmp.file.write(
15+
b"""
16+
if True:
17+
a = 1"""
18+
)
1519
tmp.file.flush()
1620
yield tmp
1721

1822

19-
def test_file_existence(tf):
20-
s = setup_state("", "", pec="")
23+
@pytest.fixture
24+
def temp_txt_file():
25+
with NamedTemporaryFile() as tmp:
26+
tmp.file.write(b"this is a text file")
27+
tmp.file.flush()
28+
yield tmp
29+
30+
31+
@pytest.fixture(params=["temp_py_file", "temp_txt_file"])
32+
def temp_file(request):
33+
return request.getfuncargvalue(request.param)
34+
35+
36+
def test_python_file_existence(temp_py_file):
37+
expected_content = cf.get_file_content(temp_py_file.name)
38+
chain = setup_state("", "", pec="")
39+
40+
# test with just student content
41+
child = cf.check_file(chain._state, temp_py_file.name)
42+
assert expected_content in child.student_code
43+
assert child.student_ast is not None
44+
assert child.solution_code is None
45+
assert child.solution_ast is None
2146

22-
child = cf.check_file(s._state, tf.name)
23-
assert "1 + 1" in child.student_code
47+
# test with solution content
48+
child = cf.check_file(
49+
chain._state, temp_py_file.name, solution_code=expected_content
50+
)
51+
assert expected_content in child.student_code
52+
assert child.student_ast is not None
53+
assert expected_content in child.solution_code
54+
assert child.solution_ast is not None
2455

25-
file_chain = s.check_file(tf.name)
26-
assert "1 + 1" in file_chain._state.student_code
56+
57+
def test_file_existence_syntax(temp_py_file):
58+
"""test integration of protowhat checks in pythonwhat"""
59+
expected_content = cf.get_file_content(temp_py_file.name)
60+
chain = setup_state("", "", pec="")
61+
62+
file_chain = chain.check_file(temp_py_file.name)
63+
assert expected_content in file_chain._state.student_code
2764

2865
with helper.verify_sct(True):
29-
s >> F(attr_scts={"check_file": cf.check_file}).check_file(tf.name)
66+
file_chain = chain >> F(attr_scts={"check_file": cf.check_file}).check_file(
67+
temp_py_file.name
68+
)
69+
assert expected_content in file_chain._state.student_code
70+
71+
72+
def test_file_parsing(temp_py_file):
73+
expected_content = cf.get_file_content(temp_py_file.name)
74+
chain = setup_state("", "", pec="")
75+
76+
file_chain = chain.check_file(temp_py_file.name, solution_code=expected_content)
77+
file_chain.check_if_else().check_test().has_equal_value()
78+
file_chain.check_if_else().check_test().has_equal_value(expr_code="False")
79+
80+
81+
def test_file_content(temp_file):
82+
expected_content = cf.get_file_content(temp_file.name)
83+
chain = setup_state("", "", pec="")
84+
85+
chain.check_file(temp_file.name, parse=False).has_code(expected_content)
86+
chain.check_file(
87+
temp_file.name, parse=False, solution_code=expected_content
88+
).has_code(expected_content)

0 commit comments

Comments
 (0)