Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
from dataclasses import replace
from typing import List, Sequence
from .todo_item import Todo ← from todo.item ^1.0.0 · built alongside by fune
from .todo_item_validate_draft import is_iso_date
from .todo_list_add_todo import require_utc_now ← addTodo, another function of this group · built into the same file, even by a slim install
from .todo_list_update_todo import index_of_todo ← updateTodo, another function of this group · built into the same file, even by a slim install
from .todo_next_occurrence import next_occurrence ← from todo.next-occurrence ^1.0.0 · built alongside by fune
def require_today(today: str) -> None:
"""Refuse a today that is not a real YYYY-MM-DD date, whether or not a repeat needs it."""
if not is_iso_date(today):
raise ValueError("today must be a date like 2026-09-28")
def complete_todo(todo: Todo, now: str, today: str) -> Todo:
"""Complete one open todo; a repeating one stays open and rolls forward to its next occurrence."""
if todo.recurrence is None:
return replace(todo, done=True, completed_at=now)
if todo.due is None:
raise ValueError(f'repeating todo "{todo.id}" has no due date')
return replace(todo, done=False, completed_at=None, due=next_occurrence(todo.recurrence, todo.due, today))
def toggle_todo(todos: Sequence[Todo], id: str, now: str, today: str) -> List[Todo]:
"""Tick or untick one todo. Reopening clears the completion time."""
at = index_of_todo(todos, id)
require_utc_now(now)
require_today(today)
out = list(todos)
t = todos[at]
out[at] = replace(t, done=False, completed_at=None) if t.done else complete_todo(t, now, today)
return out