how to make a calculator: tests and solutions
how to make a calculator 1: tests
the code from calculator/tests/test_calculator.py from how to make a calculator
1import random
2import src.calculator
3import unittest
4
5
6def a_random_number():
7 return random.triangular(-1000.0, 1000.0)
8
9
10class TestCalculator(unittest.TestCase):
11
12 random_first_number = a_random_number()
13 random_second_number = a_random_number()
14
15 def test_addition(self):
16 self.assertEqual(
17 src.calculator.add(
18 self.random_first_number,
19 self.random_second_number
20 ),
21 self.random_first_number+self.random_second_number
22 )
23
24 def test_subtraction(self):
25 self.assertEqual(
26 src.calculator.subtract(
27 self.random_first_number,
28 self.random_second_number
29 ),
30 self.random_first_number-self.random_second_number
31 )
32
33 def test_multiplication(self):
34 self.assertEqual(
35 src.calculator.multiply(
36 self.random_first_number,
37 self.random_second_number
38 ),
39 self.random_first_number*self.random_second_number
40 )
41
42 def test_division(self):
43 self.assertEqual(
44 src.calculator.divide(
45 self.random_first_number,
46 self.random_second_number
47 ),
48 self.random_first_number/self.random_second_number
49 )
50
51
52# Exceptions seen
53# AssertionError
54# NameError
55# AttributeError
56# TypeError
how to make a calculator 1: solutions
the solutions in calculator/src/calculator.py from how to make a calculator
1def add(first_input, second_input):
2 return first_input + second_input
3
4
5def subtract(first_input, second_input):
6 return first_input - second_input
7
8
9def multiply(first_input, second_input):
10 return first_input * second_input
11
12
13def divide(first_input, second_input):
14 return first_input / second_input
how to make a calculator 2: tests
the code from calculator/tests/test_calculator.py from how to make a calculator 2
1import random
2import src.calculator
3import unittest
4
5
6def a_random_number():
7 return random.triangular(-1000.0, 1000.0)
8
9
10class TestCalculator(unittest.TestCase):
11
12 random_first_number = a_random_number()
13 random_second_number = a_random_number()
14
15 def test_addition(self):
16 self.assertEqual(
17 src.calculator.add(
18 self.random_first_number,
19 self.random_second_number
20 ),
21 self.random_first_number+self.random_second_number
22 )
23
24 def test_subtraction(self):
25 self.assertEqual(
26 src.calculator.subtract(
27 self.random_first_number,
28 self.random_second_number
29 ),
30 self.random_first_number-self.random_second_number
31 )
32
33 def test_multiplication(self):
34 self.assertEqual(
35 src.calculator.multiply(
36 self.random_first_number,
37 self.random_second_number
38 ),
39 self.random_first_number*self.random_second_number
40 )
41
42 def test_division(self):
43 self.assertEqual(
44 src.calculator.divide(
45 self.random_first_number,
46 self.random_second_number
47 ),
48 self.random_first_number/self.random_second_number
49 )
50 with self.assertRaises(ZeroDivisionError):
51 src.calculator.divide(self.random_first_number, 0)
52
53
54# Exceptions seen
55# AssertionError
56# NameError
57# AttributeError
58# TypeError
how to make a calculator 3: tests
the code from calculator/tests/test_calculator.py from how to make a calculator 3
1import random
2import src.calculator
3import unittest
4
5
6def a_random_number():
7 return random.triangular(-1000.0, 1000.0)
8
9
10class TestCalculator(unittest.TestCase):
11
12 random_first_number = a_random_number()
13 random_second_number = a_random_number()
14
15 def test_addition(self):
16 self.assertEqual(
17 src.calculator.add(
18 self.random_first_number,
19 self.random_second_number
20 ),
21 self.random_first_number+self.random_second_number
22 )
23
24 def test_subtraction(self):
25 self.assertEqual(
26 src.calculator.subtract(
27 self.random_first_number,
28 self.random_second_number
29 ),
30 self.random_first_number-self.random_second_number
31 )
32
33 def test_multiplication(self):
34 self.assertEqual(
35 src.calculator.multiply(
36 self.random_first_number,
37 self.random_second_number
38 ),
39 self.random_first_number*self.random_second_number
40 )
41
42 def test_division(self):
43 try:
44 self.assertEqual(
45 src.calculator.divide(
46 self.random_first_number,
47 self.random_second_number
48 ),
49 self.random_first_number/self.random_second_number
50 )
51 except ZeroDivisionError:
52 self.assertEqual(
53 src.calculator.divide(self.random_first_number, 0),
54 'brmph?! I cannot divide by 0. Try again...'
55 )
56
57
58# Exceptions seen
59# AssertionError
60# NameError
61# AttributeError
62# TypeError
how to make a calculator 3: solutions
the solutions in calculator/src/calculator.py from how to make a calculator 3
1def subtract(first_input, second_input):
2 return first_input - second_input
3
4
5def multiply(first_input, second_input):
6 return first_input * second_input
7
8
9def divide(first_input, second_input):
10 try:
11 return first_input / second_input
12 except ZeroDivisionError:
13 return 'brmph?! I cannot divide by 0. Try again...'
14
15
16def add(first_input, second_input):
17 return first_input + second_input
how to make a calculator 4: tests
the code from calculator/tests/test_calculator.py from how to make a calculator 4
1import random
2import src.calculator
3import unittest
4
5
6def a_random_number():
7 return random.triangular(-1000.0, 1000.0)
8
9
10class TestCalculator(unittest.TestCase):
11
12 random_first_number = a_random_number()
13 random_second_number = a_random_number()
14
15 def test_addition(self):
16 self.assertEqual(
17 src.calculator.add(
18 self.random_first_number,
19 self.random_second_number
20 ),
21 self.random_first_number+self.random_second_number
22 )
23
24 def test_subtraction(self):
25 self.assertEqual(
26 src.calculator.subtract(
27 self.random_first_number,
28 self.random_second_number
29 ),
30 self.random_first_number-self.random_second_number
31 )
32
33 def test_multiplication(self):
34 self.assertEqual(
35 src.calculator.multiply(
36 self.random_first_number,
37 self.random_second_number
38 ),
39 self.random_first_number*self.random_second_number
40 )
41
42 def test_division(self):
43 try:
44 self.assertEqual(
45 src.calculator.divide(
46 self.random_first_number,
47 self.random_second_number
48 ),
49 self.random_first_number/self.random_second_number
50 )
51 except ZeroDivisionError:
52 self.assertEqual(
53 src.calculator.divide(self.random_first_number, 0),
54 'brmph?! I cannot divide by 0. Try again...'
55 )
56
57 def test_calculator_sends_message_when_input_is_not_a_number(self):
58 error_message = 'brmph?! Numbers only. Try again...'
59
60 self.assertEqual(
61 src.calculator.add(None, None),
62 error_message
63 )
64 self.assertEqual(
65 src.calculator.divide(None, None),
66 error_message
67 )
68 self.assertEqual(
69 src.calculator.multiply(None, None),
70 error_message
71 )
72 self.assertEqual(
73 src.calculator.subtract(None, None),
74 error_message
75 )
76 self.assertEqual(
77 src.calculator.add('1', '1'),
78 error_message
79 )
80 self.assertEqual(
81 src.calculator.divide('1', '1'),
82 error_message
83 )
84 self.assertEqual(
85 src.calculator.multiply('1', '1'),
86 error_message
87 )
88 self.assertEqual(
89 src.calculator.subtract('1', '1'),
90 error_message
91 )
92
93
94# Exceptions seen
95# AssertionError
96# NameError
97# AttributeError
98# TypeError
how to make a calculator 4: solutions
the solutions in calculator/src/calculator.py from how to make a calculator 4
1def numbers_only(function):
2 def decorator(first_input, second_input):
3 error_message = 'brmph?! Numbers only. Try again...'
4 if first_input is None or second_input is None:
5 return error_message
6 else:
7 try:
8 return function(first_input, second_input)
9 except TypeError:
10 return error_message
11 return decorator
12
13
14@numbers_only
15def subtract(first_input, second_input):
16 return first_input - second_input
17
18
19@numbers_only
20def multiply(first_input, second_input):
21 return first_input * second_input
22
23
24@numbers_only
25def divide(first_input, second_input):
26 try:
27 return first_input / second_input
28 except ZeroDivisionError:
29 return 'brmph?! I cannot divide by 0. Try again...'
30
31
32@numbers_only
33def add(first_input, second_input):
34 if (
35 isinstance(first_input, str)
36 or
37 isinstance(second_input, str)
38 ):
39 return 'brmph?! Numbers only. Try again...'
40 else:
41 return first_input + second_input
how to make a calculator 5: tests
the code from calculator/tests/test_calculator.py from how to make a calculator 5
1import random
2import src.calculator
3import unittest
4
5
6def a_random_number():
7 return random.triangular(-1000.0, 1000.0)
8
9
10class TestCalculator(unittest.TestCase):
11
12 random_first_number = a_random_number()
13 random_second_number = a_random_number()
14
15 def test_addition(self):
16 self.assertEqual(
17 src.calculator.add(
18 self.random_first_number,
19 self.random_second_number
20 ),
21 self.random_first_number+self.random_second_number
22 )
23
24 def test_subtraction(self):
25 self.assertEqual(
26 src.calculator.subtract(
27 self.random_first_number,
28 self.random_second_number
29 ),
30 self.random_first_number-self.random_second_number
31 )
32
33 def test_multiplication(self):
34 self.assertEqual(
35 src.calculator.multiply(
36 self.random_first_number,
37 self.random_second_number
38 ),
39 self.random_first_number*self.random_second_number
40 )
41
42 def test_division(self):
43 try:
44 self.assertEqual(
45 src.calculator.divide(
46 self.random_first_number,
47 self.random_second_number
48 ),
49 self.random_first_number/self.random_second_number
50 )
51 except ZeroDivisionError:
52 self.assertEqual(
53 src.calculator.divide(self.random_first_number, 0),
54 'brmph?! I cannot divide by 0. Try again...'
55 )
56
57 def test_calculator_sends_message_when_input_is_not_a_number(self):
58 error_message = 'brmph?! Numbers only. Try again...'
59
60 self.assertEqual(
61 src.calculator.add(None, None),
62 error_message
63 )
64 self.assertEqual(
65 src.calculator.divide(None, None),
66 error_message
67 )
68 self.assertEqual(
69 src.calculator.multiply(None, None),
70 error_message
71 )
72 self.assertEqual(
73 src.calculator.subtract(None, None),
74 error_message
75 )
76 self.assertEqual(
77 src.calculator.add('1', '1'),
78 error_message
79 )
80 self.assertEqual(
81 src.calculator.divide('1', '1'),
82 error_message
83 )
84 self.assertEqual(
85 src.calculator.multiply('1', '1'),
86 error_message
87 )
88 self.assertEqual(
89 src.calculator.subtract('1', '1'),
90 error_message
91 )
92
93 a_list = [0, 1, 2, 3]
94
95 self.assertEqual(
96 src.calculator.add(a_list, 0),
97 error_message
98 )
99 self.assertEqual(
100 src.calculator.divide(a_list, 1),
101 error_message
102 )
103 self.assertEqual(
104 src.calculator.multiply(a_list, 2),
105 error_message
106 )
107 self.assertEqual(
108 src.calculator.subtract(a_list, 3),
109 error_message
110 )
111
112 def test_calculator_w_list_items(self):
113 two_numbers = [
114 self.random_first_number,
115 self.random_second_number
116 ]
117
118 self.assertEqual(
119 src.calculator.add(
120 two_numbers[0],
121 two_numbers[1]
122 ),
123 self.random_first_number+self.random_second_number
124 )
125 self.assertEqual(
126 src.calculator.divide(
127 two_numbers[-2],
128 two_numbers[-1]
129 ),
130 self.random_first_number/self.random_second_number
131 )
132 self.assertEqual(
133 src.calculator.multiply(
134 two_numbers[1],
135 two_numbers[-1]
136 ),
137 self.random_second_number*self.random_second_number
138 )
139 self.assertEqual(
140 src.calculator.subtract(
141 two_numbers[-2],
142 two_numbers[0]
143 ),
144 self.random_first_number-self.random_first_number
145 )
146 self.assertEqual(
147 src.calculator.add(*two_numbers),
148 self.random_first_number+self.random_second_number
149 )
150 self.assertEqual(
151 src.calculator.divide(*two_numbers),
152 self.random_first_number/self.random_second_number
153 )
154 self.assertEqual(
155 src.calculator.multiply(*two_numbers),
156 self.random_first_number*self.random_second_number
157 )
158 self.assertEqual(
159 src.calculator.subtract(*two_numbers),
160 self.random_first_number-self.random_second_number
161 )
162
163 def test_calculator_raises_type_error_when_given_more_than_two_inputs(self):
164 not_two_numbers = [0, 1, 2]
165
166 with self.assertRaises(TypeError):
167 src.calculator.add(*not_two_numbers)
168 with self.assertRaises(TypeError):
169 src.calculator.divide(*not_two_numbers)
170 with self.assertRaises(TypeError):
171 src.calculator.multiply(*not_two_numbers)
172 with self.assertRaises(TypeError):
173 src.calculator.subtract(*not_two_numbers)
174
175
176# Exceptions seen
177# AssertionError
178# NameError
179# AttributeError
180# TypeError
how to make a calculator 5: solutions
the solutions in calculator/src/calculator.py from how to make a calculator 5
1def numbers_only(function):
2 def wrapper(first_input, second_input):
3 good_types = (int, float)
4 error_message = 'brmph?! Numbers only. Try again...'
5
6 if not (isinstance(first_input, good_types) and isinstance(second_input, good_types)):
7 return error_message
8 else:
9 try:
10 return function(first_input, second_input)
11 except TypeError:
12 return error_message
13 return wrapper
14
15
16@numbers_only
17def subtract(first_input, second_input):
18 return first_input - second_input
19
20
21@numbers_only
22def multiply(first_input, second_input):
23 return first_input * second_input
24
25
26@numbers_only
27def divide(first_input, second_input):
28 try:
29 return first_input / second_input
30 except ZeroDivisionError:
31 return 'brmph?! I cannot divide by 0. Try again...'
32
33
34@numbers_only
35def add(first_input, second_input):
36 return first_input + second_input
how to make a calculator 6: tests
the code from calculator/tests/test_calculator.py from how to make a calculator 6
1import random
2import src.calculator
3import unittest
4
5
6def a_random_number():
7 return random.triangular(-1000.0, 1000.0)
8
9
10class TestCalculator(unittest.TestCase):
11
12 def setUp(self):
13 self.random_first_number = a_random_number()
14 self.random_second_number = a_random_number()
15
16 def test_addition(self):
17 self.assertEqual(
18 src.calculator.add(
19 self.random_first_number,
20 self.random_second_number
21 ),
22 self.random_first_number+self.random_second_number
23 )
24
25 def test_subtraction(self):
26 self.assertEqual(
27 src.calculator.subtract(
28 self.random_first_number,
29 self.random_second_number
30 ),
31 self.random_first_number-self.random_second_number
32 )
33
34 def test_multiplication(self):
35 self.assertEqual(
36 src.calculator.multiply(
37 self.random_first_number,
38 self.random_second_number
39 ),
40 self.random_first_number*self.random_second_number
41 )
42
43 def test_division(self):
44 try:
45 self.assertEqual(
46 src.calculator.divide(
47 self.random_first_number,
48 self.random_second_number
49 ),
50 self.random_first_number/self.random_second_number
51 )
52 except ZeroDivisionError:
53 self.assertEqual(
54 src.calculator.divide(self.random_first_number, 0),
55 'brmph?! I cannot divide by 0. Try again...'
56 )
57
58 def test_calculator_w_list_items(self):
59 two_numbers = [
60 self.random_first_number,
61 self.random_second_number
62 ]
63
64 self.assertEqual(
65 src.calculator.add(
66 two_numbers[0],
67 two_numbers[1]
68 ),
69 self.random_first_number+self.random_second_number
70 )
71 self.assertEqual(
72 src.calculator.divide(
73 two_numbers[-2],
74 two_numbers[-1]
75 ),
76 self.random_first_number/self.random_second_number
77 )
78 self.assertEqual(
79 src.calculator.multiply(
80 two_numbers[1],
81 two_numbers[-1]
82 ),
83 self.random_second_number*self.random_second_number
84 )
85 self.assertEqual(
86 src.calculator.subtract(
87 two_numbers[-2],
88 two_numbers[0]
89 ),
90 self.random_first_number-self.random_first_number
91 )
92 self.assertEqual(
93 src.calculator.add(*two_numbers),
94 self.random_first_number+self.random_second_number
95 )
96 self.assertEqual(
97 src.calculator.divide(*two_numbers),
98 self.random_first_number/self.random_second_number
99 )
100 self.assertEqual(
101 src.calculator.multiply(*two_numbers),
102 self.random_first_number*self.random_second_number
103 )
104 self.assertEqual(
105 src.calculator.subtract(*two_numbers),
106 self.random_first_number-self.random_second_number
107 )
108
109 def test_calculator_raises_type_error_when_given_more_than_two_inputs(self):
110 not_two_numbers = [0, 1, 2]
111
112 with self.assertRaises(TypeError):
113 src.calculator.add(*not_two_numbers)
114 with self.assertRaises(TypeError):
115 src.calculator.divide(*not_two_numbers)
116 with self.assertRaises(TypeError):
117 src.calculator.multiply(*not_two_numbers)
118 with self.assertRaises(TypeError):
119 src.calculator.subtract(*not_two_numbers)
120
121 def test_calculator_sends_message_when_input_is_not_a_number(self):
122 error_message = 'brmph?! Numbers only. Try again...'
123
124 [
125 self.assertEqual(
126 src.calculator.add(data_type, a_random_number()),
127 error_message
128 ) for data_type in (
129 None,
130 True, False,
131 str(), 'text',
132 tuple(), (0, 1, 2, 'n'),
133 list(), [0, 1, 2, 'n'],
134 set(), {0, 1, 2, 'n'},
135 dict(), {'key': 'value'},
136 )
137 ]
138
139 for data_type in (
140 None,
141 True, False,
142 str(), 'text',
143 tuple(), (0, 1, 2, 'n'),
144 list(), [0, 1, 2, 'n'],
145 set(), {0, 1, 2, 'n'},
146 dict(), {'key': 'value'},
147 ):
148 with self.subTest(data_type=data_type):
149 self.assertEqual(
150 src.calculator.add(
151 data_type, a_random_number()
152 ),
153 error_message
154 )
155 self.assertEqual(
156 src.calculator.divide(
157 data_type, a_random_number()
158 ),
159 error_message
160 )
161 self.assertEqual(
162 src.calculator.multiply(
163 data_type, a_random_number()
164 ),
165 error_message
166 )
167 self.assertEqual(
168 src.calculator.subtract(
169 data_type, a_random_number()
170 ),
171 error_message
172 )
173
174
175# Exceptions seen
176# AssertionError
177# NameError
178# AttributeError
179# TypeError
how to make a calculator 6: solutions
the solutions in calculator/src/calculator.py from how to make a calculator 5
1def numbers_only(function):
2 def decorator(first_input, second_input):
3 bad_data_types = (str, list, bool)
4 error_message = 'brmph?! Numbers only. Try again...'
5
6 for value in (first_input, second_input):
7 if (
8 value is None
9 or
10 isinstance(value, bad_data_types)
11 ):
12 return error_message
13
14 try:
15 return function(first_input, second_input)
16 except TypeError:
17 return error_message
18 return decorator
19
20
21@numbers_only
22def subtract(first_input, second_input):
23 return first_input - second_input
24
25
26@numbers_only
27def multiply(first_input, second_input):
28 return first_input * second_input
29
30
31@numbers_only
32def divide(first_input, second_input):
33 try:
34 return first_input / second_input
35 except ZeroDivisionError:
36 return 'brmph?! I cannot divide by 0. Try again...'
37
38
39@numbers_only
40def add(first_input, second_input):
41 return first_input + second_input
how to make a calculator 7: tests
the code from calculator/tests/test_calculator.py from how to make a calculator 7
1import random
2import src.calculator
3import unittest
4
5
6def a_random_number():
7 return random.triangular(-1000.0, 1000.0)
8
9
10class TestCalculator(unittest.TestCase):
11
12 def setUp(self):
13 self.random_first_number = a_random_number()
14 self.random_second_number = a_random_number()
15
16 x = self.random_first_number
17 y = self.random_second_number
18
19 try:
20 division_result = x / y
21 except ZeroDivisionError:
22 division_result = 'brmph?! I cannot divide by 0. Try again...'
23
24 self.arithmetic_tests = {
25 'addition': {
26 'function': src.calculator.add,
27 'expectation': x+y,
28 },
29 'subtraction': {
30 'function': src.calculator.subtract,
31 'expectation': x-y,
32 },
33 'division': {
34 'function': src.calculator.divide,
35 'expectation': division_result,
36 },
37 'multiplication': {
38 'function': src.calculator.multiply,
39 'expectation': x*y,
40 }
41 }
42
43 def test_calculator_w_list_items(self):
44 # two_numbers = [
45 # self.random_first_number,
46 # self.random_second_number
47 # ]
48 a_dictionary = {
49 'x': self.random_first_number,
50 'y': self.random_second_number
51 }
52 two_numbers = list(a_dictionary.values())
53
54 for operation in self.arithmetic_tests:
55 with self.subTest(operation=operation):
56 self.assertEqual(
57 self.arithmetic_tests[operation]['function'](
58 *two_numbers
59 ),
60 self.arithmetic_tests[operation]['expectation']
61 )
62
63 self.assertEqual(
64 src.calculator.add(
65 two_numbers[0],
66 two_numbers[1]
67 ),
68 self.random_first_number+self.random_second_number
69 )
70 self.assertEqual(
71 src.calculator.divide(
72 two_numbers[-2],
73 two_numbers[-1]
74 ),
75 self.random_first_number/self.random_second_number
76 )
77 self.assertEqual(
78 src.calculator.multiply(
79 two_numbers[1],
80 two_numbers[-1]
81 ),
82 self.random_second_number*self.random_second_number
83 )
84 self.assertEqual(
85 src.calculator.subtract(
86 two_numbers[-2],
87 two_numbers[0]
88 ),
89 self.random_first_number-self.random_first_number
90 )
91
92 def test_calculator_w_dictionary_items(self):
93 two_numbers = {
94 'first_input': self.random_first_number,
95 'second_input': self.random_second_number,
96 }
97
98 for operation in self.arithmetic_tests:
99 with self.subTest(operation=operation):
100 self.assertEqual(
101 self.arithmetic_tests[operation]['function'](
102 **two_numbers
103 ),
104 self.arithmetic_tests[operation]['expectation']
105 )
106
107 self.assertEqual(
108 src.calculator.add(
109 two_numbers['first_input'],
110 two_numbers['second_input']
111 ),
112 self.random_first_number+self.random_second_number
113 )
114 self.assertEqual(
115 src.calculator.divide(
116 two_numbers['first_input'],
117 two_numbers['second_input']
118 ),
119 self.random_first_number/self.random_second_number
120 )
121 self.assertEqual(
122 src.calculator.multiply(
123 two_numbers['second_input'],
124 two_numbers['second_input']
125 ),
126 self.random_second_number*self.random_second_number
127 )
128 self.assertEqual(
129 src.calculator.subtract(
130 two_numbers['first_input'],
131 two_numbers['first_input']
132 ),
133 self.random_first_number-self.random_first_number
134 )
135
136 def test_calculator_raises_type_error_when_given_more_than_two_inputs(self):
137 for operation in self.arithmetic_tests:
138 with (
139 self.subTest(operation=operation),
140 self.assertRaises(TypeError),
141 ):
142 self.arithmetic_tests[operation]['function'](
143 [0, 1, 2]
144 )
145
146 def test_calculator_sends_message_when_input_is_not_a_number(self):
147 for bad_input in (
148 None,
149 True, False,
150 str(), 'text',
151 tuple(), (0, 1, 2, 'n'),
152 list(), [0, 1, 2, 'n'],
153 set(), {0, 1, 2, 'n'},
154 dict(), {'key': 'value'},
155 ):
156 for operation in self.arithmetic_tests:
157 with self.subTest(
158 operation=operation,
159 bad_input=bad_input,
160 ):
161 self.assertEqual(
162 self.arithmetic_tests[operation]['function'](
163 bad_input, a_random_number()
164 ),
165 'brmph?! Numbers only. Try again...'
166 )
167
168 def test_calculator_functions(self):
169 for operation in self.arithmetic_tests:
170 with self.subTest(operation=operation):
171 self.assertEqual(
172 self.arithmetic_tests[operation]['function'](
173 self.random_first_number,
174 self.random_second_number
175 ),
176 self.arithmetic_tests[operation]['expectation']
177 )
178
179
180# Exceptions seen
181# AssertionError
182# NameError
183# AttributeError
184# TypeError
185# KeyError
how to make a calculator 8: tests
the code from calculator/tests/test_calculator.py from how to make a calculator 8
1import random
2import src.calculator
3import unittest
4
5
6def a_random_number():
7 return random.triangular(-1000.0, 1000.0)
8
9
10class TestCalculator(unittest.TestCase):
11
12 @staticmethod
13 def get_division_result(x, y):
14 try:
15 return x / y
16 except ZeroDivisionError:
17 return 'brmph?! I cannot divide by 0. Try again...'
18
19 def setUp(self):
20 self.random_first_number = a_random_number()
21 self.random_second_number = a_random_number()
22
23 x = self.random_first_number
24 y = self.random_second_number
25
26 self.calculator_tests = {
27 'add': x+y,
28 'subtract': x-y,
29 'multiply': x*y,
30 'divide': self.get_division_result(x, y)
31 }
32
33 def test_calculator_w_list_items(self):
34 # two_numbers = [
35 # self.random_first_number,
36 # self.random_second_number
37 # ]
38 a_dictionary = {
39 'x': self.random_first_number,
40 'y': self.random_second_number
41 }
42 two_numbers = list(a_dictionary.values())
43
44 for operation in self.calculator_tests:
45 with self.subTest(operation=operation):
46 self.assertEqual(
47 src.calculator.__getattribute__(operation)(
48 *two_numbers
49 ),
50 self.calculator_tests[operation]
51 )
52
53 self.assertEqual(
54 src.calculator.add(
55 two_numbers[0],
56 two_numbers[1]
57 ),
58 self.random_first_number+self.random_second_number
59 )
60 self.assertEqual(
61 src.calculator.divide(
62 two_numbers[-2],
63 two_numbers[-1]
64 ),
65 self.random_first_number/self.random_second_number
66 )
67 self.assertEqual(
68 src.calculator.multiply(
69 two_numbers[1],
70 two_numbers[-1]
71 ),
72 self.random_second_number*self.random_second_number
73 )
74 self.assertEqual(
75 src.calculator.subtract(
76 two_numbers[-2],
77 two_numbers[0]
78 ),
79 self.random_first_number-self.random_first_number
80 )
81
82 def test_calculator_w_dictionary_items(self):
83 two_numbers = {
84 'first_input': self.random_first_number,
85 'second_input': self.random_second_number,
86 }
87
88 for operation in self.calculator_tests:
89 with self.subTest(operation=operation):
90 self.assertEqual(
91 src.calculator.__getattribute__(operation)(
92 **two_numbers
93 ),
94 self.calculator_tests[operation]
95 )
96
97 self.assertEqual(
98 src.calculator.add(
99 two_numbers['first_input'],
100 two_numbers['second_input']
101 ),
102 self.random_first_number+self.random_second_number
103 )
104 self.assertEqual(
105 src.calculator.divide(
106 two_numbers['first_input'],
107 two_numbers['second_input']
108 ),
109 self.random_first_number/self.random_second_number
110 )
111 self.assertEqual(
112 src.calculator.multiply(
113 two_numbers['second_input'],
114 two_numbers['second_input']
115 ),
116 self.random_second_number*self.random_second_number
117 )
118 self.assertEqual(
119 src.calculator.subtract(
120 two_numbers['first_input'],
121 two_numbers['first_input']
122 ),
123 self.random_first_number-self.random_first_number
124 )
125
126 def test_calculator_raises_type_error_when_given_more_than_two_inputs(self):
127 for operation in self.calculator_tests:
128 with (
129 self.subTest(operation=operation),
130 self.assertRaises(TypeError),
131 ):
132 src.calculator.__getattribute__(operation)(
133 [0, 1, 2]
134 )
135
136 def test_calculator_sends_message_when_input_is_not_a_number(self):
137 for bad_input in (
138 None,
139 True, False,
140 str(), 'text',
141 tuple(), (0, 1, 2, 'n'),
142 list(), [0, 1, 2, 'n'],
143 set(), {0, 1, 2, 'n'},
144 dict(), {'key': 'value'},
145 ):
146 for operation in self.calculator_tests:
147 with self.subTest(
148 operation=operation,
149 bad_input=bad_input,
150 ):
151 self.assertEqual(
152 src.calculator.__getattribute__(operation)(
153 bad_input, a_random_number()
154 ),
155 'brmph?! Numbers only. Try again...'
156 )
157
158 def test_calculator_functions(self):
159 for operation in self.calculator_tests:
160 with self.subTest(operation=operation):
161 self.assertEqual(
162 src.calculator.__getattribute__(operation)(
163 self.random_first_number,
164 self.random_second_number
165 ),
166 self.calculator_tests[operation]
167 )
168
169
170# Exceptions seen
171# AssertionError
172# NameError
173# AttributeError
174# TypeError
175# KeyError
how to make a calculator 9: tests
the code from calculator/tests/test_calculator_website.py from how to make a calculator 9
1import src.website
2import tests.test_calculator
3import unittest
4
5
6class TestCalculatorWebsite(unittest.TestCase):
7
8 def setUp(self):
9 self.client = src.website.app.test_client()
10 self.x = tests.test_calculator.a_random_number()
11
12 def test_home_page(self):
13 response = self.client.get('/')
14 self.assertEqual(response.status_code, 200)
15 self.assertIn(
16 b'<h1>Calculator</h1>',
17 response.data
18 )
19
20 def test_calculations(self):
21 y = tests.test_calculator.a_random_number()
22
23 operations = {
24 'add': '+',
25 'subtract': '-',
26 'divide': '/',
27 'multiply': '*',
28 }
29
30 for operation in operations:
31 with self.subTest(operation=operation):
32 response = self.client.post(
33 '/calculate',
34 data={
35 'first_input': self.x,
36 'second_input': y,
37 'operation': operation,
38 }
39 )
40 self.assertEqual(response.status_code, 200)
41
42 function = src.calculator.__getattribute__(
43 operation
44 )
45 result = function(self.x, y)
46 self.assertEqual(
47 response.data.decode(),
48 (
49 f'<h2>{self.x} {operations[operation]} {y} '
50 f'= {result}</h2>'
51 )
52 )
53
54 def test_website_handling_zero_division_error(self):
55 response = self.client.post(
56 '/calculate',
57 data={
58 'first_input': self.x,
59 'second_input': 0,
60 'operation': 'divide',
61 }
62 )
63 self.assertEqual(
64 response.data.decode(),
65 (
66 f'<h2>{self.x} / 0.0 = '
67 'brmph?! I cannot divide by 0. Try again...</h2>'
68 )
69 )
70
71
72# Exceptions seen
73# NameError
74# ModuleNotFoundError
75# AttributeError
76# AssertionError
77# jinja2.exceptions.TemplateNotFound
78# SyntaxError
the code from calculator/tests/test_calculator.py from how to make a calculator 9
1import random
2import src.calculator
3import unittest
4
5
6def a_random_number():
7 return random.triangular(-1000.0, 1000.0)
8
9
10class TestCalculator(unittest.TestCase):
11
12 @staticmethod
13 def get_division_result(x, y):
14 try:
15 return x / y
16 except ZeroDivisionError:
17 return 'brmph?! I cannot divide by 0. Try again...'
18
19 def setUp(self):
20 self.random_first_number = a_random_number()
21 self.random_second_number = a_random_number()
22
23 x = self.random_first_number
24 y = self.random_second_number
25
26 self.calculator_tests = {
27 'add': x+y,
28 'subtract': x-y,
29 'multiply': x*y,
30 'divide': self.get_division_result(x, y)
31 }
32
33 def test_calculator_w_list_items(self):
34 # two_numbers = [
35 # self.random_first_number,
36 # self.random_second_number
37 # ]
38 a_dictionary = {
39 'x': self.random_first_number,
40 'y': self.random_second_number
41 }
42 two_numbers = list(a_dictionary.values())
43
44 for operation in self.calculator_tests:
45 with self.subTest(operation=operation):
46 self.assertEqual(
47 src.calculator.__getattribute__(operation)(
48 *two_numbers
49 ),
50 self.calculator_tests[operation]
51 )
52
53 self.assertEqual(
54 src.calculator.add(
55 two_numbers[0],
56 two_numbers[1]
57 ),
58 self.random_first_number+self.random_second_number
59 )
60 self.assertEqual(
61 src.calculator.divide(
62 two_numbers[-2],
63 two_numbers[-1]
64 ),
65 self.random_first_number/self.random_second_number
66 )
67 self.assertEqual(
68 src.calculator.multiply(
69 two_numbers[1],
70 two_numbers[-1]
71 ),
72 self.random_second_number*self.random_second_number
73 )
74 self.assertEqual(
75 src.calculator.subtract(
76 two_numbers[-2],
77 two_numbers[0]
78 ),
79 self.random_first_number-self.random_first_number
80 )
81
82 def test_calculator_w_dictionary_items(self):
83 two_numbers = {
84 'first_input': self.random_first_number,
85 'second_input': self.random_second_number,
86 }
87
88 for operation in self.calculator_tests:
89 with self.subTest(operation=operation):
90 self.assertEqual(
91 src.calculator.__getattribute__(operation)(
92 **two_numbers
93 ),
94 self.calculator_tests[operation]
95 )
96
97 self.assertEqual(
98 src.calculator.add(
99 two_numbers['first_input'],
100 two_numbers['second_input']
101 ),
102 self.random_first_number+self.random_second_number
103 )
104 self.assertEqual(
105 src.calculator.divide(
106 two_numbers['first_input'],
107 two_numbers['second_input']
108 ),
109 self.random_first_number/self.random_second_number
110 )
111 self.assertEqual(
112 src.calculator.multiply(
113 two_numbers['second_input'],
114 two_numbers['second_input']
115 ),
116 self.random_second_number*self.random_second_number
117 )
118 self.assertEqual(
119 src.calculator.subtract(
120 two_numbers['first_input'],
121 two_numbers['first_input']
122 ),
123 self.random_first_number-self.random_first_number
124 )
125
126 def test_calculator_raises_type_error_when_given_more_than_two_inputs(self):
127 for operation in self.calculator_tests:
128 with (
129 self.subTest(operation=operation),
130 self.assertRaises(TypeError),
131 ):
132 src.calculator.__getattribute__(operation)(
133 [0, 1, 2]
134 )
135
136 def test_calculator_sends_message_when_inputs_are_not_numbers(self):
137 for bad_input in (
138 None,
139 True, False,
140 str(), 'text',
141 tuple(), (0, 1, 2, 'n'),
142 list(), [0, 1, 2, 'n'],
143 set(), {0, 1, 2, 'n'},
144 dict(), {'key': 'value'},
145 ):
146 for operation in self.calculator_tests:
147 with self.subTest(
148 operation=operation,
149 bad_input=bad_input,
150 ):
151 self.assertEqual(
152 src.calculator.__getattribute__(operation)(
153 bad_input, a_random_number()
154 ),
155 'brmph?! Numbers only. Try again...'
156 )
157 self.assertEqual(
158 src.calculator.__getattribute__(operation)(
159 a_random_number(), bad_input
160 ),
161 'brmph?! Numbers only. Try again...'
162 )
163
164 def test_calculator_functions(self):
165 for operation in self.calculator_tests:
166 with self.subTest(operation=operation):
167 self.assertEqual(
168 src.calculator.__getattribute__(operation)(
169 self.random_first_number,
170 self.random_second_number
171 ),
172 self.calculator_tests[operation]
173 )
174
175
176# Exceptions seen
177# AssertionError
178# NameError
179# AttributeError
180# TypeError
181# KeyError
how to make a calculator 9: solutions
the code from calculator/src/calculator.py from how to make a calculator 9
1def check_input(function):
2 def wrapper(first_input, second_input):
3 if isinstance(
4 first_input,
5 (dict, set, list, tuple, str, bool)
6 ) or first_input is None:
7 return 'brmph?! Numbers only. Try again...'
8 return function(first_input, second_input)
9 return wrapper
10
11
12@check_input
13def add(first_input, second_input):
14 return first_input + second_input
15
16
17@check_input
18def divide(first_input, second_input):
19 try:
20 return first_input / second_input
21 except ZeroDivisionError:
22 return 'brmph?! I cannot divide by 0. Try again...'
23
24
25@check_input
26def multiply(first_input, second_input):
27 return first_input * second_input
28
29
30@check_input
31def subtract(first_input, second_input):
32 return first_input - second_input
the code from calculator/src/website.py from how to make a calculator 9
1import pathlib
2import sys
3sys.path.insert(
4 0, str(pathlib.Path(__file__).resolve().parent)
5)
6
7import calculator
8import flask
9
10
11app = flask.Flask(__name__)
12
13
14@app.route('/')
15def home():
16 return flask.render_template('index.html')
17
18
19@app.route('/calculate', methods=['POST'])
20def calculate():
21 first_input = flask.request.form.get('first_input')
22 first_input = float(first_input)
23 second_input = flask.request.form.get('second_input')
24 second_input = float(second_input)
25 operation = flask.request.form.get('operation')
26
27 operations = {
28 'add': '+',
29 'subtract': '-',
30 'divide': '/',
31 'multiply': '*',
32 }
33
34 result = calculator.__getattribute__(operation)(
35 first_input, second_input
36 )
37 return (
38 f'<h2>{first_input} {operations[operation]} {second_input} '
39 f'= {result}</h2>'
40 )
how to make a calculator 10: part 1: tests
the code from calculator/tests/test_streamlit_calculator.py from how to make a calculator 10: part 1
1import random
2import streamlit.testing.v1
3import tests.test_calculator
4import unittest
5
6
7class TestStreamlitCalculator(unittest.TestCase):
8
9 def setUp(self):
10 self.tester = streamlit.testing.v1.AppTest.from_file(
11 'src/streamlit_calculator.py'
12 )
13 self.tester.run()
14
15 def test_streamlit_calculator_title(self):
16 self.assertEqual(self.tester.title[0].value, 'Calculator')
17
18 def test_streamlit_calculator_display(self):
19 self.assertEqual(
20 self.tester.main.children[1].type,
21 'flex_container'
22 )
23
24 def test_streamlit_calculator_columns(self):
25 self.assertEqual(len(self.tester.columns), 4)
26 self.assertEqual(
27 self.tester.columns[0].button('<-').label,
28 '<-'
29 )
30 self.assertEqual(
31 self.tester.columns[0].button('7').label,
32 '7'
33 )
34 self.assertEqual(
35 self.tester.columns[0].button('4').label,
36 '4'
37 )
38 self.assertEqual(
39 self.tester.columns[0].button('1').label,
40 '1'
41 )
42 self.assertEqual(
43 self.tester.columns[0].button('+/-').label,
44 '+/-'
45 )
46 self.assertEqual(
47 self.tester.columns[1].button('C').label,
48 'C'
49 )
50 self.assertEqual(
51 self.tester.columns[1].button('8').label,
52 '8'
53 )
54 self.assertEqual(
55 self.tester.columns[1].button('5').label,
56 '5'
57 )
58 self.assertEqual(
59 self.tester.columns[1].button('2').label,
60 '2'
61 )
62 self.assertEqual(
63 self.tester.columns[1].button('0').label,
64 '0'
65 )
66
67 self.assertEqual(
68 self.tester.columns[2].button('AC').label,
69 'AC'
70 )
71 self.assertEqual(
72 self.tester.columns[2].button('9').label,
73 '9'
74 )
75 self.assertEqual(
76 self.tester.columns[2].button('6').label,
77 '6'
78 )
79 self.assertEqual(
80 self.tester.columns[2].button('3').label,
81 '3'
82 )
83 self.assertEqual(
84 self.tester.columns[2].button('.').label,
85 '.'
86 )
87
88 self.assertEqual(
89 self.tester.columns[3].button('/').label,
90 '/'
91 )
92 self.assertEqual(
93 self.tester.columns[3].button('X').label,
94 'X'
95 )
96 self.assertEqual(
97 self.tester.columns[3].button('-').label,
98 r'\-'
99 )
100 self.assertEqual(
101 self.tester.columns[3].button('+').label,
102 r'\+'
103 )
104 self.assertEqual(
105 self.tester.columns[3].button('=').label,
106 '='
107 )
108
109 def test_streamlit_session_state(self):
110 expectation = '0'
111 for _ in range(0, 10):
112 number = random.choice('0123456789')
113 (
114 self.tester.button(number)
115 .click().run()
116 )
117 if expectation == '0':
118 expectation = number
119 else:
120 expectation += number
121 self.assertEqual(
122 self.tester.session_state['number'],
123 expectation
124 )
125
126 def test_streamlit_calculator_w_decimals(self):
127 for button in ('0.23.5.6.7.8.9'):
128 (
129 self.tester.button(button)
130 .click().run()
131 )
132 self.assertEqual(
133 self.tester.session_state['number'],
134 '.2356789'
135 )
136
137 def test_streamlit_calculator_w_plus_minus(self):
138 number = '963.0258741'
139 for button in number:
140 (
141 self.tester.button(button)
142 .click().run()
143 )
144 self.tester.button('+/-').click().run()
145 self.assertEqual(
146 self.tester.session_state['number'],
147 f'-{number}'
148 )
149
150 self.tester.session_state['number'] = '0'
151 number = '-963.0258741'
152 for button in number:
153 (
154 self.tester.button(button)
155 .click().run()
156 )
157
158 self.tester.button('+/-').click().run()
159 self.assertEqual(
160 self.tester.session_state['number'],
161 number[1:]
162 )
163
164 def test_streamlit_calculator_reset_state(self):
165 numbers = '123456789'
166 number = random.choice(numbers)
167 self.tester.button(number).click().run()
168 self.assertEqual(
169 self.tester.session_state['number'],
170 number
171 )
172 self.tester.button('C').click().run()
173 self.assertEqual(
174 self.tester.session_state['number'],
175 '0'
176 )
177
178 number = random.choice(numbers)
179 self.tester.button(number).click().run()
180 self.assertEqual(
181 self.tester.session_state['number'],
182 number
183 )
184 self.tester.button('AC').click().run()
185 self.assertEqual(
186 self.tester.session_state['number'],
187 '0'
188 )
189
190 @unittest.skip
191 def test_streamlit_calculator_operations(self):
192 # first_number = '1'
193 first_number = tests.test_calculator.a_random_number()
194 first_number = str(first_number)
195 second_number = '2'
196
197 for character in first_number:
198 if character == '-':
199 self.tester.button('+/-').click().run()
200 else:
201 self.tester.button(character).click().run()
202 self.tester.button('+').click().run()
203 self.assertEqual(
204 self.tester.session_state['first_number'],
205 first_number
206 )
207
208 self.tester.button(second_number).click().run()
209 self.tester.button('=').click().run()
210 self.assertEqual(
211 self.tester.session_state['second_number'],
212 second_number
213 )
214
215 self.assertEqual(
216 self.tester.session_state['number'],
217 str(float(first_number) + float(second_number))
218 )
219
220
221# Exceptions seen
222# NameError
223# AttributeError
224# AssertionError
225# SyntaxError
226# KeyError
227# streamlit.errors.StreamlitDuplicateElementKey
228# TypeError
how to make a calculator 10: part 1: solutions
the code from calculator/src/streamlit_calculator.py from how to make a calculator 10: part 1
1import streamlit
2
3
4def show_result(display):
5 streamlit.session_state['second_number'] = \
6 streamlit.session_state['number']
7 streamlit.session_state['number'] = str(
8 float(streamlit.session_state['first_number'])
9 + float(streamlit.session_state['second_number'])
10 )
11 display.write(streamlit.session_state['number'])
12
13
14def make_variable(display):
15 streamlit.session_state['first_number'] = \
16 streamlit.session_state['number']
17 reset_state(display)
18
19
20def reset_state(display):
21 streamlit.session_state['number'] = '0'
22 display.write(streamlit.session_state['number'])
23
24
25def update_state(value):
26 if value == '.':
27 if (
28 streamlit.session_state['number']
29 .count('.') != 0
30 ):
31 return
32 if streamlit.session_state['number'] == '0':
33 streamlit.session_state['number'] = value
34 return
35 if value == '+/-':
36 if not (
37 streamlit.session_state['number']
38 .startswith('-')
39 ):
40 negative = (
41 '-' +
42 streamlit.session_state['number']
43 )
44 streamlit.session_state['number'] = \
45 negative
46 return
47 else:
48 streamlit.session_state['number'] = \
49 streamlit.session_state['number'][1:]
50 return
51 streamlit.session_state['number'] += value
52
53
54def show(display, value):
55 update_state(value)
56 display.write(streamlit.session_state['number'])
57
58
59def add_buttons():
60 display = streamlit.container(border=True)
61 column_1, column_2, column_3, operations = streamlit.columns(4)
62
63 column_1.button('<-', key='<-', width='stretch')
64 column_1.button(
65 '7', key='7', width='stretch',
66 on_click=show, args=[display, '7'],
67 )
68 column_1.button(
69 '4', key='4', width='stretch',
70 on_click=show, args=[display, '4'],
71 )
72 column_1.button(
73 '1', key='1', width='stretch',
74 on_click=show, args=[display, '1'],
75 )
76 column_1.button(
77 '+/-', key='+/-', width='stretch',
78 on_click=show, args=[display, '+/-'],
79 )
80
81 column_2.button(
82 'C', key='C', width='stretch', type='primary',
83 on_click=reset_state, args=[display],
84 )
85 column_2.button(
86 '8', key='8', width='stretch',
87 on_click=show, args=[display, '8'],
88 )
89 column_2.button(
90 '5', key='5', width='stretch',
91 on_click=show, args=[display, '5'],
92 )
93 column_2.button(
94 '2', key='2', width='stretch',
95 on_click=show, args=[display, '2'],
96 )
97 column_2.button(
98 '0', key='0', width='stretch',
99 on_click=show, args=[display, '0'],
100 )
101
102 column_3.button(
103 'AC', key='AC', width='stretch', type='primary',
104 on_click=reset_state, args=[display],
105 )
106 column_3.button(
107 '9', key='9', width='stretch',
108 on_click=show, args=[display, '9'],
109 )
110 column_3.button(
111 '6', key='6', width='stretch',
112 on_click=show, args=[display, '6'],
113 )
114 column_3.button(
115 '3', key='3', width='stretch',
116 on_click=show, args=[display, '3'],
117 )
118 column_3.button(
119 '.', key='.', width='stretch',
120 on_click=show, args=[display, '.'],
121 )
122
123 operations.button('/', key='/', width='stretch', type='primary')
124 operations.button('X', key='X', width='stretch', type='primary')
125 operations.button(r'\-', key='-', width='stretch', type='primary')
126 operations.button(
127 r'\+', key='+', width='stretch', type='primary',
128 on_click=make_variable, args=[display],
129 )
130 operations.button(
131 '=', key='=', width='stretch', type='primary',
132 on_click=show_result, args=[display],
133 )
134
135
136def main():
137 streamlit.title('Calculator')
138 streamlit.session_state.setdefault('number', '0')
139 add_buttons()
140
141
142if __name__ == '__main__':
143 main()
how to make a calculator 10: part 2: tests and solutions
the code from calculator/tests/test_streamlit_calculator.py from how to make a calculator 10: part 2
1import random
2import streamlit.testing.v1
3import tests.test_calculator
4import unittest
5
6
7class TestStreamlitCalculator(unittest.TestCase):
8
9 def setUp(self):
10 self.tester = streamlit.testing.v1.AppTest.from_file(
11 'src/streamlit_calculator.py'
12 )
13 self.tester.run()
14
15 def test_streamlit_calculator_title(self):
16 self.assertEqual(self.tester.title[0].value, 'Calculator')
17
18 def test_streamlit_calculator_display(self):
19 self.assertEqual(
20 self.tester.main.children[1].type,
21 'flex_container'
22 )
23
24 def test_streamlit_calculator_columns(self):
25 self.assertEqual(len(self.tester.columns), 4)
26 self.assertEqual(
27 self.tester.columns[0].button('<-').label,
28 '<-'
29 )
30 self.assertEqual(
31 self.tester.columns[0].button('7').label,
32 '7'
33 )
34 self.assertEqual(
35 self.tester.columns[0].button('4').label,
36 '4'
37 )
38 self.assertEqual(
39 self.tester.columns[0].button('1').label,
40 '1'
41 )
42 self.assertEqual(
43 self.tester.columns[0].button('+/-').label,
44 '+/-'
45 )
46 self.assertEqual(
47 self.tester.columns[1].button('C').label,
48 'C'
49 )
50 self.assertEqual(
51 self.tester.columns[1].button('8').label,
52 '8'
53 )
54 self.assertEqual(
55 self.tester.columns[1].button('5').label,
56 '5'
57 )
58 self.assertEqual(
59 self.tester.columns[1].button('2').label,
60 '2'
61 )
62 self.assertEqual(
63 self.tester.columns[1].button('0').label,
64 '0'
65 )
66
67 self.assertEqual(
68 self.tester.columns[2].button('AC').label,
69 'AC'
70 )
71 self.assertEqual(
72 self.tester.columns[2].button('9').label,
73 '9'
74 )
75 self.assertEqual(
76 self.tester.columns[2].button('6').label,
77 '6'
78 )
79 self.assertEqual(
80 self.tester.columns[2].button('3').label,
81 '3'
82 )
83 self.assertEqual(
84 self.tester.columns[2].button('.').label,
85 '.'
86 )
87
88 self.assertEqual(
89 self.tester.columns[3].button('/').label,
90 '/'
91 )
92 self.assertEqual(
93 self.tester.columns[3].button('X').label,
94 'X'
95 )
96 self.assertEqual(
97 self.tester.columns[3].button('-').label,
98 r'\-'
99 )
100 self.assertEqual(
101 self.tester.columns[3].button('+').label,
102 r'\+'
103 )
104 self.assertEqual(
105 self.tester.columns[3].button('=').label,
106 '='
107 )
108
109 def test_streamlit_session_state(self):
110 expectation = '0'
111 for _ in range(0, 10):
112 number = random.choice('0123456789')
113 (
114 self.tester.button(number)
115 .click().run()
116 )
117 if expectation == '0':
118 expectation = number
119 else:
120 expectation += number
121 self.assertEqual(
122 self.tester.session_state['number'],
123 expectation
124 )
125
126 def test_streamlit_calculator_w_decimals(self):
127 for button in ('0.23.5.6.7.8.9'):
128 (
129 self.tester.button(button)
130 .click().run()
131 )
132 self.assertEqual(
133 self.tester.session_state['number'],
134 '.2356789'
135 )
136
137 def test_streamlit_calculator_w_plus_minus(self):
138 number = '963.0258741'
139 for button in number:
140 (
141 self.tester.button(button)
142 .click().run()
143 )
144 self.tester.button('+/-').click().run()
145 self.assertEqual(
146 self.tester.session_state['number'],
147 f'-{number}'
148 )
149
150 self.tester.session_state['number'] = '0'
151 number = '-963.0258741'
152 for button in number:
153 (
154 self.tester.button(button)
155 .click().run()
156 )
157
158 self.tester.button('+/-').click().run()
159 self.assertEqual(
160 self.tester.session_state['number'],
161 number[1:]
162 )
163
164 def test_streamlit_calculator_reset_state(self):
165 numbers = '123456789'
166 number = random.choice(numbers)
167 self.tester.button(number).click().run()
168 self.assertEqual(
169 self.tester.session_state['number'],
170 number
171 )
172 self.tester.button('C').click().run()
173 self.assertEqual(
174 self.tester.session_state['number'],
175 '0'
176 )
177
178 number = random.choice(numbers)
179 self.tester.button(number).click().run()
180 self.assertEqual(
181 self.tester.session_state['number'],
182 number
183 )
184 self.tester.button('AC').click().run()
185 self.assertEqual(
186 self.tester.session_state['number'],
187 '0'
188 )
189
190 @unittest.skip
191 def test_streamlit_calculator_operations(self):
192 # first_number = '1'
193 first_number = tests.test_calculator.a_random_number()
194 first_number = str(first_number)
195 second_number = '2'
196
197 for character in first_number:
198 if character == '-':
199 self.tester.button('+/-').click().run()
200 else:
201 self.tester.button(character).click().run()
202 self.tester.button('+').click().run()
203 self.assertEqual(
204 self.tester.session_state['first_number'],
205 first_number
206 )
207
208 self.tester.button(second_number).click().run()
209 self.tester.button('=').click().run()
210 self.assertEqual(
211 self.tester.session_state['second_number'],
212 second_number
213 )
214
215 self.assertEqual(
216 self.tester.session_state['number'],
217 str(float(first_number) + float(second_number))
218 )
219
220
221# Exceptions seen
222# NameError
223# AttributeError
224# AssertionError
225# SyntaxError
226# KeyError
227# streamlit.errors.StreamlitDuplicateElementKey
228# TypeError
how to make a calculator 10: part 2: solutions
the code from calculator/src/streamlit_calculator.py from how to make a calculator 10: part 2
1import streamlit
2
3
4def show_number(display):
5 display.write(streamlit.session_state['number'])
6
7
8def plus_minus():
9 if streamlit.session_state['number'].startswith('-'):
10 number = streamlit.session_state['number'][1:]
11 else:
12 number = '-' + streamlit.session_state['number']
13 streamlit.session_state['number'] = number
14
15
16def backspace():
17 number = streamlit.session_state['number'][:-1]
18 streamlit.session_state['number'] = number
19
20
21def add_decimal():
22 if streamlit.session_state['number'].count('.') == 0:
23 streamlit.session_state['number'] += '.'
24
25
26def add_number_to_state(number):
27 if streamlit.session_state['number'] == '0':
28 streamlit.session_state['number'] = number
29 else:
30 streamlit.session_state['number'] += number
31
32
33def on_click(function, display, *value):
34 function(*value)
35 show_number(display)
36
37
38def add_buttons_to_column_1(column_1, display):
39 column_1.button(
40 label='<-', key='<-', width='stretch', on_click=on_click,
41 args=[backspace, display],
42 )
43 column_1.button(
44 label='7', key='7', width='stretch', on_click=on_click,
45 args=[add_number_to_state, display, '7'],
46 )
47 column_1.button(
48 label='4', key='4', width='stretch', on_click=on_click,
49 args=[add_number_to_state, display, '4'],
50 )
51 column_1.button(
52 label='1', key='1', width='stretch', on_click=on_click,
53 args=[add_number_to_state, display, '1'],
54 )
55 column_1.button(
56 label='+/-', key='+/-', width='stretch', on_click=on_click,
57 args=[plus_minus, display],
58 )
59
60
61def add_buttons_to_column_2(column_2, display):
62 column_2.button(
63 label='C', key='C', width='stretch', type='primary',
64 )
65 column_2.button(
66 label='8', key='8', width='stretch', on_click=on_click,
67 args=[add_number_to_state, display, '8'],
68 )
69 column_2.button(
70 label='5', key='5', width='stretch', on_click=on_click,
71 args=[add_number_to_state, display, '5'],
72 )
73 column_2.button(
74 label='2', key='2', width='stretch', on_click=on_click,
75 args=[add_number_to_state, display, '2'],
76 )
77 column_2.button(
78 label='0', key='0', width='stretch', on_click=on_click,
79 args=[add_number_to_state, display, '0'],
80 )
81
82
83def add_buttons_to_column_3(column_3, display):
84 column_3.button(
85 label='AC', key='AC', width='stretch', type='primary',
86 )
87 column_3.button(
88 label='9', key='9', width='stretch', on_click=on_click,
89 args=[add_number_to_state, display, '9'],
90 )
91 column_3.button(
92 label='6', key='6', width='stretch', on_click=on_click,
93 args=[add_number_to_state, display, '6'],
94 )
95 column_3.button(
96 label='3', key='3', width='stretch', on_click=on_click,
97 args=[add_number_to_state, display, '3'],
98 )
99 column_3.button(
100 label='.', key='.', width='stretch', on_click=on_click,
101 args=[add_decimal, display]
102 )
103
104
105def add_buttons_to_column_4(column_4):
106 column_4.button(
107 label='/', key='/', width='stretch', type='primary',
108 )
109 column_4.button(
110 label='X', key='X', width='stretch', type='primary',
111 )
112 column_4.button(
113 label=r'\-', key=r'\-', width='stretch', type='primary',
114 )
115 column_4.button(
116 label=r'\+', key=r'\+', width='stretch', type='primary',
117 )
118 column_4.button(
119 label='=', key='=', width='stretch', type='primary',
120 )
121
122
123def main():
124 streamlit.title('Calculator')
125 streamlit.session_state.setdefault('number', '0')
126 display = streamlit.container(border=True)
127
128 column_1, column_2, column_3, operations = streamlit.columns(4)
129 add_buttons_to_column_1(column_1, display)
130 add_buttons_to_column_2(column_2, display)
131 add_buttons_to_column_3(column_3, display)
132 add_buttons_to_column_4(operations)
133
134
135if __name__ == '__main__':
136 main()
how to make a calculator 10: part 3: tests
the code from calculator/tests/test_streamlit_calculator.py from how to make a calculator 10: part 3
1import random
2import streamlit.testing.v1
3import tests.test_calculator
4import unittest
5
6
7class TestStreamlitCalculator(unittest.TestCase):
8
9 def press_button(self, key):
10 self.tester.button(key).click().run()
11
12 def setUp(self):
13 self.tester = streamlit.testing.v1.AppTest.from_file(
14 'src/streamlit_calculator.py'
15 )
16 self.tester.run()
17
18 def test_streamlit_calculator_title(self):
19 self.assertEqual(self.tester.title[0].value, 'Calculator')
20
21 def test_streamlit_calculator_display(self):
22 display = (
23 self.tester.main.children[1].proto
24 .flex_container
25 )
26 self.assertEqual(display.gap_config.gap_size, 1)
27 self.assertEqual(display.direction, 1)
28 self.assertEqual(display.justify, 1)
29 self.assertEqual(display.align, 1)
30 self.assertTrue(display.border)
31
32 def test_streamlit_calculator_columns_and_buttons(self):
33 self.assertEqual(len(self.tester.columns), 4)
34
35 for column, keys in (
36 (0, ('<-', '7', '4', '1', '+/-')),
37 (1, ('C', '8', '5', '2', '0')),
38 (2, ('AC', '9', '6', '3', '.')),
39 (3, ('/', 'X', r'\-', r'\+', '=')),
40 ):
41 for key in keys:
42 with self.subTest(key=key):
43 self.assertEqual(
44 (
45 self.tester.columns[column]
46 .button(key)
47 .label
48 ),
49 key
50 )
51
52 def test_streamlit_calculator_operations_buttons(self):
53 for key in ('/', 'X', r'\-', r'\+', '=', 'C', 'AC'):
54 with self.subTest(key=key):
55 self.assertEqual(
56 self.tester.button(key).proto.type,
57 'primary'
58 )
59
60 def test_streamlit_session_state(self):
61 numbers = '0123456789'
62 self.assertEqual(self.tester.session_state['number'], '0')
63
64 expectation = random.choice(numbers)
65 while expectation == '0':
66 expectation = random.choice(numbers)
67 else:
68 self.press_button(expectation)
69
70 self.assertEqual(
71 self.tester.session_state['number'], expectation
72 )
73
74 for _ in range(0, len(numbers)):
75 a_random_number = random.choice(numbers)
76 self.press_button(a_random_number)
77 expectation += a_random_number
78
79 self.assertEqual(
80 self.tester.session_state['number'],
81 expectation
82 )
83
84 def test_streamlit_calculator_w_decimals(self):
85 for key in ('0.23.5.6.7.89'):
86 self.press_button(key)
87
88 self.assertEqual(
89 self.tester.session_state['number'],
90 '0.2356789'
91 )
92
93 def test_streamlit_calculator_backspace(self):
94 a_random_number = tests.test_calculator.a_random_number()
95 while a_random_number < 0:
96 a_random_number = tests.test_calculator.a_random_number()
97 a_random_number = str(a_random_number)
98
99 for key in a_random_number:
100 self.press_button(key)
101 self.press_button('<-')
102
103 self.assertEqual(
104 self.tester.session_state['number'],
105 a_random_number[:-1]
106 )
107
108 self.press_button('<-')
109 self.assertEqual(
110 self.tester.session_state['number'],
111 a_random_number[:-2]
112 )
113
114 def test_streamlit_calculator_w_plus_minus(self):
115 a_number = '963.0258741'
116 for key in a_number:
117 self.press_button(key)
118 self.assertEqual(
119 self.tester.session_state['number'], a_number
120 )
121
122 self.press_button('+/-')
123 self.assertEqual(
124 self.tester.session_state['number'], f'-{a_number}'
125 )
126
127 self.press_button('+/-')
128 self.assertEqual(
129 self.tester.session_state['number'], a_number
130 )
131
132
133# Exceptions seen
134# NameError
135# AttributeError
136# AssertionError
137# SyntaxError
138# KeyError
139# streamlit.errors.StreamlitDuplicateElementKey
how to make a calculator 10: part 3: solutions
the code from calculator/src/streamlit_calculator.py from how to make a calculator 10: part 3
1import streamlit
2
3
4def show_number(display):
5 display.write(streamlit.session_state['number'])
6
7
8def plus_minus():
9 if streamlit.session_state['number'].startswith('-'):
10 number = streamlit.session_state['number'][1:]
11 else:
12 number = '-' + streamlit.session_state['number']
13 streamlit.session_state['number'] = number
14
15
16def backspace():
17 number = streamlit.session_state['number'][:-1]
18 streamlit.session_state['number'] = number
19
20
21def add_decimal():
22 if streamlit.session_state['number'].count('.') == 0:
23 streamlit.session_state['number'] += '.'
24
25
26def add_number_to_state(number):
27 if streamlit.session_state['number'] == '0':
28 streamlit.session_state['number'] = number
29 else:
30 streamlit.session_state['number'] += number
31
32
33def on_click(function, display, *value):
34 function(*value)
35 show_number(display)
36
37
38def add_buttons_to_column_1(column_1, display):
39 column_1.button(
40 label='<-', key='<-', width='stretch', on_click=on_click,
41 args=[backspace, display],
42 )
43 column_1.button(
44 label='7', key='7', width='stretch', on_click=on_click,
45 args=[add_number_to_state, display, '7'],
46 )
47 column_1.button(
48 label='4', key='4', width='stretch', on_click=on_click,
49 args=[add_number_to_state, display, '4'],
50 )
51 column_1.button(
52 label='1', key='1', width='stretch', on_click=on_click,
53 args=[add_number_to_state, display, '1'],
54 )
55 column_1.button(
56 label='+/-', key='+/-', width='stretch', on_click=on_click,
57 args=[plus_minus, display],
58 )
59
60
61def add_buttons_to_column_2(column_2, display):
62 column_2.button(
63 label='C', key='C', width='stretch', type='primary',
64 )
65 column_2.button(
66 label='8', key='8', width='stretch', on_click=on_click,
67 args=[add_number_to_state, display, '8'],
68 )
69 column_2.button(
70 label='5', key='5', width='stretch', on_click=on_click,
71 args=[add_number_to_state, display, '5'],
72 )
73 column_2.button(
74 label='2', key='2', width='stretch', on_click=on_click,
75 args=[add_number_to_state, display, '2'],
76 )
77 column_2.button(
78 label='0', key='0', width='stretch', on_click=on_click,
79 args=[add_number_to_state, display, '0'],
80 )
81
82
83def add_buttons_to_column_3(column_3, display):
84 column_3.button(
85 label='AC', key='AC', width='stretch', type='primary',
86 )
87 column_3.button(
88 label='9', key='9', width='stretch', on_click=on_click,
89 args=[add_number_to_state, display, '9'],
90 )
91 column_3.button(
92 label='6', key='6', width='stretch', on_click=on_click,
93 args=[add_number_to_state, display, '6'],
94 )
95 column_3.button(
96 label='3', key='3', width='stretch', on_click=on_click,
97 args=[add_number_to_state, display, '3'],
98 )
99 column_3.button(
100 label='.', key='.', width='stretch', on_click=on_click,
101 args=[add_decimal, display]
102 )
103
104
105def add_buttons_to_column_4(column_4):
106 column_4.button(
107 label='/', key='/', width='stretch', type='primary',
108 )
109 column_4.button(
110 label='X', key='X', width='stretch', type='primary',
111 )
112 column_4.button(
113 label=r'\-', key=r'\-', width='stretch', type='primary',
114 )
115 column_4.button(
116 label=r'\+', key=r'\+', width='stretch', type='primary',
117 )
118 column_4.button(
119 label='=', key='=', width='stretch', type='primary',
120 )
121
122
123def main():
124 streamlit.title('Calculator')
125 streamlit.session_state.setdefault('number', '0')
126 display = streamlit.container(border=True)
127
128 column_1, column_2, column_3, operations = streamlit.columns(4)
129 add_buttons_to_column_1(column_1, display)
130 add_buttons_to_column_2(column_2, display)
131 add_buttons_to_column_3(column_3, display)
132 add_buttons_to_column_4(operations)
133
134
135if __name__ == '__main__':
136 main()
how to make a calculator 10: part 4: tests
the code from calculator/tests/test_streamlit_calculator.py from how to make a calculator 10: part 4
1import random
2import streamlit.testing.v1
3import tests.test_calculator
4import unittest
5
6
7class TestStreamlitCalculator(unittest.TestCase):
8
9 def setUp(self):
10 self.tester = streamlit.testing.v1.AppTest.from_file(
11 'src/streamlit_calculator.py'
12 )
13 self.tester.run()
14
15 def test_streamlit_calculator_title(self):
16 self.assertEqual(self.tester.title[0].value, 'Calculator')
17
18 def test_streamlit_calculator_display(self):
19 self.assertEqual(
20 self.tester.main.children[1].type,
21 'flex_container'
22 )
23
24 def test_streamlit_calculator_columns(self):
25 self.assertEqual(len(self.tester.columns), 4)
26 self.assertEqual(
27 self.tester.columns[0].button('<-').label,
28 '<-'
29 )
30 self.assertEqual(
31 self.tester.columns[0].button('7').label,
32 '7'
33 )
34 self.assertEqual(
35 self.tester.columns[0].button('4').label,
36 '4'
37 )
38 self.assertEqual(
39 self.tester.columns[0].button('1').label,
40 '1'
41 )
42 self.assertEqual(
43 self.tester.columns[0].button('+/-').label,
44 '+/-'
45 )
46 self.assertEqual(
47 self.tester.columns[1].button('C').label,
48 'C'
49 )
50 self.assertEqual(
51 self.tester.columns[1].button('8').label,
52 '8'
53 )
54 self.assertEqual(
55 self.tester.columns[1].button('5').label,
56 '5'
57 )
58 self.assertEqual(
59 self.tester.columns[1].button('2').label,
60 '2'
61 )
62 self.assertEqual(
63 self.tester.columns[1].button('0').label,
64 '0'
65 )
66
67 self.assertEqual(
68 self.tester.columns[2].button('AC').label,
69 'AC'
70 )
71 self.assertEqual(
72 self.tester.columns[2].button('9').label,
73 '9'
74 )
75 self.assertEqual(
76 self.tester.columns[2].button('6').label,
77 '6'
78 )
79 self.assertEqual(
80 self.tester.columns[2].button('3').label,
81 '3'
82 )
83 self.assertEqual(
84 self.tester.columns[2].button('.').label,
85 '.'
86 )
87
88 self.assertEqual(
89 self.tester.columns[3].button('/').label,
90 '/'
91 )
92 self.assertEqual(
93 self.tester.columns[3].button('X').label,
94 'X'
95 )
96 self.assertEqual(
97 self.tester.columns[3].button('-').label,
98 r'\-'
99 )
100 self.assertEqual(
101 self.tester.columns[3].button('+').label,
102 r'\+'
103 )
104 self.assertEqual(
105 self.tester.columns[3].button('=').label,
106 '='
107 )
108
109 def test_streamlit_session_state(self):
110 expectation = '0'
111 for _ in range(0, 10):
112 number = random.choice('0123456789')
113 (
114 self.tester.button(number)
115 .click().run()
116 )
117 if expectation == '0':
118 expectation = number
119 else:
120 expectation += number
121 self.assertEqual(
122 self.tester.session_state['number'],
123 expectation
124 )
125
126 def test_streamlit_calculator_w_decimals(self):
127 for button in ('0.23.5.6.7.8.9'):
128 (
129 self.tester.button(button)
130 .click().run()
131 )
132 self.assertEqual(
133 self.tester.session_state['number'],
134 '.2356789'
135 )
136
137 def test_streamlit_calculator_w_plus_minus(self):
138 number = '963.0258741'
139 for button in number:
140 (
141 self.tester.button(button)
142 .click().run()
143 )
144 self.tester.button('+/-').click().run()
145 self.assertEqual(
146 self.tester.session_state['number'],
147 f'-{number}'
148 )
149
150 self.tester.session_state['number'] = '0'
151 number = '-963.0258741'
152 for button in number:
153 (
154 self.tester.button(button)
155 .click().run()
156 )
157
158 self.tester.button('+/-').click().run()
159 self.assertEqual(
160 self.tester.session_state['number'],
161 number[1:]
162 )
163
164 def test_streamlit_calculator_reset_state(self):
165 numbers = '123456789'
166 number = random.choice(numbers)
167 self.tester.button(number).click().run()
168 self.assertEqual(
169 self.tester.session_state['number'],
170 number
171 )
172 self.tester.button('C').click().run()
173 self.assertEqual(
174 self.tester.session_state['number'],
175 '0'
176 )
177
178 number = random.choice(numbers)
179 self.tester.button(number).click().run()
180 self.assertEqual(
181 self.tester.session_state['number'],
182 number
183 )
184 self.tester.button('AC').click().run()
185 self.assertEqual(
186 self.tester.session_state['number'],
187 '0'
188 )
189
190 @unittest.skip
191 def test_streamlit_calculator_operations(self):
192 # first_number = '1'
193 first_number = tests.test_calculator.a_random_number()
194 first_number = str(first_number)
195 second_number = '2'
196
197 for character in first_number:
198 if character == '-':
199 self.tester.button('+/-').click().run()
200 else:
201 self.tester.button(character).click().run()
202 self.tester.button('+').click().run()
203 self.assertEqual(
204 self.tester.session_state['first_number'],
205 first_number
206 )
207
208 self.tester.button(second_number).click().run()
209 self.tester.button('=').click().run()
210 self.assertEqual(
211 self.tester.session_state['second_number'],
212 second_number
213 )
214
215 self.assertEqual(
216 self.tester.session_state['number'],
217 str(float(first_number) + float(second_number))
218 )
219
220
221# Exceptions seen
222# NameError
223# AttributeError
224# AssertionError
225# SyntaxError
226# KeyError
227# streamlit.errors.StreamlitDuplicateElementKey
228# TypeError
how to make a calculator 10: part 4: solutions
the code from calculator/src/streamlit_calculator.py from how to make a calculator 10: part 4
1import streamlit
2
3
4def show_number(display):
5 display.write(streamlit.session_state['number'])
6
7
8def plus_minus():
9 if streamlit.session_state['number'].startswith('-'):
10 number = streamlit.session_state['number'][1:]
11 else:
12 number = '-' + streamlit.session_state['number']
13 streamlit.session_state['number'] = number
14
15
16def backspace():
17 number = streamlit.session_state['number'][:-1]
18 streamlit.session_state['number'] = number
19
20
21def add_decimal():
22 if streamlit.session_state['number'].count('.') == 0:
23 streamlit.session_state['number'] += '.'
24
25
26def add_number_to_state(number):
27 if streamlit.session_state['number'] == '0':
28 streamlit.session_state['number'] = number
29 else:
30 streamlit.session_state['number'] += number
31
32
33def on_click(function, display, *value):
34 function(*value)
35 show_number(display)
36
37
38def add_buttons_to_column_1(column_1, display):
39 column_1.button(
40 label='<-', key='<-', width='stretch', on_click=on_click,
41 args=[backspace, display],
42 )
43 column_1.button(
44 label='7', key='7', width='stretch', on_click=on_click,
45 args=[add_number_to_state, display, '7'],
46 )
47 column_1.button(
48 label='4', key='4', width='stretch', on_click=on_click,
49 args=[add_number_to_state, display, '4'],
50 )
51 column_1.button(
52 label='1', key='1', width='stretch', on_click=on_click,
53 args=[add_number_to_state, display, '1'],
54 )
55 column_1.button(
56 label='+/-', key='+/-', width='stretch', on_click=on_click,
57 args=[plus_minus, display],
58 )
59
60
61def add_buttons_to_column_2(column_2, display):
62 column_2.button(
63 label='C', key='C', width='stretch', type='primary',
64 )
65 column_2.button(
66 label='8', key='8', width='stretch', on_click=on_click,
67 args=[add_number_to_state, display, '8'],
68 )
69 column_2.button(
70 label='5', key='5', width='stretch', on_click=on_click,
71 args=[add_number_to_state, display, '5'],
72 )
73 column_2.button(
74 label='2', key='2', width='stretch', on_click=on_click,
75 args=[add_number_to_state, display, '2'],
76 )
77 column_2.button(
78 label='0', key='0', width='stretch', on_click=on_click,
79 args=[add_number_to_state, display, '0'],
80 )
81
82
83def add_buttons_to_column_3(column_3, display):
84 column_3.button(
85 label='AC', key='AC', width='stretch', type='primary',
86 )
87 column_3.button(
88 label='9', key='9', width='stretch', on_click=on_click,
89 args=[add_number_to_state, display, '9'],
90 )
91 column_3.button(
92 label='6', key='6', width='stretch', on_click=on_click,
93 args=[add_number_to_state, display, '6'],
94 )
95 column_3.button(
96 label='3', key='3', width='stretch', on_click=on_click,
97 args=[add_number_to_state, display, '3'],
98 )
99 column_3.button(
100 label='.', key='.', width='stretch', on_click=on_click,
101 args=[add_decimal, display]
102 )
103
104
105def add_buttons_to_column_4(column_4):
106 column_4.button(
107 label='/', key='/', width='stretch', type='primary',
108 )
109 column_4.button(
110 label='X', key='X', width='stretch', type='primary',
111 )
112 column_4.button(
113 label=r'\-', key=r'\-', width='stretch', type='primary',
114 )
115 column_4.button(
116 label=r'\+', key=r'\+', width='stretch', type='primary',
117 )
118 column_4.button(
119 label='=', key='=', width='stretch', type='primary',
120 )
121
122
123def main():
124 streamlit.title('Calculator')
125 streamlit.session_state.setdefault('number', '0')
126 display = streamlit.container(border=True)
127
128 column_1, column_2, column_3, operations = streamlit.columns(4)
129 add_buttons_to_column_1(column_1, display)
130 add_buttons_to_column_2(column_2, display)
131 add_buttons_to_column_3(column_3, display)
132 add_buttons_to_column_4(operations)
133
134
135if __name__ == '__main__':
136 main()