Title: Enum `auto()` functionally fails following alias creation · Issue #91456 · python/cpython · GitHub
Open Graph Title: Enum `auto()` functionally fails following alias creation · Issue #91456 · python/cpython
X Title: Enum `auto()` functionally fails following alias creation · Issue #91456 · python/cpython
Description: 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(...
Open Graph Description: 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...
X Description: 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...
Opengraph URL: https://github.com/python/cpython/issues/91456
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Enum `auto()` functionally fails following alias creation ","articleBody":"### What is the issue?\r\nThe 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()`. \r\n\r\n\r\n### Why is it problematic?\r\nFor 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.\r\n\r\nGiven the following code:\r\n```python\r\nfrom enum import Enum, auto\r\n\r\nclass Example(Enum):\r\n A = auto()\r\n B = auto()\r\n C = A\r\n D = auto()\r\n```\r\nthe 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:\r\n\r\n```python\r\n\u003e\u003e\u003e print(Example.A)\r\nExample.A\r\n\u003e\u003e\u003e print(Example.B)\r\nExample.B\r\n\u003e\u003e\u003e print(Example.C)\r\nExample.A\r\n\u003e\u003e\u003e print(Example.D) ### UNEXPECTED!\r\nExample.B\r\n```\r\neffectively rendering `D` as an alias to `B` rather than its own separate value.\r\n\r\n### Suggested Cause\r\nUpon 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\"\r\nhttps://github.com/python/cpython/blob/a8abb76af92a5f6883a640a987f9f45b47ec852b/Lib/enum.py#L1171-L1186\r\n\r\n### Current Workaround\r\nAt the moment, to workaround this issue, the user can:\r\n- Ensure that all aliases are only declared **after** any and all enums assigned with `auto()`\r\n- Implement a replacement `_generate_next_value_(name, start, count, last_values)` function as described in the [docs](docs.python.org/3/library/enum.html#using-automatic-values)\r\n\r\n-----\r\nThis 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.\r\n\r\n```python\r\n def _generate_next_value_(name, start, count, last_values):\r\n # for last_value in reversed(last_values):\r\n for last_value in sorted(last_values, reverse=True):\r\n try:\r\n return last_value + 1\r\n except TypeError:\r\n pass\r\n else:\r\n return start\r\n```","author":{"url":"https://github.com/oscar-LT","@type":"Person","name":"oscar-LT"},"datePublished":"2022-04-11T20:38:40.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":3},"url":"https://github.com/91456/cpython/issues/91456"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:3e6d4b6f-6539-2bfd-5797-cafd54e3465f |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | AA9A:359457:12F5778:1A96441:696A3D98 |
| html-safe-nonce | 8c3a81d076c4537a0662dde4bb43f5c43670c4c9709f90d9cbfdf7df565f8884 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJBQTlBOjM1OTQ1NzoxMkY1Nzc4OjFBOTY0NDE6Njk2QTNEOTgiLCJ2aXNpdG9yX2lkIjoiMzIzMzQzMzU0NDY0NTI5NTUxMiIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | 1012fa351a56084662a2d1c2b547ea02f4ee7d2ef00882ad1ece15baa343b758 |
| hovercard-subject-tag | issue:1200508231 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/python/cpython/91456/issue_layout |
| twitter:image | https://opengraph.githubassets.com/1264d98d945ca7017570727785c5ddba62bd49371cd3379967870d7bd5de5aed/python/cpython/issues/91456 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/1264d98d945ca7017570727785c5ddba62bd49371cd3379967870d7bd5de5aed/python/cpython/issues/91456 |
| og:image:alt | 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... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | oscar-LT |
| hostname | github.com |
| expected-hostname | github.com |
| None | 321736bfdb3f591415ae895a0459bec204b26a76caf47ba5c980634cfacc4538 |
| turbo-cache-control | no-preview |
| go-import | github.com/python/cpython git https://github.com/python/cpython.git |
| octolytics-dimension-user_id | 1525981 |
| octolytics-dimension-user_login | python |
| octolytics-dimension-repository_id | 81598961 |
| octolytics-dimension-repository_nwo | python/cpython |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 81598961 |
| octolytics-dimension-repository_network_root_nwo | python/cpython |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 13581a31d51edf4a3aca179e10890a4d4f9b6d76 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width