GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Enum `auto()` functionally fails following alias creation · Issue #91456 · python/cpython

Enum auto() functionally fails following alias creation  #91456

New issue
Copy link
New issue
Copy link
Closed
Closed
Enum auto() functionally fails following alias creation #91456
Copy link
Assignees
ethanfurman
Labels
stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Description

@oscar-LT
oscar-LT
opened on Apr 11, 2022
Issue body actions

What is the issue?

The base _generate_next_value_(name, start, count, last_values) in class Enum is not sufficiently rigorous as a default implementation for assigning values with auto().

Why is it problematic?

For a user employing auto() to assign values for their enums, the expectation is that the function will automatically assign unique values to new enums without the user needing to specify those values manually. However, when used following the creation of an alias to a pre-existing enum, the value generated by auto() is not guaranteed to be unique.

Given the following code:

from enum import Enum, auto

class Example(Enum):
    A = auto()
    B = auto()
    C = A
    D = auto()

the expectation is that A, B, D have been assigned unique values whereas C is an alias of A. A printout of each of the Example enum's values proves that not to be the case though:

>>> print(Example.A)
Example.A
>>> print(Example.B)
Example.B
>>> print(Example.C)
Example.A
>>> print(Example.D)     ### UNEXPECTED!
Example.B

effectively rendering D as an alias to B rather than its own separate value.

Suggested Cause

Upon closer inspection, the reason seems to be that the base _generate_next_value_ which auto() relies on is incrementing the "last value that was assigned" rather than the "last NEW value that was assigned"

cpython/Lib/enum.py

Lines 1171 to 1186 in a8abb76

def _generate_next_value_(name, start, count, last_values):
"""
Generate the next value when not given.
name: the name of the member
start: the initial start value or None
count: the number of existing members
last_value: the last value assigned or None
"""
for last_value in reversed(last_values):
try:
return last_value + 1
except TypeError:
pass
else:
return start

Current Workaround

At the moment, to workaround this issue, the user can:

  • Ensure that all aliases are only declared after any and all enums assigned with auto()
  • Implement a replacement _generate_next_value_(name, start, count, last_values) function as described in the docs

This issue only affects code that combines the use of auto() with aliases. Although straightforward workarounds do exist (overloading _generate_next_value_ is well described in the docs), it seems unintuitive and unfriendly as the default behavior of auto(). Even simply sorting last_values before incrementing may be a sufficient solution to this issue, e.g.

    def _generate_next_value_(name, start, count, last_values):
        # for last_value in reversed(last_values):
        for last_value in sorted(last_values, reverse=True):
            try:
                return last_value + 1
            except TypeError:
                pass
        else:
            return start

Activity

  1. oscar-LT commented on Apr 11, 2022

    @oscar-LT
    oscar-LT
    on Apr 11, 2022
    ContributorAuthor
    More actions

    Published a tentative PR with the suggested solution

  2. AlexWaygood
    assigned
    ethanfurman
    on Apr 11, 2022
  3. AlexWaygood
    added
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    on Apr 11, 2022
  4. ethanfurman commented on Jun 9, 2022

    @ethanfurman
    ethanfurman
    on Jun 9, 2022
    Member
    More actions

    Okay, let's change the default _generate_next_value_ to do the sort before picking the highest number, and add a warning to the docs that auto() will fail if used in an enum with non-numeric data. If the user wants to mix numeric and non-numeric data and still use auto() they'll have to create their own _generate_next_value_ to handle it.

  5. AlexWaygood
    added
    stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory
    on Jun 9, 2022
  6. ethanfurman commented on Jun 23, 2022

    @ethanfurman
    ethanfurman
    on Jun 23, 2022
    Member
    More actions

    Change of plans: the current behavior is documented and tested, so a deprecation warning for 3.11 and 3.12 is appropriate. #91457 has been updated.

  7. ethanfurman
    added a commit that references this issue on Jun 23, 2022

    gh-91456: [Enum] Deprecate default auto() behavior with mixed value t…

    fb1e950
  8. miss-islington
    added 2 commits that reference this issue on Jun 23, 2022

    pythongh-91456: [Enum] Deprecate default auto() behavior with mixed v…

    53678ac

    gh-91456: [Enum] Deprecate default auto() behavior with mixed value t…

    321acd4
  9. ethanfurman
    closed this as completedon Jun 23, 2022
  10. serhiy-storchaka
    added a commit that references this issue on Jun 26, 2022

    Revert 30935 defer bpo45162 to 312 (#94285)

    1ffde3e
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

  • @ethanfurman
    ethanfurman

Labels

stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    You are visitor 01402503 — GeezerVison does not store the pages you look up.
    Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.