Skip to content

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

Description

@jborean93

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)

Activity

  1. 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[/+] on Jul 11, 2022
  2. added
    stdlibStandard Library Python modules in the Lib/ directory
    on Jul 11, 2022
  3. AlexWaygood commented on Jul 11, 2022

    @AlexWaygood
    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/

  4. jborean93 commented on Jul 11, 2022

    @jborean93
    ContributorAuthor

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

  5. ethanfurman commented on Jul 14, 2022

    @ethanfurman
    Member

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

  6. jborean93 commented on Jul 14, 2022

    @jborean93
    ContributorAuthor

    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?

  7. ethanfurman commented on Jul 15, 2022

    @ethanfurman
    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().

  8. pitrou commented on Oct 26, 2022

    @pitrou
    Member

    @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?

  9. johnthagen commented on Oct 29, 2022

    @johnthagen
    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:

  10. ethanfurman commented on Nov 14, 2022

    @ethanfurman
    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
  11. bilderbuchi commented on Jul 21, 2023

    @bilderbuchi

    @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

Metadata

Metadata

Assignees

Labels

3.11only security fixesstdlibStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or error

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions