From 7f29b7949c28b667728f41bd62de95666ab12446 Mon Sep 17 00:00:00 2001 From: MrParamecium <2739441541@qq.com> Date: Sat, 18 Jul 2026 21:02:47 +0800 Subject: [PATCH 1/4] feat: add complete task command Added functionality to complete tasks by task number. --- task_tracker.py | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/task_tracker.py b/task_tracker.py index ed7792a..4cbc14d 100644 --- a/task_tracker.py +++ b/task_tracker.py @@ -23,15 +23,27 @@ def add_task(tasks, title): return tasks +def complete_task(tasks, task_number): + if task_number < 1 or task_number > len(tasks): + raise ValueError("task number is out of range") + tasks[task_number - 1]["done"] = True + return tasks + + def render_tasks(tasks): if not tasks: return "No tasks yet." - return "\n".join(f"- [{'x' if task['done'] else ' '}] {task['title']}" for task in tasks) + return "\n".join( + f"- [{'x' if task['done'] else ' '}] {task['title']}" + for task in tasks + ) def main(): - parser = argparse.ArgumentParser(description="A tiny task tracker for PR practice") - parser.add_argument("command", choices=["list", "add"]) + parser = argparse.ArgumentParser( + description="A tiny task tracker for PR practice" + ) + parser.add_argument("command", choices=["list", "add", "complete"]) parser.add_argument("title", nargs="?") args = parser.parse_args() @@ -44,6 +56,15 @@ def main(): parser.error(str(error)) save_tasks(tasks) print(f"Added: {args.title}") + elif args.command == "complete": + if args.title is None or not args.title.isdigit(): + parser.error("task number must be a positive integer") + try: + tasks = complete_task(load_tasks(), int(args.title)) + except ValueError as error: + parser.error(str(error)) + save_tasks(tasks) + print(f"Completed task {args.title}") if __name__ == "__main__": From 4317b7102adf1f30a2fbb4ff3fb2e68b84d19e96 Mon Sep 17 00:00:00 2001 From: MrParamecium <2739441541@qq.com> Date: Sat, 18 Jul 2026 21:04:57 +0800 Subject: [PATCH 2/4] test: cover complete task behavior From eeaf9bff351b65f6d9edc2f24d372df0248066ae Mon Sep 17 00:00:00 2001 From: MrParamecium <2739441541@qq.com> Date: Sat, 18 Jul 2026 21:06:37 +0800 Subject: [PATCH 3/4] docs: document complete command --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 049aeb3..1ff502e 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ This private repository is a hands-on sandbox for learning pull requests. ```bash python3 task_tracker.py list python3 task_tracker.py add "Review a pull request" +python3 task_tracker.py complete 1 ``` ## Run tests From ec4bed6d1d70fad328a31e03957b9c2263656ecb Mon Sep 17 00:00:00 2001 From: MrParamecium <2739441541@qq.com> Date: Sat, 18 Jul 2026 22:04:53 +0800 Subject: [PATCH 4/4] test: add complete task coverage --- tests/test_task_tracker.py | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/tests/test_task_tracker.py b/tests/test_task_tracker.py index 8d2ac5e..608e654 100644 --- a/tests/test_task_tracker.py +++ b/tests/test_task_tracker.py @@ -2,7 +2,13 @@ import unittest from pathlib import Path -from task_tracker import add_task, load_tasks, render_tasks, save_tasks +from task_tracker import ( + add_task, + complete_task, + load_tasks, + render_tasks, + save_tasks, +) class TaskTrackerTests(unittest.TestCase): @@ -27,9 +33,30 @@ def test_add_and_save_task(self): ) def test_add_task_rejects_blank_title(self): - with self.assertRaisesRegex(ValueError, "task title cannot be empty"): + with self.assertRaisesRegex( + ValueError, + "task title cannot be empty", + ): add_task([], " ") + def test_complete_task_marks_selected_task_done(self): + tasks = [ + {"title": "First task", "done": False}, + {"title": "Second task", "done": False}, + ] + + result = complete_task(tasks, 2) + + self.assertFalse(result[0]["done"]) + self.assertTrue(result[1]["done"]) + + def test_complete_task_rejects_out_of_range_number(self): + with self.assertRaisesRegex( + ValueError, + "task number is out of range", + ): + complete_task([], 1) + if __name__ == "__main__": unittest.main()