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 diff --git a/task_tracker.py b/task_tracker.py index e6de844..819d502 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("value", nargs="?") args = parser.parse_args() @@ -44,7 +56,16 @@ def main(): parser.error(str(error)) save_tasks(tasks) print(f"Added: {args.value}") + elif args.command == "complete": + if args.value is None or not args.value.isdigit(): + parser.error("task number must be a positive integer") + try: + tasks = complete_task(load_tasks(), int(args.value)) + except ValueError as error: + parser.error(str(error)) + save_tasks(tasks) + print(f"Completed task {args.value}") if __name__ == "__main__": - main() + main() \ No newline at end of file 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()