Skip to content
Merged
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
20 changes: 19 additions & 1 deletion Lib/enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,25 @@ def __new__(cls, value):
if member._value_ == value:
return member
# still not found -- try _missing_ hook
return cls._missing_(value)
try:
exc = None
result = cls._missing_(value)
except Exception as e:
exc = e
result = None
if isinstance(result, cls):
return result
else:
ve_exc = ValueError("%r is not a valid %s" % (value, cls.__name__))
if result is None and exc is None:
raise ve_exc
elif exc is None:
exc = TypeError(
'error in %s._missing_: returned %r instead of None or a valid member'
% (cls.__name__, result)
)
exc.__context__ = ve_exc
raise exc

def _generate_next_value_(name, start, count, last_values):
for last_value in reversed(last_values):
Expand Down
32 changes: 32 additions & 0 deletions Lib/test/test_enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -1717,6 +1717,38 @@ class Dupes(Enum):
third = auto()
self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes))

def test_missing(self):
class Color(Enum):
red = 1
green = 2
blue = 3
@classmethod
def _missing_(cls, item):
if item == 'three':
return cls.blue
elif item == 'bad return':
# trigger internal error
return 5
elif item == 'error out':
raise ZeroDivisionError
else:
# trigger not found
return None
self.assertIs(Color('three'), Color.blue)
self.assertRaises(ValueError, Color, 7)
try:
Color('bad return')
except TypeError as exc:
self.assertTrue(isinstance(exc.__context__, ValueError))
else:
raise Exception('Exception not raised.')
try:
Color('error out')
except ZeroDivisionError as exc:
self.assertTrue(isinstance(exc.__context__, ValueError))
else:
raise Exception('Exception not raised.')

def test_multiple_mixin(self):
class MaxMixin:
@classproperty
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
`Enum._missing_`: raise `ValueError` if None returned and `TypeError` if
non-member is returned.