diff --git a/Lib/enum.py b/Lib/enum.py index 1efddfa1a0acc6..7ad599bb1e62e3 100644 --- a/Lib/enum.py +++ b/Lib/enum.py @@ -430,7 +430,9 @@ def __setitem__(self, key, value): if isinstance(value, auto): single = True value = (value, ) - if isinstance(value, tuple): + if type(value) is tuple and any(isinstance(v, auto) for v in value): + # insist on an actual tuple, no subclasses, in keeping with only supporting + # top-level auto() usage (not contained in any other data structure) auto_valued = [] for v in value: if isinstance(v, auto): diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py index a9b80ad0d3dbc3..0e2da1d64c1950 100644 --- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -2727,6 +2727,19 @@ class MyIntFlag(IntFlag): self.assertEqual(deep, flags) self.assertEqual(copied.value, 1 | 2 | 8) + def test_namedtuple_as_value(self): + from collections import namedtuple + TTuple = namedtuple('TTuple', 'id a blist') + class NTEnum(Enum): + NONE = TTuple(0, 0, []) + A = TTuple(1, 2, [4]) + B = TTuple(2, 4, [0, 1, 2]) + self.assertEqual(repr(NTEnum.NONE), "") + self.assertEqual(NTEnum.NONE.value, TTuple(id=0, a=0, blist=[])) + self.assertEqual( + [x.value for x in NTEnum], + [TTuple(id=0, a=0, blist=[]), TTuple(id=1, a=2, blist=[4]), TTuple(id=2, a=4, blist=[0, 1, 2])], + ) class TestOrder(unittest.TestCase): "test usage of the `_order_` attribute" diff --git a/Misc/NEWS.d/next/Library/2022-12-08-06-18-06.gh-issue-100098.uBvPlp.rst b/Misc/NEWS.d/next/Library/2022-12-08-06-18-06.gh-issue-100098.uBvPlp.rst new file mode 100644 index 00000000000000..256f2bcd39f81d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-12-08-06-18-06.gh-issue-100098.uBvPlp.rst @@ -0,0 +1 @@ +Fix ``tuple`` subclasses being cast to ``tuple`` when used as enum values.