CODSOFT-TO-DO-LIST
π Exciting News: Built My First To-Do List App in Python! I am thrilled to share a project Iβve been working on recently: a functional To-Do List Application built entirely using Python! ππ
Author- Prem Somnath Sonawane
https://ai.studio/apps/2d690c27-9353-45d6-8132-bf8bd64f7412?fullscreenApplet=true
Python To-Do Application Studio
PEP 8 Gated
Compare clean Object-Oriented Tkinter GUI & Functional Streamlined CLI with Sandbox Simulators
Option 1: todo_cli.py
"""
Implementation 1: Command-Line Interface (CLI) To-Do List App
Features persistent storage using 'todo_list.json' and handles basic error cases.
Follows PEP 8 guidelines.
"""
import os
import json
FILENAME = "todo_list.json"
def load_tasks():
"""Loads tasks from a JSON file, returning a list of task dicts."""
if not os.path.exists(FILENAME):
return []
try:
with open(FILENAME, "r", encoding="utf-8") as file:
return json.load(file)
except (json.JSONDecodeError, IOError):
print("Warning: Could not read 'todo_list.json'. Creating a new task list.")
return []
def save_tasks(tasks):
"""Saves the current tasks list to a JSON file."""
try:
with open(FILENAME, "w", encoding="utf-8") as file:
json.dump(tasks, file, indent=4)
except IOError:
print("Error: Could not save tasks to file.")
def display_tasks(tasks):
"""Prints all active and completed tasks in a readable format."""
if not tasks:
print("\nYour to-do list is empty.")
return
print("\n--- Current To-Do List ---")
for idx, task in enumerate(tasks, start=1):
status = "[β] Completed" if task.get("completed") else "[β] Pending"
print(f"{idx}. {task['title']} - {status}")
def add_task(tasks):
"""Prompts the user to add a task, validating input."""
title = input("\nEnter the task description: ").strip()
if not title:
print("Error: Task description cannot be empty or just whitespace.")
return
tasks.append({"title": title, "completed": False})
save_tasks(tasks)
print(f"Task '{title}' added successfully!")
def update_task(tasks):
"""Marks a task as completed."""
if not tasks:
print("\nNo tasks available to update.")
return
display_tasks(tasks)
try:
choice = int(input("\nEnter the number of the task to mark as completed: "))
if 1 <= choice <= len(tasks):
tasks[choice - 1]["completed"] = True
save_tasks(tasks)
print(f"Task '{tasks[choice - 1]['title']}' marked as completed.")
else:
print("Error: Invalid task number.")
except ValueError:
print("Error: Please enter a valid integer task number.")
def delete_task(tasks):
"""Deletes a selected task."""
if not tasks:
print("\nNo tasks available to delete.")
return
display_tasks(tasks)
try:
choice = int(input("\nEnter the number of the task to delete: "))
if 1 <= choice <= len(tasks):
removed = tasks.pop(choice - 1)
save_tasks(tasks)
print(f"Task '{removed['title']}' deleted successfully.")
else:
print("Error: Invalid task number.")
except ValueError:
print("Error: Please enter a valid integer task number.")
def main():
"""Main terminal execution loop."""
tasks = load_tasks()
while True:
print("\n=========================")
print(" Python To-Do CLI")
print("=========================")
print("1. View Tasks")
print("2. Add Task")
print("3. Update/Complete Task")
print("4. Delete Task")
print("5. Exit")
choice = input("\nEnter your choice (1-5): ").strip()
if choice == "1":
display_tasks(tasks)
elif choice == "2":
add_task(tasks)
elif choice == "3":
update_task(tasks)
elif choice == "4":
delete_task(tasks)
elif choice == "5":
print("\nExiting To-Do App. Goodbye!")
break
else:
print("Error: Invalid choice. Please choose a number from 1 to 5.")
if name == "main":
main()
OUTPUT:
Python 3.11.4 (main, Jun 8 2026, 19:13:17)
[GCC 11.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
python todo_cli.py
=========================
Python To-Do CLI
=========================
-
View Tasks
-
Add Task
-
Update/Complete Task
-
Delete Task
-
Exit
Enter your choice (1-5):
=========================
Python To-Do CLI
=========================
-
View Tasks
-
Add Task
-
Update/Complete Task
-
Delete Task
-
Exit
Enter your choice (1-5):
Option 2: todo_gui.py
"""
Implementation 2: Graphical User Interface (GUI) To-Do List App
Uses Python's native 'tkinter' library and native messagebox popups.
Follows PEP 8 guidelines.
"""
import tkinter as tk
from tkinter import messagebox
import json
import os
FILENAME = "todo_list.json"
class TodoGUIApp:
def init(self, root):
self.root = root
self.root.title("Python To-Do List Application")
self.root.geometry("480x520")
self.root.minsize(400, 450)
self.root.configure(bg="#f4f6fa")
self.tasks = self.load_tasks()
# UI Styling & Fonts
self.title_font = ("Helvetica", 16, "bold")
self.label_font = ("Helvetica", 10)
self.btn_font = ("Helvetica", 10, "bold")
self.create_widgets()
self.populate_listbox()
def load_tasks(self):
"""Loads tasks from a JSON file, returning a list of task dicts."""
if not os.path.exists(FILENAME):
return []
try:
with open(FILENAME, "r", encoding="utf-8") as file:
return json.load(file)
except (json.JSONDecodeError, IOError):
return []
def save_tasks(self):
"""Saves current state of tasks to 'todo_list.json'."""
try:
with open(FILENAME, "w", encoding="utf-8") as file:
json.dump(self.tasks, file, indent=4)
except IOError:
messagebox.showerror("Error", "Could not save tasks to file.")
def create_widgets(self):
"""Builds all native tkinter components of the application."""
# Top Title Frame
title_frame = tk.Frame(self.root, bg="#f4f6fa", pady=10)
title_frame.pack(fill=tk.X)
title_label = tk.Label(
title_frame,
text="β
To-Do Tasks Manager β
",
font=self.title_font,
bg="#f4f6fa",
fg="#2c3e50"
)
title_label.pack()
# Input Frame (Entry + Button)
input_frame = tk.Frame(self.root, bg="#f4f6fa", padx=15, pady=5)
input_frame.pack(fill=tk.X)
self.task_entry = tk.Entry(
input_frame,
font=("Helvetica", 11),
bd=1,
relief=tk.SOLID
)
self.task_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, ipady=4, padx=(0, 10))
self.task_entry.bind("<Return>", lambda event: self.add_task())
add_btn = tk.Button(
input_frame,
text="Add Task",
font=self.btn_font,
bg="#3498db",
fg="white",
activebackground="#2980b9",
activeforeground="white",
relief=tk.FLAT,
padx=15,
pady=4,
command=self.add_task
)
add_btn.pack(side=tk.RIGHT)
# Central Listbox Frame with scrollbar
list_frame = tk.Frame(self.root, bg="#f4f6fa", padx=15, pady=10)
list_frame.pack(fill=tk.BOTH, expand=True)
self.scrollbar = tk.Scrollbar(list_frame)
self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.task_listbox = tk.Listbox(
list_frame,
font=("Helvetica", 11),
bd=1,
relief=tk.SOLID,
selectbackground="#95a5a6",
selectforeground="white",
yscrollcommand=self.scrollbar.set
)
self.task_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
self.scrollbar.config(command=self.task_listbox.yview)
# Buttons Control Frame
ctrl_frame = tk.Frame(self.root, bg="#f4f6fa", padx=15, pady=15)
ctrl_frame.pack(fill=tk.X)
complete_btn = tk.Button(
ctrl_frame,
text="Complete Task",
font=self.btn_font,
bg="#2ecc71",
fg="white",
activebackground="#27ae60",
activeforeground="white",
relief=tk.FLAT,
pady=8,
command=self.complete_task
)
complete_btn.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(0, 10))
delete_btn = tk.Button(
ctrl_frame,
text="Delete Task",
font=self.btn_font,
bg="#e74c3c",
fg="white",
activebackground="#c0392b",
activeforeground="white",
relief=tk.FLAT,
pady=8,
command=self.delete_task
)
delete_btn.pack(side=tk.RIGHT, fill=tk.X, expand=True)
def populate_listbox(self):
"""Clears and refills the Listbox with formatted task strings."""
self.task_listbox.delete(0, tk.END)
for task in self.tasks:
# Change icon indicators to represent state
status_indicator = "β" if task.get("completed") else "β"
self.task_listbox.insert(tk.END, f" [{status_indicator}] {task['title']}")
def add_task(self):
"""Add new task validation and storage."""
title = self.task_entry.get().strip()
if not title:
# Trigger popup warnings for empty task
messagebox.showwarning("Warning", "Cannot add an empty task. Please enter some text.")
return
self.tasks.append({"title": title, "completed": False})
self.save_tasks()
self.populate_listbox()
self.task_entry.delete(0, tk.END)
def get_selected_index(self):
"""Helper to get and check selected task index. Raises warning message if none."""
try:
index = self.task_listbox.curselection()[0]
return index
except IndexError:
# Prompt warning if button clicked without active selection
messagebox.showwarning("Warning", "Please select a task from the listbox first.")
return None
def complete_task(self):
"""Marks selected task as completed."""
idx = self.get_selected_index()
if idx is not None:
self.tasks[idx]["completed"] = True
self.save_tasks()
self.populate_listbox()
self.task_listbox.selection_set(idx)
def delete_task(self):
"""Deletes selected task."""
idx = self.get_selected_index()
if idx is not None:
self.tasks.pop(idx)
self.save_tasks()
self.populate_listbox()
if name == "main":
app_root = tk.Tk()
app = TodoGUIApp(app_root)
app_root.mainloop()