Search code examples
pythonpython-3.xenumsmultiple-inheritance

Overriding Enum._generate_next_value_ not working as expected with MRO?


Why does overriding _generate_next_value_ only work if done in the LAST inherited enum?

For example:

class AutoEnum(Enum):
    def _generate_next_value_(name, start, count, last_values):
        return 'overriding _generate_next_value'

class OtherEnum(Enum):
    def some_other_method(self):
        return

class AutoOther(AutoEnum, OtherEnum):
    TEST = auto()

class OtherAuto(OtherEnum, AutoEnum):
    TEST = auto()


print(f'{AutoOther.TEST}: mro={getmro(AutoOther)}\n'
      f'name: {AutoOther.TEST.name}, value: {AutoOther.TEST.value}')

print(f'{OtherAuto.TEST}: mro={getmro(OtherAuto)}\n'
      f'name: {OtherAuto.TEST.name}, value: {OtherAuto.TEST.value}')

Output:

AutoOther.TEST: mro=(<enum 'AutoOther'>, <enum 'AutoEnum'>, <enum 'OtherEnum'>, <enum 'Enum'>, <class 'object'>)
name: TEST, value: 1

OtherAuto.TEST: mro=(<enum 'OtherAuto'>, <enum 'OtherEnum'>, <enum 'AutoEnum'>, <enum 'Enum'>, <class 'object'>)
name: TEST, value: overriding _generate_next_value

If somehow the default _generate_next_value_ is being set every time if it's not specifically overridden, how is it not being reset again when Enum is inherited?

I think I'm missing something with how/why this is working like this.


Solution

  • Special methods such as _generate_next_value_ need to be in place before the class is actually created. In order to support this, EnumMeta looks for these special methods in the base Enum class -- and the base Enum class is the last one listed.

    It certainly feels like any other Enum classes should also be searched for the enum methods, though.

    Issue created.


    Disclosure: I am the author of the Python stdlib Enum, the enum34 backport, and the Advanced Enumeration (aenum) library.