from typing import List, Sequence from .dates_day_of_week import day_of_week from .todo_due_status import due_status from .todo_group_by_due_types import DueGroup from .todo_item import Todo SECTIONS = [ ("overdue", "Overdue"), ("today", "Today"), ("tomorrow", "Tomorrow"), ("this-week", "This week"), ("later", "Later"), ("none", "No date"), ("done", "Done"), ] SORTED_BY_DUE = ("overdue", "this-week", "later") def group_by_due(todos: Sequence[Todo], today: str) -> List[DueGroup]: """Todos in planner sections, fixed order, empty sections left out.""" day_of_week(today) # a bad today is an error even for an empty list statuses = [due_status(todo, today) for todo in todos] groups: List[DueGroup] = [] for status, title in SECTIONS: members = [todo for todo, s in zip(todos, statuses) if s == status] if not members: continue if status in SORTED_BY_DUE: # sorted is stable, so equal dates keep input order. members = sorted(members, key=lambda todo: todo.due or "") groups.append(DueGroup(status=status, title=title, todos=members)) # type: ignore[arg-type] return groups