Wednesday, April 19, 2023

Python 3.11 - IntEnum str() representation changes

Got an unwanted surprise today trying to run my codebase ("TPMS Studio") using the latest Python (3.11) instead of the 3.7 / 3.8 combos I've been using for the past few years.

Turns out the core team made a breaking change to the behaviour of enums, which breaks our file format + causes the code to crash on startup (assert failures)!

The cause:
`str(eMyEnum.Value_1)` now evaluates to "1" instead of "eMyEnum.Value_1"

(Note: eMyEnum is defined as an IntEnum)

 

The solution I ended up with was based on:
https://github.com/python/cpython/issues/94763#issuecomment-1313058070

 

[EDIT: This was the old solution. I have since learned of an even easier fix, from the official docs. See below]

In short, I now do something like:
```

import sys
import enum

if sys.version_info >= (3, 11):
    # Python 3.11+ hack
    class IntEnum(int, enum.Enum):
        # Get back old "EnumName.VariantName" str() behaviour
        pass
else:
    # Use old defines for older Python versions
    IntEnum = enum.IntEnum

```

 

[Latest Update: This solution is easier to use. It comes from the official docs (i.e. example 2)]

```

from enum import Enum, IntEnum

class eMyEnum(IntEnum):

    __str__ = Enum.__str__      # <--- That's the key right there

``` 


 Reposting from my original Mastodon posts for easier searchability