Fix calculator bugs and add calculation history feature

#3
Files changed (1) hide show
  1. gradio_calculator.py +87 -27
gradio_calculator.py CHANGED
@@ -1,41 +1,101 @@
1
  import gradio as gr
2
 
3
 
4
- def calculate(num1, num2, operation):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  try:
6
- num1 = float(num1)
7
- num2 = float(num2)
8
-
9
- if operation == "+":
10
- result = num1 + num2
11
- elif operation == "-":
12
- result = num1 - num2
13
- elif operation == "*":
14
- result = num1 * num2
15
- elif operation == "/":
16
- if num2 == 0:
17
- return "Cannot divide by zero"
18
- result = num1 / num2
19
- else:
20
- return "Invalid operation"
21
-
22
- return result
23
- except ValueError:
24
- return "Please enter valid numbers"
25
-
26
-
27
- with gr.Blocks() as demo:
 
 
 
 
 
 
 
 
 
 
 
 
28
  gr.Markdown("# Simple Calculator")
29
 
 
 
 
30
  with gr.Row():
31
  num1 = gr.Number(label="First number")
32
  operation = gr.Dropdown(["+", "-", "*", "/"], label="Operation", value="+")
33
  num2 = gr.Number(label="Second number")
34
 
35
- calc_button = gr.Button("Calculate")
36
- output = gr.Textbox(label="Result")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
- calc_button.click(fn=calculate, inputs=[num1, num2, operation], outputs=output)
 
 
 
 
 
39
 
40
 
41
- demo.launch()
 
 
1
  import gradio as gr
2
 
3
 
4
+ def format_number(x: float) -> str:
5
+ # FIX (Bug 3): format the result so users never see float noise
6
+ # such as 0.30000000000000004 for 0.1 + 0.2.
7
+ if x == int(x) and abs(x) < 1e15:
8
+ return str(int(x))
9
+ return f"{x:.10g}"
10
+
11
+
12
+ def render_history(history: list) -> str:
13
+ # NEW FEATURE: render the history list as numbered Markdown lines.
14
+ if not history:
15
+ return "_No calculations yet._"
16
+ return "\n".join(f"{i + 1}. {entry}" for i, entry in enumerate(history))
17
+
18
+
19
+ def calculate(num1, num2, operation, history):
20
+ history = history or []
21
+
22
+ # FIX (Bug 2): gr.Number returns None for empty fields, and float(None)
23
+ # raises TypeError (not ValueError), which crashed the app. Guard first.
24
+ if num1 is None or num2 is None:
25
+ return "Please enter both numbers", history, render_history(history)
26
+
27
  try:
28
+ a = float(num1)
29
+ b = float(num2)
30
+ except (ValueError, TypeError):
31
+ return "Please enter valid numbers", history, render_history(history)
32
+
33
+ if operation == "+":
34
+ result = a + b
35
+ elif operation == "-":
36
+ result = a - b
37
+ elif operation == "*":
38
+ result = a * b
39
+ elif operation == "/":
40
+ if b == 0:
41
+ return "Cannot divide by zero", history, render_history(history)
42
+ result = a / b
43
+ else:
44
+ return "Invalid operation", history, render_history(history)
45
+
46
+ result_text = format_number(result)
47
+
48
+ # NEW FEATURE: append this successful calculation to the history and
49
+ # return the updated list plus its rendered form.
50
+ entry = f"{format_number(a)} {operation} {format_number(b)} = {result_text}"
51
+ history = history + [entry]
52
+
53
+ return result_text, history, render_history(history)
54
+
55
+
56
+ def clear_history():
57
+ # NEW FEATURE: reset history to empty when Clear History is clicked.
58
+ return [], "_No calculations yet._"
59
+
60
+
61
+ with gr.Blocks(title="Simple Calculator") as demo:
62
  gr.Markdown("# Simple Calculator")
63
 
64
+ # NEW FEATURE: per-session storage for the calculation history.
65
+ history_state = gr.State([])
66
+
67
  with gr.Row():
68
  num1 = gr.Number(label="First number")
69
  operation = gr.Dropdown(["+", "-", "*", "/"], label="Operation", value="+")
70
  num2 = gr.Number(label="Second number")
71
 
72
+ with gr.Row():
73
+ calc_button = gr.Button("Calculate", variant="primary")
74
+ # NEW FEATURE: button to clear the history.
75
+ clear_button = gr.Button("Clear History")
76
+
77
+ output = gr.Textbox(label="Result", interactive=False)
78
+
79
+ # NEW FEATURE: collapsible panel showing past calculations.
80
+ with gr.Accordion("History", open=True):
81
+ history_display = gr.Markdown("_No calculations yet._")
82
+
83
+ # FIX (Bug 1): inputs must be in the order calculate() expects
84
+ # (num1, num2, operation). The original passed them swapped, so every
85
+ # calculation failed with "Please enter valid numbers".
86
+ calc_button.click(
87
+ fn=calculate,
88
+ inputs=[num1, num2, operation, history_state],
89
+ outputs=[output, history_state, history_display],
90
+ )
91
 
92
+ # NEW FEATURE: wire the Clear History button.
93
+ clear_button.click(
94
+ fn=clear_history,
95
+ inputs=None,
96
+ outputs=[history_state, history_display],
97
+ )
98
 
99
 
100
+ if __name__ == "__main__":
101
+ demo.launch()