classification
Title: Enum: mixin classes don't mix well with already mixed Enums
Type: Stage: patch review
Components: Library (Lib) Versions: Python 3.8
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: ethan.furman Nosy List: barry, eli.bendersky, ethan.furman, zero.piraeus
Priority: normal Keywords: patch

Created on 2017-02-16 02:09 by ethan.furman, last changed 2018-09-22 05:26 by ethan.furman.

Pull Requests
URL Status Linked Edit
PR 9328 merged ethan.furman, 2018-09-15 03:05
PR 9486 merged ethan.furman, 2018-09-22 02:12
Messages (6)
msg287910 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2017-02-16 02:09
Consider:
--------
class AllEnum(Enum):
    @classattr
    def ALL(cls):
        members = list(cls)
        all_value = None
        if members:
            all_value = members[0]
            for member in members[1:]:
                all_value |= member
        cls.ALL = all_value
        return all_value

class Color(AllEnum, Flag):
    RED = auto()
    BLUE = auto()
    GREEN = auto()

class IntColor(AllEnum, IntFlag):
    RED = auto()
    BLUE = auto()
    GREEN = auto()

--------

The Color class works fine, but the IntColor fails.  This is due to the way the base data type and __new__ method is discovered.  If we switch the order of the bases

  class IntColor(IntFlag, AllEnum)

it works, but having to put the mixin class last is both bizarre and unworkable when the mixin should be overriding behavior.
msg287914 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2017-02-16 05:13
To get the above code snippet to fail properly:
- remove the @classattr line
- prepend from enum import Enum, Flag, IntFlag, auto
msg287931 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2017-02-16 11:45
While only IntColor fails with an error, Color also fails as it is not a Flag type Enum:

>>> list(Color)
[<Color.RED: 1>, <Color.BLUE: 2>, <Color.GREEN: 3>]

It should have values of 1, 2, 4.
msg287934 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2017-02-16 12:29
Possibilities:

- only allow one base Enum class
  (fails with All and IntFlag)

- only allow base Enum classes that are compatible
 (so not an Enum and a Flag)
 (would require multiple base classes for the same behavior: DocEnum,
  DocFlag, etc.)

- only allow one mixin
  (before/after that one mixin the inheritance is linear)
  (same issue as above)

- only allow one non-Enum mixin, critical Enum is last one in the bases,
  previous Enums in bases are mixins
  (all sunder/dunder methods come from critical Enum, all normal methods
  and attributes are in normal base order)

- be smarter about determining/saving the correct __new__ and base data type

The last one needs to happen, and some form of the next-to-last one (hopefully allowing for more than one non-Enum mixin).
msg326065 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2018-09-22 02:03
New changeset 5bdab641da0afd8aa581dfbde4f82d88d337c4b5 by Ethan Furman in branch 'master':
bpo-29577: Enum: mixin classes don't mix well with already mixed Enums (GH-9328)
https://github.com/python/cpython/commit/5bdab641da0afd8aa581dfbde4f82d88d337c4b5
msg326077 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2018-09-22 05:26
New changeset 0c076caaa82a9c6596e1fe1dbe6384d53f30a1a3 by Ethan Furman in branch '3.7':
[3.7] bpo-29577: Enum: mixin classes don't mix well with already mixed Enums (GH-9328) (GH-9486)
https://github.com/python/cpython/commit/0c076caaa82a9c6596e1fe1dbe6384d53f30a1a3
History
Date User Action Args
2018-09-22 05:26:36ethan.furmansetmessages: + msg326077
2018-09-22 02:12:04ethan.furmansetpull_requests: + pull_request8896
2018-09-22 02:03:13ethan.furmansetmessages: + msg326065
2018-09-15 03:05:05ethan.furmansetkeywords: + patch
stage: patch review
pull_requests: + pull_request8751
2018-09-12 18:37:35ethan.furmansetversions: + Python 3.8, - Python 3.6, Python 3.7
2018-09-11 01:21:40ethan.furmanlinkissue34082 superseder
2017-02-16 12:29:34ethan.furmansetmessages: + msg287934
2017-02-16 11:45:48ethan.furmansetmessages: + msg287931
2017-02-16 07:00:43zero.piraeussetnosy: + zero.piraeus
2017-02-16 05:13:06ethan.furmansetmessages: + msg287914
2017-02-16 02:09:44ethan.furmancreate