Functional Weave
Code in Rust

todo.group-by-due@1.1.0

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