Skip to content

topmark.core.enum_mixins

topmark / core / enum_mixins

Generic Enum utilities for TopMark (typing-friendly, UI-agnostic).

This module provides helpers that add lightweight introspection to Enum types without binding callers to UI/CLI concerns (like color). Keep presentation-specific concepts in topmark.presentation and reuse these mixins/utilities anywhere else.

Provided
  • enum_from_name(enum_cls, name, *, case_insensitive=False): Typed lookup by name from __members__. Returns None on miss.
  • EnumIntrospectionMixin: Adds .value_length (cached) to any Enum subclass for formatting.
Design
  • Keep the functions pure and side-effect free.
  • Avoid bringing UI libraries (e.g. yachalk) into this module.
  • Prefer functions over overly clever metaclass tricks for type-checker sanity.
Example
from enum import Enum

from topmark.core.enum_mixins import EnumIntrospectionMixin
from topmark.core.enum_mixins import enum_from_name


class Mode(EnumIntrospectionMixin, str, Enum):
    A = "alpha"
    B = "beta"


assert Mode.A.value_length == 5
assert enum_from_name(Mode, "A") is Mode.A

EnumIntrospectionMixin

Small, UI-agnostic mixin that adds introspection conveniences to Enums.

When mixed into an Enum class, provides:

• ``value_length`` (cached_property): maximum length (in characters) of all
  ``.value`` strings for the enum class. Useful for printing aligned labels.
Implementation note

We rely on the Enum metaclass providing iterability over members and the presence of .value on each. Static analyzers may not infer this on the mixin type itself; local # type: ignore hints are used sparingly.

value_length cached property

value_length

Maximum length of the enum's .value strings.

Returns:

Type Description
int

The maximum length among all member .value strings of the enum class that this

int

member belongs to.

KeyedStrEnum

Bases: str, Enum

Enum where .value is a stable machine key; metadata lives on attributes.

Use this when you want
  • a stable, serialization-friendly key (.value / .key)
  • a human label (.label) and optional aliases for parsing

Attributes:

Name Type Description
label str

Human-readable label for the member.

aliases tuple[str, ...]

Alternative tokens accepted by parse().

Example

class OutputTarget(KeyedStrEnum): FILE = ("file", "Write to file") STDOUT = ("stdout", "Write to STDOUT")

key property

key

Stable machine key (same as .value).

parse classmethod

parse(raw)

Parse a token into an enum member.

Matches against
  • the stable key (.value)
  • the member name (.name)
  • any configured aliases

Matching is case-insensitive and normalizes '-', ' ' to '_' via _norm_token().

Source code in src/topmark/core/enum_mixins.py
@classmethod
def parse(cls, raw: str | None) -> Self | None:
    """Parse a token into an enum member.

    Matches against:
      - the stable key (`.value`)
      - the member name (`.name`)
      - any configured aliases

    Matching is case-insensitive and normalizes '-', ' ' to '_' via `_norm_token()`.
    """
    if raw is None:
        return None
    token: str = _norm_token(raw)

    for m in cls:
        if token == _norm_token(m.value):
            return m
        if token == _norm_token(m.name):
            return m
        for a in m.aliases:
            if token == _norm_token(a):
                return m
    return None

enum_from_name

enum_from_name(
    enum_cls, key_name, *, case_insensitive=False
)

Return the enum member for key_name from enum_cls.__members__.

Parameters:

Name Type Description Default
enum_cls type[_E]

The Enum class to search.

required
key_name str | None

The member name (e.g., 'OK'). If None, returns None.

required
case_insensitive bool

If True, lookup is performed with key_name.upper().

False

Returns:

Type Description
_E | None

The matching enum member, or None if not found.

Notes
  • This is a name lookup. If you want to match against values as well, normalize the candidate first and query __members__ for both keys, or introduce a separate helper (kept out of this core to avoid policy).
Source code in src/topmark/core/enum_mixins.py
def enum_from_name(
    enum_cls: type[_E],
    key_name: str | None,
    *,
    case_insensitive: bool = False,
) -> _E | None:
    """Return the enum member for ``key_name`` from ``enum_cls.__members__``.

    Args:
        enum_cls: The Enum class to search.
        key_name: The member name (e.g., ``'OK'``). If ``None``, returns ``None``.
        case_insensitive: If True, lookup is performed with ``key_name.upper()``.

    Returns:
        The matching enum member, or ``None`` if not found.

    Notes:
        - This is a *name* lookup. If you want to match against values as well,
          normalize the candidate first and query ``__members__`` for both keys,
          or introduce a separate helper (kept out of this core to avoid policy).
    """
    if key_name is None:
        return None
    target: str = key_name.upper() if case_insensitive else key_name
    member: object | None = getattr(enum_cls, "__members__", {}).get(target)
    return cast("_E | None", member)