-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtodo_app.py
More file actions
117 lines (101 loc) · 3.92 KB
/
Copy pathtodo_app.py
File metadata and controls
117 lines (101 loc) · 3.92 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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# ==========================================
# Python Learning Lab: CLI Todo List Application
# ==========================================
# This is a guided project. You will build a CLI application that:
# 1. Adds tasks to a list.
# 2. Views all active tasks.
# 3. Marks tasks as completed.
# 4. Saves tasks to a JSON file (`todo_list.json`) so they persist.
# 5. Loads tasks from the JSON file on startup.
#
# Instructions:
# - Fill in the # TODO placeholders.
# - Run the application: `python todo_app.py` and interact with the menu!
import os
import json
TODO_FILE = "todo_list.json"
def load_tasks():
"""Load tasks from the JSON database file. Return a list of dictionaries."""
if not os.path.exists(TODO_FILE):
return []
# TODO: Open TODO_FILE in read mode, load JSON data, and return it.
# Each task dictionary should look like: {"title": "Task Name", "completed": False}
try:
with open(TODO_FILE, "r") as f:
return json.load(f)
except Exception:
return []
def save_tasks(tasks):
"""Save tasks list to the JSON database file."""
# TODO: Open TODO_FILE in write mode and dump the tasks list using json.dump().
with open(TODO_FILE, "w") as f:
json.dump(tasks, f, indent=4)
def show_menu():
print("\n--- CLI Todo List Manager ---")
print("1. View Tasks")
print("2. Add Task")
print("3. Complete Task")
print("4. Exit")
def view_tasks(tasks):
if not tasks:
print("\nNo tasks found! Add some tasks first.")
return
print("\n--- Current Tasks ---")
for i, task in enumerate(tasks, 1):
status = "✓" if task["completed"] else " "
print(f"{i}. [{status}] {task['title']}")
def main():
tasks = load_tasks()
while True:
show_menu()
choice = input("\nEnter choice (1-4): ").strip()
if choice == "1":
view_tasks(tasks)
elif choice == "2":
title = input("Enter task description: ").strip()
if title:
# TODO: Append the new task as a dictionary to `tasks` and save the list
new_task = {"title": title, "completed": False}
tasks.append(new_task)
save_tasks(tasks)
print(f"Added task: '{title}'")
else:
print("Task title cannot be empty.")
elif choice == "3":
view_tasks(tasks)
if not tasks:
continue
try:
num = int(input("Enter task number to mark complete: ").strip())
if 1 <= num <= len(tasks):
# TODO: Set the task's "completed" field to True, and save the list
tasks[num - 1]["completed"] = True
save_tasks(tasks)
print(f"Task {num} marked completed!")
else:
print("Invalid task number.")
except ValueError:
print("Please enter a valid number.")
elif choice == "4":
print("\nGoodbye!")
break
else:
print("Invalid selection. Please choose 1, 2, 3, or 4.")
if __name__ == "__main__":
# If running interactively, call main()
# To run test assertions in headless mode:
# Set run_interactive to True to use CLI
run_interactive = False
if run_interactive:
main()
else:
# Dry-run test assertions to check structure
test_tasks = [{"title": "Learn OOP", "completed": False}]
save_tasks(test_tasks)
loaded = load_tasks()
assert len(loaded) == 1, "Failed to load/save tasks"
assert loaded[0]["title"] == "Learn OOP", "Task title did not match"
# Cleanup
if os.path.exists(TODO_FILE):
os.remove(TODO_FILE)
print("Todo App structure verified successfully! Switch 'run_interactive' to True to play with it!")