impl/python/group_by_due_with_order.py
1,445 bytes · the Python implementation · view raw
Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
import json
from typing import List, Sequence
from .dates_day_of_week import day_of_week ← from dates.day-of-week ^1.0.0 · built alongside by fune
from .todo_due_status import due_status ← from todo.due-status ^1.0.0 · built alongside by fune
from .todo_group_by_due_types import DueGroup, SectionOrder
from .todo_item import Todo ← from todo.item ^1.0.0 · built alongside by fune
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_with_order(todos: Sequence[Todo], today: str, order: SectionOrder) -> List[DueGroup]:
"""Todos in planner sections; order "due" sorts the multi-date sections by date, "input" keeps input order."""
if order not in ("due", "input"):
raise ValueError(f'order must be "due" or "input", found {json.dumps(order)}')
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 order == "due" and 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