Skip to content

Commit d771729

Browse files
authored
[3.12] gh-116040: [Enum] fix by-value calls when second value is falsey (GH-116072) (GH-116476)
e.g. Cardinal(1, 0) (cherry picked from commit 13ffd4b)
1 parent 4efd20e commit d771729

File tree

3 files changed

+46
-4
lines changed

3 files changed

+46
-4
lines changed

Lib/enum.py

+11-4
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,13 @@ def _dedent(text):
166166
lines[j] = l[i:]
167167
return '\n'.join(lines)
168168

169+
class _not_given:
170+
def __repr__(self):
171+
return('<not given>')
172+
def __bool__(self):
173+
return False
174+
_not_given = _not_given()
175+
169176
class _auto_null:
170177
def __repr__(self):
171178
return '_auto_null'
@@ -718,7 +725,7 @@ def __bool__(cls):
718725
"""
719726
return True
720727

721-
def __call__(cls, value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None):
728+
def __call__(cls, value, names=_not_given, *values, module=None, qualname=None, type=None, start=1, boundary=None):
722729
"""
723730
Either returns an existing member, or creates a new enum class.
724731
@@ -747,18 +754,18 @@ def __call__(cls, value, names=None, *values, module=None, qualname=None, type=N
747754
"""
748755
if cls._member_map_:
749756
# simple value lookup if members exist
750-
if names:
757+
if names is not _not_given:
751758
value = (value, names) + values
752759
return cls.__new__(cls, value)
753760
# otherwise, functional API: we're creating a new Enum type
754-
if names is None and type is None:
761+
if names is _not_given and type is None:
755762
# no body? no data-type? possibly wrong usage
756763
raise TypeError(
757764
f"{cls} has no members; specify `names=()` if you meant to create a new, empty, enum"
758765
)
759766
return cls._create_(
760767
class_name=value,
761-
names=names,
768+
names=names or None,
762769
module=module,
763770
qualname=qualname,
764771
type=type,

Lib/test/test_enum.py

+34
Original file line numberDiff line numberDiff line change
@@ -3312,6 +3312,40 @@ def __new__(cls, value):
33123312
member._value_ = Base(value)
33133313
return member
33143314

3315+
def test_second_tuple_item_is_falsey(self):
3316+
class Cardinal(Enum):
3317+
RIGHT = (1, 0)
3318+
UP = (0, 1)
3319+
LEFT = (-1, 0)
3320+
DOWN = (0, -1)
3321+
self.assertIs(Cardinal(1, 0), Cardinal.RIGHT)
3322+
self.assertIs(Cardinal(-1, 0), Cardinal.LEFT)
3323+
3324+
def test_no_members(self):
3325+
with self.assertRaisesRegex(
3326+
TypeError,
3327+
'has no members',
3328+
):
3329+
Enum(7)
3330+
with self.assertRaisesRegex(
3331+
TypeError,
3332+
'has no members',
3333+
):
3334+
Flag(7)
3335+
3336+
def test_empty_names(self):
3337+
for nothing, e_type in (
3338+
('', None),
3339+
('', int),
3340+
([], None),
3341+
([], int),
3342+
({}, None),
3343+
({}, int),
3344+
):
3345+
empty_enum = Enum('empty_enum', nothing, type=e_type)
3346+
self.assertEqual(len(empty_enum), 0)
3347+
self.assertRaises(TypeError, 'has no members', empty_enum, 0)
3348+
33153349

33163350
class TestOrder(unittest.TestCase):
33173351
"test usage of the `_order_` attribute"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[Enum] fix by-value calls when second value is falsey; e.g. Cardinal(1, 0)

0 commit comments

Comments
 (0)