generated from coulomb/repo-seed
85 lines
2.3 KiB
Python
85 lines
2.3 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
CANONICAL_TASK_STATUSES: tuple[str, ...] = (
|
|
"wait",
|
|
"todo",
|
|
"progress",
|
|
"done",
|
|
"cancel",
|
|
)
|
|
|
|
TASK_STATUS_CODES: dict[str, str] = {
|
|
"WAIT": "wait",
|
|
"TODO": "todo",
|
|
"PROG": "progress",
|
|
"DONE": "done",
|
|
"CNCL": "cancel",
|
|
}
|
|
|
|
LEGACY_TASK_STATUS_ALIASES: dict[str, str] = {
|
|
"blocked": "wait",
|
|
"waiting": "wait",
|
|
"in_progress": "progress",
|
|
"in-progress": "progress",
|
|
"prog": "progress",
|
|
"cancelled": "cancel",
|
|
"canceled": "cancel",
|
|
"cncl": "cancel",
|
|
}
|
|
|
|
OPEN_TASK_STATUSES: frozenset[str] = frozenset({"wait", "todo", "progress"})
|
|
ACTIVE_TASK_STATUSES: frozenset[str] = frozenset({"wait", "progress"})
|
|
TERMINAL_TASK_STATUSES: frozenset[str] = frozenset({"done", "cancel"})
|
|
|
|
TASK_STATUS_ORDER: dict[str, int] = {
|
|
"todo": 0,
|
|
"wait": 1,
|
|
"progress": 1,
|
|
"done": 2,
|
|
"cancel": 2,
|
|
}
|
|
|
|
TASK_STATUS_LABELS: dict[str, str] = {
|
|
"wait": "wait",
|
|
"todo": "todo",
|
|
"progress": "progress",
|
|
"done": "done",
|
|
"cancel": "cancel",
|
|
}
|
|
|
|
|
|
def raw_status_value(status: Any) -> str:
|
|
if hasattr(status, "value"):
|
|
status = status.value
|
|
return str(status or "").strip()
|
|
|
|
|
|
def normalize_task_status(status: Any, *, default: str | None = None) -> str:
|
|
"""Normalize canon task statuses plus legacy aliases to stored values."""
|
|
value = raw_status_value(status).lower()
|
|
if not value:
|
|
if default is not None:
|
|
return default
|
|
raise ValueError("task status is required")
|
|
value = LEGACY_TASK_STATUS_ALIASES.get(value, value)
|
|
if value not in CANONICAL_TASK_STATUSES:
|
|
allowed = ", ".join(CANONICAL_TASK_STATUSES)
|
|
aliases = ", ".join(sorted(LEGACY_TASK_STATUS_ALIASES))
|
|
raise ValueError(f"task status must be one of {allowed}; legacy aliases: {aliases}")
|
|
return value
|
|
|
|
|
|
def status_value(status: Any, *, default: str | None = None) -> str:
|
|
"""Compatibility wrapper used by lifecycle and reconciliation code."""
|
|
return normalize_task_status(status, default=default)
|
|
|
|
|
|
def is_open_task_status(status: Any) -> bool:
|
|
return normalize_task_status(status, default="todo") in OPEN_TASK_STATUSES
|
|
|
|
|
|
def is_terminal_task_status(status: Any) -> bool:
|
|
return normalize_task_status(status, default="todo") in TERMINAL_TASK_STATUSES
|