October 22, 2024
Chicago 12, Melborne City, USA
python

Enum of dataclass works but frozen attrs doesn't


The built-in enum provides a way to create enums of primitive types (IntEnum, StrEnum).

I’d like to create an enum of structured objects.

One way to do that is with dataclass, and it works:

from dataclasses import dataclass
from enum import Enum

from typing_extensions import assert_never

@dataclass(frozen=True)
class _BaseInstTypeDataclass:
    instance_type: str
    display_name: str


class InstTypeDataClass(_BaseInstTypeDataclass, Enum):
    t2_micro = ("t2.micro", "t2.micro: Cheap!")
    r7i_2xlarge = ("r7i.2xlarge", "r7i.2xlarge: Expensive!")


assert list(InstTypeDataClass) == [
    InstTypeDataClass.t2_micro,
    InstTypeDataClass.r7i_2xlarge,
]
assert isinstance(InstTypeDataClass.t2_micro, InstTypeDataClass)


# This function type checks
def f_dataclass(e: InstTypeDataClass):
    if e == InstTypeDataClass.t2_micro:
        ...
    elif e == InstTypeDataClass.r7i_2xlarge:
        ...
    else:
        assert_never(e)

Both the static- (via pyright) and runtime-behavior is as expected.

However, with attrs…:

import attrs


@attrs.define(frozen=True)
class _BaseInstTypeAttrs:
    instance_type: str
    display_name: str


class InstTypeAttrs(_BaseInstTypeAttrs, Enum):
    t2_micro = ("t2.micro", "t2.micro: Cheap!")
    r7i_2xlarge = ("r7i.2xlarge", "r7i.2xlarge: Expensive!")


# This function type checks
def f_attrs(e: InstTypeAttrs):
    if e == InstTypeAttrs.t2_micro:
        ...
    elif e == InstTypeAttrs.r7i_2xlarge:
        ...
    else:
        assert_never(e)

… the type checker is happy, but at run-time…:

$ python foo.py 
_BaseInstTypeDataclass(instance_type="foo", display_name="bar")
Traceback (most recent call last):
  File "foo.py", line 58, in <module>
    class InstTypeAttrs(_BaseInstTypeAttrs, Enum):
  File "/Users/.../python3.10/enum.py", line 287, in __new__
    enum_member._value_ = value
  File "/Users/.../python3.10/site-packages/attr/_make.py", line 551, in _frozen_setattrs
    raise FrozenInstanceError()
attr.exceptions.FrozenInstanceError

Is this because… Enum and attrs.define(frozen=True) don’t play nice…?



You need to sign in to view this answers

Leave feedback about this

  • Quality
  • Price
  • Service

PROS

+
Add Field

CONS

+
Add Field
Choose Image
Choose Video