49 lines
1.1 KiB
Python
49 lines
1.1 KiB
Python
|
|
"""Work-record flavor (STATE-WP-0092).
|
||
|
|
|
||
|
|
Flavor is a closed bucket on workplans and tasks, orthogonal to kind and
|
||
|
|
status. Unset flavor is not residual.
|
||
|
|
"""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
from typing import Any
|
||
|
|
|
||
|
|
WORK_RECORD_FLAVORS: tuple[str, ...] = (
|
||
|
|
"planning",
|
||
|
|
"implementation",
|
||
|
|
"refactoring",
|
||
|
|
"extension",
|
||
|
|
"residual",
|
||
|
|
)
|
||
|
|
RESIDUAL_FLAVOR = "residual"
|
||
|
|
FLAVOR_PROMOTION_REASONS: tuple[str, ...] = ("demand", "risk")
|
||
|
|
|
||
|
|
_EMPTY = {"", "~", "null", "none", "nil"}
|
||
|
|
|
||
|
|
|
||
|
|
def normalize_flavor(value: Any) -> str | None:
|
||
|
|
if value is None:
|
||
|
|
return None
|
||
|
|
text = str(value).strip().lower()
|
||
|
|
if text in _EMPTY:
|
||
|
|
return None
|
||
|
|
return text
|
||
|
|
|
||
|
|
|
||
|
|
def is_known_flavor(value: Any) -> bool:
|
||
|
|
flavor = normalize_flavor(value)
|
||
|
|
return flavor is None or flavor in WORK_RECORD_FLAVORS
|
||
|
|
|
||
|
|
|
||
|
|
def is_residual_flavor(value: Any) -> bool:
|
||
|
|
return normalize_flavor(value) == RESIDUAL_FLAVOR
|
||
|
|
|
||
|
|
|
||
|
|
def normalize_promotion_reason(value: Any) -> str | None:
|
||
|
|
if value is None:
|
||
|
|
return None
|
||
|
|
text = str(value).strip().lower()
|
||
|
|
if text in _EMPTY:
|
||
|
|
return None
|
||
|
|
return text
|