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

Python 3.11.0b4 str(enum) giving integer value and not name #94763

Closed
jborean93 opened this issue Jul 11, 2022 · 9 comments
Closed

Python 3.11.0b4 str(enum) giving integer value and not name #94763

jborean93 opened this issue Jul 11, 2022 · 9 comments
Assignees
Labels
3.11 only security fixes stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@jborean93
Copy link
Contributor

jborean93 commented Jul 11, 2022

Bug report

The str() method on Python 3.11.0b4 is outputting the raw integer value not the class name and label that older Python versions do.

import enum

class MyEnum(enum.IntEnum):
    TEST = 1


assert str(MyEnum.TEST) == "MyEnum.TEST", f"Actual '{MyEnum.TEST}'"

On Python 3.10 (and older Python 3 versions) this assertion is true. On python 3.11.0b4 the str value is just 1.

The repr() is the same as on older versions, just seems like str() is affected.

Your environment

  • CPython versions tested on: 3.11.0b4
  • Operating system and architecture: Linux (should be N/A though)
@jborean93 jborean93 added the type-bug An unexpected behavior, bug, or error label Jul 11, 2022
@jborean93 jborean93 changed the title Python 3.11 str(enum) giving integer value and not name Python 3.11.0b4 str(enum) giving integer value and not name Jul 11, 2022
@AlexWaygood AlexWaygood added the stdlib Python modules in the Lib dir label Jul 11, 2022
@AlexWaygood
Copy link
Member

I believe that this is a deliberate behaviour change from previous versions. The Steering Council specifically approved this change; see the penultimate paragraph here regarding aligning str() and format() for IntEnum: https://mail.python.org/archives/list/python-dev@python.org/message/RN3WCRZSTQR55DOHJTZ2KIO6CZPJPCU7/

@jborean93
Copy link
Contributor Author

jborean93 commented Jul 11, 2022

#22392 does seem somewhat related but it does mention only string enums should use the values and other types use the member name. If this is a change made on purpose that's fine, I just want to know for sure and whether to update my tests.

Edit: Sorry you posted just as I was commenting.

@AlexWaygood AlexWaygood added the 3.11 only security fixes label Jul 11, 2022
@ethanfurman
Copy link
Member

My apologies for the confusion, I need to get the Whats New updated with the Enum changes/additions.

@jborean93
Copy link
Contributor Author

No worries, so just to confirm this is expected for pretty much any enum types and not just a string enum as mentioned in the linked issue?

@ethanfurman
Copy link
Member

This is (now) the expected behavior for any mixed Enum/Flag defined in the enum module. The expectation is that existing code being replaced with IntEnum, StrEnum, or IntFlag should have its str() continue to be the same as it was; if you mix your own (i.e. MyIntEnum(int, Enum)) then you get the original behavior of both repr() and str() being overridden. In either case, format() will be the same as str().

@pitrou
Copy link
Member

pitrou commented Oct 26, 2022

@ethanfurman So what is the idiomatic way to get the member name rather than the value? In 3.10 I have:

>>> fs.FileType.__mro__
(<enum 'FileType'>, <enum 'IntEnum'>, int, <enum 'Enum'>, object)
>>> str(fs.FileType.Directory)
'FileType.Directory'
>>> repr(fs.FileType.Directory)
'<FileType.Directory: 3>'

How do I get 'FileType.Directory' with 3.11?

@johnthagen
Copy link
Contributor

I know it was intentional, but just as a data point, the breaking changes to format for MyEnum(str, Enum) did cause some downstream breakage, such as:

@ethanfurman
Copy link
Member

How do I get 'FileType.Directory' with 3.11?

@pitrou Either change the __str__ for the FileType enum, or make a new base enum to inherit from:

class OldIntEnum(int, Enum):
    """
    use the `classname.membername` str()
    """
    pass

@bilderbuchi
Copy link

bilderbuchi commented Jul 21, 2023

@ethanfurman I know this is probably water under the bridge now, but I wonder why breaking changes like this are not called out more distinctly in the What's New (e.g. by including the word "breaking")?!

We just had code using plain IntEnum/IntFlag change behaviour on Python 3.11, and now have a hard time working around that breaking change (probably by inheriting from (int, Enum) to support all current Python versions and our user's use case.
Hitting surprises like this is unpleasant, and I have to admit they somewhat undermine my trust in the versioning scheme.

Could breaking changes at least be marked/called out with "breaking" or somesuch? Then it's easier to grep the What's new when, against expectations, a minor version upgrades changes public behaviour. :-(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.11 only security fixes stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

6 participants