Skip to content

Enum _missing_ function changes __contains__ behaviour #132684

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

Open
artur-sl opened this issue Apr 18, 2025 · 9 comments
Open

Enum _missing_ function changes __contains__ behaviour #132684

artur-sl opened this issue Apr 18, 2025 · 9 comments
Labels
3.12 only security fixes 3.13 bugs and security fixes 3.14 new features, bugs and security fixes release-blocker stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@artur-sl
Copy link

artur-sl commented Apr 18, 2025

Bug report

Bug description:

I observed different behavior for Enum __contains__ in 3.13.2 and 3.13.3 if there is _missing_ method implemented:

from enum import Enum

class Color(Enum):
    RED = 1
    
    @classmethod
    def _missing_(cls, value):
        return cls.RED

# 3.13.2
>>> "blue" in Color
False

# 3.13.3
>>> "blue" in Color
True

IMO _missing_ should only influence the __call__ method:

# both 3.13.2 and 3.13.3
>>> Color("blue")
<Color.RED: 1>

CPython versions tested on:

3.13

Operating systems tested on:

macOS

Linked PRs

@artur-sl artur-sl added the type-bug An unexpected behavior, bug, or error label Apr 18, 2025
@noamcohen97
Copy link
Contributor

I am fairly certain this is a side effect of #131053, but I'm not sure what the correct behavior should be.
@picnixz @ethanfurman, what are your thoughts?

@picnixz
Copy link
Member

picnixz commented Apr 18, 2025

Arf... this is something I didn't think of. This can be pretty annoying and we could also need to revert it in 3.12 :< I'll mark it as a release-blocker for now to draw attention.

@picnixz picnixz added stdlib Python modules in the Lib dir release-blocker labels Apr 18, 2025
@picnixz picnixz added 3.12 only security fixes 3.13 bugs and security fixes 3.14 new features, bugs and security fixes labels Apr 18, 2025
@picnixz
Copy link
Member

picnixz commented Apr 18, 2025

Actually, Ethan said on the previous issue:

In other words, if Weekday(x) would return a valid member, then x in Weekday should return True.

Now, here Color("blue") returns Color.RED. So... if we were to follow the same logic, "blue" in Color would still be correct. I'm not entirely sure whether we need to fix this or not but I know for sure that sometimes we do checks of the form x in ENUM and depending on how the ENUM is being done, we may or may not have broken some code out there.

@s3rius
Copy link

s3rius commented Apr 18, 2025

I guess it makes total sense, because usually you only check that the value is present in the enum to create its member.

But if you really want to mimic the behavior of 3.12 then you can use this workaround:

>>> 'blue' in {color.name for color in Color}
False

@noamcohen97
Copy link
Contributor

Perhaps we should simply document the change in behavior?

@picnixz
Copy link
Member

picnixz commented Apr 18, 2025

If possible, yes, but it's also sad that the behavior of some constructions have been broken in a stable release.

@ethanfurman
Copy link
Member

The change was for Flags -- i'll look at narrowing the code to reflect that.

@ethanfurman
Copy link
Member

we could also need to revert it in 3.12

3.12 is in security-only mode, unfortunately.

@picnixz
Copy link
Member

picnixz commented Apr 24, 2025

We can still ask @Yhg1s if he would consider the bugfix as an incomplete bugfix then (considering we broke something =/) and backport your recent bugfix.

miss-islington pushed a commit to miss-islington/cpython that referenced this issue Apr 25, 2025
…pythonGH-132790)

(cherry picked from commit 22bc953)

Co-authored-by: Ethan Furman <[email protected]>
Co-authored-by: Bénédikt Tran <[email protected]>
ethanfurman added a commit that referenced this issue Apr 25, 2025
GH-132790) (GH-132896)

gh-132684: [Enum] only call _missing_ in __contains__ for Flags (GH-132790)
(cherry picked from commit 22bc953)

Co-authored-by: Ethan Furman <[email protected]>
Co-authored-by: Bénédikt Tran <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.12 only security fixes 3.13 bugs and security fixes 3.14 new features, bugs and security fixes release-blocker stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
Projects
Development

No branches or pull requests

5 participants