Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enum: mixin classes don't mix well with already mixed Enums #73763

Closed
ethanfurman opened this issue Feb 16, 2017 · 6 comments
Closed

Enum: mixin classes don't mix well with already mixed Enums #73763

ethanfurman opened this issue Feb 16, 2017 · 6 comments
Assignees
Labels
3.8 (EOL) end of life stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@ethanfurman
Copy link
Member

BPO 29577
Nosy @warsaw, @ethanfurman
PRs
  • bpo-29577: Enum: mixin classes don't mix well with already mixed Enums #9328
  • [3.7] bpo-29577: Enum: mixin classes don't mix well with already mixed Enums (GH-9328) #9486
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/ethanfurman'
    closed_at = <Date 2019-07-16.03:27:52.424>
    created_at = <Date 2017-02-16.02:09:44.122>
    labels = ['3.8', 'type-bug', 'library']
    title = "Enum: mixin classes don't mix well with already mixed Enums"
    updated_at = <Date 2019-07-16.03:27:52.423>
    user = 'https://github.com/ethanfurman'

    bugs.python.org fields:

    activity = <Date 2019-07-16.03:27:52.423>
    actor = 'ethan.furman'
    assignee = 'ethan.furman'
    closed = True
    closed_date = <Date 2019-07-16.03:27:52.424>
    closer = 'ethan.furman'
    components = ['Library (Lib)']
    creation = <Date 2017-02-16.02:09:44.122>
    creator = 'ethan.furman'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 29577
    keywords = ['patch']
    message_count = 6.0
    messages = ['287910', '287914', '287931', '287934', '326065', '326077']
    nosy_count = 4.0
    nosy_names = ['barry', 'eli.bendersky', 'ethan.furman', 'zero.piraeus']
    pr_nums = ['9328', '9486']
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue29577'
    versions = ['Python 3.8']

    @ethanfurman
    Copy link
    Member Author

    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.

    @ethanfurman ethanfurman added the 3.7 (EOL) end of life label Feb 16, 2017
    @ethanfurman ethanfurman self-assigned this Feb 16, 2017
    @ethanfurman ethanfurman added the stdlib Python modules in the Lib dir label Feb 16, 2017
    @ethanfurman
    Copy link
    Member Author

    To get the above code snippet to fail properly:

    • remove the @classattr line
    • prepend from enum import Enum, Flag, IntFlag, auto

    @ethanfurman
    Copy link
    Member Author

    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.

    @ethanfurman
    Copy link
    Member Author

    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).

    @ethanfurman ethanfurman added 3.8 (EOL) end of life and removed 3.7 (EOL) end of life labels Sep 12, 2018
    @ethanfurman
    Copy link
    Member Author

    New changeset 5bdab64 by Ethan Furman in branch 'master':
    bpo-29577: Enum: mixin classes don't mix well with already mixed Enums (GH-9328)
    5bdab64

    @ethanfurman
    Copy link
    Member Author

    New changeset 0c076ca 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)
    0c076ca

    @ethanfurman ethanfurman added the type-bug An unexpected behavior, bug, or error label Jul 16, 2019
    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.8 (EOL) end of life stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
    Projects
    None yet
    Development

    No branches or pull requests

    1 participant