Skip to content

← Everyday Standard Library Tools step 49 of 55

Medium Primitives

Migrate a Status Enum to StrEnum

The starter defines Status and Legacy as plain Enum classes. So str(Status.PENDING) is "Status.PENDING", a member never equals its string, and json.dumps raises. Switch both classes to StrEnum, add a parser, and update the report.

parse_status("active")   # Status.ACTIVE
parse_status("ACTIVE")   # raises ValueError
f"{Status.PENDING}"      # "pending"

What to write

  • Make Status a StrEnum and keep @unique. Its members, in this order, are PENDING = "pending", ACTIVE = "active", DONE = "done" and FAILED = "failed".
  • Make Legacy a StrEnum without @unique, with OLD = "same" and then NEW = "same". NEW must stay an alias of OLD.
  • Keep PRIORITY: dict[str, int] as {"pending": 0, "active": 1, "done": 2, "failed": 3}.
  • Write parse_status(raw: str) -> Status. It calls Status(raw) on the exact input. Unknown strings raise ValueError, including upper-case names and strings with extra spaces.
  • Write matches_raw(status: Status, raw: str) -> bool. It returns status == raw. Use it for the comparison in solve, because mypy reports an error when you compare a member with a string literal directly.

Update solve

The starter's solve already builds the report. Change it to call parse_status and matches_raw, and to use members directly where it now uses .value. It returns:

Key Value
values [str(member) for member in Status], in declaration order
json json.dumps({"status": Status.ACTIVE, "history": [Status.PENDING, Status.ACTIVE]}), with default formatting
eq_raw matches_raw(Status.PENDING, "pending"), which is True
formatted f"{Status.PENDING}", which is "pending"
lookup PRIORITY[Status.DONE], with the member as the key, which gives 2
parsed For each input string, the parsed member's name, or "ValueError" if parsing fails
duplicates "ValueError" if unique(Legacy) raises, otherwise "accepted"
aliased Legacy.NEW.name, which is "OLD"

For raw=["active", "ACTIVE", "done"], parsed is ["ACTIVE", "ValueError", "DONE"].

Edge cases

  • Keep the input order and any duplicates in parsed, and do not change the input list.
  • An empty input list gives an empty parsed list. The other keys do not change.
  • unique(Legacy) raises, but the alias stays in place, so aliased is still "OLD".