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

Skip to content

Commit 019f0a0

Browse files
authored
bpo-34536: raise error for invalid _missing_ results (GH-9147)
* raise exception if _missing_ returns None or invalid type
1 parent a5d1eb8 commit 019f0a0

3 files changed

Lines changed: 54 additions & 1 deletion

File tree

Lib/enum.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,25 @@ def __new__(cls, value):
585585
if member._value_ == value:
586586
return member
587587
# still not found -- try _missing_ hook
588-
return cls._missing_(value)
588+
try:
589+
exc = None
590+
result = cls._missing_(value)
591+
except Exception as e:
592+
exc = e
593+
result = None
594+
if isinstance(result, cls):
595+
return result
596+
else:
597+
ve_exc = ValueError("%r is not a valid %s" % (value, cls.__name__))
598+
if result is None and exc is None:
599+
raise ve_exc
600+
elif exc is None:
601+
exc = TypeError(
602+
'error in %s._missing_: returned %r instead of None or a valid member'
603+
% (cls.__name__, result)
604+
)
605+
exc.__context__ = ve_exc
606+
raise exc
589607

590608
def _generate_next_value_(name, start, count, last_values):
591609
for last_value in reversed(last_values):

Lib/test/test_enum.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import pydoc
44
import sys
55
import unittest
6+
import sys
67
import threading
78
from collections import OrderedDict
89
from enum import Enum, IntEnum, EnumMeta, Flag, IntFlag, unique, auto
@@ -1697,6 +1698,38 @@ class Dupes(Enum):
16971698
third = auto()
16981699
self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes))
16991700

1701+
def test_missing(self):
1702+
class Color(Enum):
1703+
red = 1
1704+
green = 2
1705+
blue = 3
1706+
@classmethod
1707+
def _missing_(cls, item):
1708+
if item == 'three':
1709+
return cls.blue
1710+
elif item == 'bad return':
1711+
# trigger internal error
1712+
return 5
1713+
elif item == 'error out':
1714+
raise ZeroDivisionError
1715+
else:
1716+
# trigger not found
1717+
return None
1718+
self.assertIs(Color('three'), Color.blue)
1719+
self.assertRaises(ValueError, Color, 7)
1720+
try:
1721+
Color('bad return')
1722+
except TypeError as exc:
1723+
self.assertTrue(isinstance(exc.__context__, ValueError))
1724+
else:
1725+
raise Exception('Exception not raised.')
1726+
try:
1727+
Color('error out')
1728+
except ZeroDivisionError as exc:
1729+
self.assertTrue(isinstance(exc.__context__, ValueError))
1730+
else:
1731+
raise Exception('Exception not raised.')
1732+
17001733

17011734
class TestOrder(unittest.TestCase):
17021735

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)