Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0f2fc8b

Browse files
vstinnerethanfurman
authored andcommitted
bpo-34536: raise error for invalid _missing_ results (GH-9147) (GH-9978)
* raise exception if _missing_ returns None or invalid type
1 parent 2a6cf44 commit 0f2fc8b

3 files changed

Lines changed: 53 additions & 1 deletion

File tree

Lib/enum.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,25 @@ def __new__(cls, value):
540540
if member._value_ == value:
541541
return member
542542
# still not found -- try _missing_ hook
543-
return cls._missing_(value)
543+
try:
544+
exc = None
545+
result = cls._missing_(value)
546+
except Exception as e:
547+
exc = e
548+
result = None
549+
if isinstance(result, cls):
550+
return result
551+
else:
552+
ve_exc = ValueError("%r is not a valid %s" % (value, cls.__name__))
553+
if result is None and exc is None:
554+
raise ve_exc
555+
elif exc is None:
556+
exc = TypeError(
557+
'error in %s._missing_: returned %r instead of None or a valid member'
558+
% (cls.__name__, result)
559+
)
560+
exc.__context__ = ve_exc
561+
raise exc
544562

545563
def _generate_next_value_(name, start, count, last_values):
546564
for last_value in reversed(last_values):

Lib/test/test_enum.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1717,6 +1717,38 @@ class Dupes(Enum):
17171717
third = auto()
17181718
self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes))
17191719

1720+
def test_missing(self):
1721+
class Color(Enum):
1722+
red = 1
1723+
green = 2
1724+
blue = 3
1725+
@classmethod
1726+
def _missing_(cls, item):
1727+
if item == 'three':
1728+
return cls.blue
1729+
elif item == 'bad return':
1730+
# trigger internal error
1731+
return 5
1732+
elif item == 'error out':
1733+
raise ZeroDivisionError
1734+
else:
1735+
# trigger not found
1736+
return None
1737+
self.assertIs(Color('three'), Color.blue)
1738+
self.assertRaises(ValueError, Color, 7)
1739+
try:
1740+
Color('bad return')
1741+
except TypeError as exc:
1742+
self.assertTrue(isinstance(exc.__context__, ValueError))
1743+
else:
1744+
raise Exception('Exception not raised.')
1745+
try:
1746+
Color('error out')
1747+
except ZeroDivisionError as exc:
1748+
self.assertTrue(isinstance(exc.__context__, ValueError))
1749+
else:
1750+
raise Exception('Exception not raised.')
1751+
17201752
def test_multiple_mixin(self):
17211753
class MaxMixin:
17221754
@classproperty
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
`Enum._missing_`: raise `ValueError` if None returned and `TypeError` if
2+
non-member is returned.

0 commit comments

Comments
 (0)