Skip to content

Commit 6b42205

Browse files
committed
Added instructions append for error handling and updated example.py, JinJa2 template, and regenerated test file.
1 parent 99ae47d commit 6b42205

File tree

4 files changed

+75
-38
lines changed

4 files changed

+75
-38
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Instructions append
2+
3+
## Exception messages
4+
5+
Sometimes it is necessary to [raise an exception](https://docs.python.org/3/tutorial/errors.html#raising-exceptions). When you do this, you should always include a **meaningful error message** to indicate what the source of the error is. This makes your code more readable and helps significantly with debugging. For situations where you know that the error source will be a certain type, you can choose to raise one of the [built in error types](https://docs.python.org/3/library/exceptions.html#base-classes), but should still include a meaningful message.
6+
7+
This particular exercise requires that you use the [raise statement](https://docs.python.org/3/reference/simple_stmts.html#the-raise-statement) to "throw" a `ValueError` if the question passed to `answer()` is malformed/invalid, or contains an unknown operation. The tests will only pass if you both `raise` the `exception` and include a message with it.
8+
9+
To raise a `ValueError` with a message, write the message as an argument to the `exception` type:
10+
11+
```python
12+
# if the question contains an unknown operation.
13+
raise ValueError("unknown operation")
14+
15+
# if the question is malformed or invalid.
16+
raise ValueError("syntax error")
17+
```
Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
1-
import sys
21
from operator import add, mul, sub
3-
4-
if sys.version_info[0] == 2:
5-
from operator import div
6-
else:
7-
from operator import floordiv as div
2+
from operator import floordiv as div
83

94

105
VALID_OPERATIONS = {"plus": add, "minus": sub,
116
"multiplied by": mul, "divided by": div}
127

138

149
def answer(question):
15-
if not (question.startswith("What is ") and question.endswith("?")):
16-
raise ValueError("Ill-formed question")
17-
words = question[8:-1].strip().lower().split()
18-
if not words:
19-
raise ValueError("Ill-formed question")
20-
words.reverse()
10+
if not bool(question[8:-1].strip().lower().split()):
11+
raise ValueError("syntax error")
12+
13+
elif not question.startswith("What is "):
14+
raise ValueError("unknown operation")
15+
16+
else:
17+
words = question[8:-1].strip().lower().split()
18+
words.reverse()
19+
2120
try:
2221
main_value = int(words.pop())
2322
except ValueError:
24-
raise ValueError("Ill-formed question")
23+
raise ValueError("syntax error")
24+
2525
while words:
2626
operation = [words.pop()]
2727
while words:
@@ -30,12 +30,21 @@ def answer(question):
3030
second_value = int(next_to_evaluate)
3131
break
3232
except ValueError:
33-
operation.append(next_to_evaluate)
33+
if next_to_evaluate == operation[-1]:
34+
raise ValueError("syntax error")
35+
else:
36+
operation.append(next_to_evaluate)
3437
else:
35-
raise ValueError("Ill-formed question")
38+
if operation[-1] not in VALID_OPERATIONS and not operation[-1].isdigit() :
39+
raise ValueError("unknown operation")
40+
else:
41+
raise ValueError("syntax error")
42+
3643
operation = " ".join(operation)
44+
3745
try:
3846
main_value = VALID_OPERATIONS[operation](main_value, second_value)
3947
except KeyError:
40-
raise ValueError("Ill-formed question")
48+
raise ValueError("unknown operation")
49+
4150
return main_value

exercises/practice/wordy/.meta/template.j2

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
def test_{{ case["description"] | to_snake }}(self):
44
{%- set question = case["input"]["question"] %}
55
{%- if case is error_case %}
6-
with self.assertRaisesWithMessage(ValueError):
6+
with self.assertRaises(ValueError) as err:
77
{{ case["property"] }}("{{ question }}")
8+
self.assertEqual(type(err.exception), ValueError)
9+
self.assertEqual(err.exception.args[0], "{{ case["expected"]["error"] }}")
810
{%- else %}
911
self.assertEqual({{ case["property"] }}("{{ question }}"), {{ case["expected"] }})
1012
{%- endif %}
@@ -23,6 +25,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase):
2325
{{ test_case(case) }}
2426
{% endfor %}
2527
{%- endif %}
26-
27-
28-
{{ macros.footer() }}

exercises/practice/wordy/wordy_test.py

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -54,51 +54,63 @@ def test_multiple_division(self):
5454
self.assertEqual(answer("What is -12 divided by 2 divided by -3?"), 2)
5555

5656
def test_unknown_operation(self):
57-
with self.assertRaisesWithMessage(ValueError):
57+
with self.assertRaises(ValueError) as err:
5858
answer("What is 52 cubed?")
59+
self.assertEqual(type(err.exception), ValueError)
60+
self.assertEqual(err.exception.args[0], "unknown operation")
5961

6062
def test_non_math_question(self):
61-
with self.assertRaisesWithMessage(ValueError):
63+
with self.assertRaises(ValueError) as err:
6264
answer("Who is the President of the United States?")
65+
self.assertEqual(type(err.exception), ValueError)
66+
self.assertEqual(err.exception.args[0], "unknown operation")
6367

6468
def test_reject_problem_missing_an_operand(self):
65-
with self.assertRaisesWithMessage(ValueError):
69+
with self.assertRaises(ValueError) as err:
6670
answer("What is 1 plus?")
71+
self.assertEqual(type(err.exception), ValueError)
72+
self.assertEqual(err.exception.args[0], "syntax error")
6773

6874
def test_reject_problem_with_no_operands_or_operators(self):
69-
with self.assertRaisesWithMessage(ValueError):
75+
with self.assertRaises(ValueError) as err:
7076
answer("What is?")
77+
self.assertEqual(type(err.exception), ValueError)
78+
self.assertEqual(err.exception.args[0], "syntax error")
7179

7280
def test_reject_two_operations_in_a_row(self):
73-
with self.assertRaisesWithMessage(ValueError):
81+
with self.assertRaises(ValueError) as err:
7482
answer("What is 1 plus plus 2?")
83+
self.assertEqual(type(err.exception), ValueError)
84+
self.assertEqual(err.exception.args[0], "syntax error")
7585

7686
def test_reject_two_numbers_in_a_row(self):
77-
with self.assertRaisesWithMessage(ValueError):
87+
with self.assertRaises(ValueError) as err:
7888
answer("What is 1 plus 2 1?")
89+
self.assertEqual(type(err.exception), ValueError)
90+
self.assertEqual(err.exception.args[0], "syntax error")
7991

8092
def test_reject_postfix_notation(self):
81-
with self.assertRaisesWithMessage(ValueError):
93+
with self.assertRaises(ValueError) as err:
8294
answer("What is 1 2 plus?")
95+
self.assertEqual(type(err.exception), ValueError)
96+
self.assertEqual(err.exception.args[0], "syntax error")
8397

8498
def test_reject_prefix_notation(self):
85-
with self.assertRaisesWithMessage(ValueError):
99+
with self.assertRaises(ValueError) as err:
86100
answer("What is plus 1 2?")
101+
self.assertEqual(type(err.exception), ValueError)
102+
self.assertEqual(err.exception.args[0], "syntax error")
87103

88104
# Additional tests for this track
89105

90106
def test_missing_operation(self):
91-
with self.assertRaisesWithMessage(ValueError):
107+
with self.assertRaises(ValueError) as err:
92108
answer("What is 2 2 minus 3?")
109+
self.assertEqual(type(err.exception), ValueError)
110+
self.assertEqual(err.exception.args[0], "unknown operation")
93111

94112
def test_missing_number(self):
95-
with self.assertRaisesWithMessage(ValueError):
113+
with self.assertRaises(ValueError) as err:
96114
answer("What is 7 plus multiplied by -2?")
97-
98-
# Utility functions
99-
def assertRaisesWithMessage(self, exception):
100-
return self.assertRaisesRegex(exception, r".+")
101-
102-
103-
if __name__ == "__main__":
104-
unittest.main()
115+
self.assertEqual(type(err.exception), ValueError)
116+
self.assertEqual(err.exception.args[0], "unknown operation")

0 commit comments

Comments
 (0)