Search code examples
pythonenums

iterate over IntFlag enumeration using iter differs in python 3.8 and 3.12.4


I have the following working in python 3.8.1

@unique
class Encoder(IntFlag):
    # H1 sensor signal
    H1 = 0x00
    # H2 sensor signal
    H2 = 0x01
    # H3 sensor signal
    H3 = 0x02

Then I am trying to catch with an assert if the value is not within the enum, i.e.

from enum import unique, IntFlag
signal = Encoder.H1
assert signal in iter(Encoder), f"Valid Encoder line is integer 0 to 2 inclusive."

I noticed on python 3.8, the signal in iter(Encoder) returns True but False in python 3.12.4

enter image description here

It might be a change in some version from 3.8.1 to 3.12.4 but I am not sure where to star looking for getting this working in both.


Solution

  • enum.Flag implements __contains__.

    For membership checks, drop the iter call and just use:

    signal in Encoder
    

    This will work in both 3.8.1 and 3.12.4.

    Note: The change in iteration behavior for flags happened in Python 3.11 and is mentioned in the changelog here.

    Also, you should probably be using IntEnum rather than IntFlag anyway. IntFlag would be appropriate in a use case where Encoder.H2 | Encoder.H3 was meaningful, and meant "both of these". In your use case, Encoder.H2 | Encoder.H3 is an invalid value.