diff options
author | Ethan Furman <ethan@stoneleaf.us> | 2024-03-07 23:26:13 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-07 23:26:13 (GMT) |
commit | d771729679d39904768f60b3352e02f5f491966c (patch) | |
tree | f10e71a75c35cd90085a1bf170898fb079a48ef6 /Lib | |
parent | 4efd20e23a1cafe442e663355ca3644c3904c945 (diff) | |
download | cpython-d771729679d39904768f60b3352e02f5f491966c.zip cpython-d771729679d39904768f60b3352e02f5f491966c.tar.gz cpython-d771729679d39904768f60b3352e02f5f491966c.tar.bz2 |
[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 13ffd4bd9f529b6a5fe33741fbd57f14b4b80137)
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/enum.py | 15 | ||||
-rw-r--r-- | Lib/test/test_enum.py | 34 |
2 files changed, 45 insertions, 4 deletions
diff --git a/Lib/enum.py b/Lib/enum.py index 6d3bbdc..110fbda 100644 --- a/Lib/enum.py +++ b/Lib/enum.py @@ -166,6 +166,13 @@ def _dedent(text): lines[j] = l[i:] return '\n'.join(lines) +class _not_given: + def __repr__(self): + return('<not given>') + def __bool__(self): + return False +_not_given = _not_given() + class _auto_null: def __repr__(self): return '_auto_null' @@ -718,7 +725,7 @@ class EnumType(type): """ return True - def __call__(cls, value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None): + def __call__(cls, value, names=_not_given, *values, module=None, qualname=None, type=None, start=1, boundary=None): """ Either returns an existing member, or creates a new enum class. @@ -747,18 +754,18 @@ class EnumType(type): """ if cls._member_map_: # simple value lookup if members exist - if names: + if names is not _not_given: value = (value, names) + values return cls.__new__(cls, value) # otherwise, functional API: we're creating a new Enum type - if names is None and type is None: + if names is _not_given and type is None: # no body? no data-type? possibly wrong usage raise TypeError( f"{cls} has no members; specify `names=()` if you meant to create a new, empty, enum" ) return cls._create_( class_name=value, - names=names, + names=names or None, module=module, qualname=qualname, type=type, diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py index c58dc36..d5e9444 100644 --- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -3312,6 +3312,40 @@ class TestSpecial(unittest.TestCase): member._value_ = Base(value) return member + def test_second_tuple_item_is_falsey(self): + class Cardinal(Enum): + RIGHT = (1, 0) + UP = (0, 1) + LEFT = (-1, 0) + DOWN = (0, -1) + self.assertIs(Cardinal(1, 0), Cardinal.RIGHT) + self.assertIs(Cardinal(-1, 0), Cardinal.LEFT) + + def test_no_members(self): + with self.assertRaisesRegex( + TypeError, + 'has no members', + ): + Enum(7) + with self.assertRaisesRegex( + TypeError, + 'has no members', + ): + Flag(7) + + def test_empty_names(self): + for nothing, e_type in ( + ('', None), + ('', int), + ([], None), + ([], int), + ({}, None), + ({}, int), + ): + empty_enum = Enum('empty_enum', nothing, type=e_type) + self.assertEqual(len(empty_enum), 0) + self.assertRaises(TypeError, 'has no members', empty_enum, 0) + class TestOrder(unittest.TestCase): "test usage of the `_order_` attribute" |