8000 bpo-39728: enum with invalid value results in ValueError twice by dorosch · Pull Request #18641 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

bpo-39728: enum with invalid value results in ValueError twice #18641

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

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Lib/enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ def __new__(cls, value):
'error in %s._missing_: returned %r instead of None or a valid member'
% (cls.__name__, result)
)
exc.__context__ = ve_exc
exc.__context__ = ve_exc
raise exc

def _generate_next_value_(name, start, count, last_values):
Expand Down
5 changes: 3 additions & 2 deletions Lib/test/test_enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -1776,7 +1776,8 @@ def _missing_(cls, item):
# trigger not found
return None
self.assertIs(Color('three'), Color.blue)
self.assertRaises(ValueError, Color, 7)
with self.assertRaises(ValueError):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This statement passes on the old code as well. Is it possible to specifically assert that a ValueError has been raised, but without the second ValueError being raised in the process?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that can (and should) be tested, with something like this:

        with self.assertRaises(ValueError) as cm:
            Color(7)
        self.assertIsNone(cm.exception.__context__)

Color(7)
try:
Color('bad return')
except TypeError as exc:
Expand All @@ -1786,7 +1787,7 @@ def _missing_(cls, item):
try:
Color('error out')
except ZeroDivisionError as exc:
self.assertTrue(isinstance(exc.__context__, ValueError))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I hadn't noticed but this test would (still) be affected by the fix. And it seems reasonable to keep : \

Instead of changing when context is added to the exception, could the default implementation of _missing be changed to return None? Or would that break something?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that would break logic because None might be as value of enum:

from enum import Enum

class Color(Enum):
    BLUE = 'blue'
    RED = 'red'
    UNDEFINED = None

Copy link
@jonasmalacofilho jonasmalacofilho Feb 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But in that example _missing_ would need to return cls.UNDEFINED instead of None, because it has to return an instance of cls.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you're right) I will try it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original verification here should be kept. It's checking that if using _missing_ explodes when searching for a value, the final result is the ValueError (of the bad value) and the ZeroDivisionError (of the internal problem).

self.assertTrue(not exc.__context__)
else:
raise Exception('Exception not raised.')

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Instantiating enum with invalid value results in ValueError twice
0