Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
29 changes: 25 additions & 4 deletions task_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand All @@ -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()
31 changes: 29 additions & 2 deletions tests/test_task_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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()