gh-93820: Fix copy() regression in enum.Flag (GH-93876)

GH-26658 introduced a regression in copy / pickle protocol for combined
`enum.Flag`s. `copy.copy(re.A | re.I)` would fail with
`AttributeError: ASCII|IGNORECASE`.

`enum.Flag` now has a `__reduce_ex__()` method that reduces flags by
combined value, not by combined name.
This commit is contained in:
Christian Heimes 2022-06-16 08:42:36 +02:00 committed by GitHub
parent 8ba1c7f720
commit 05b32c1c79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 0 deletions

View File

@ -1369,6 +1369,9 @@ class Flag(Enum, boundary=STRICT):
Support for flags Support for flags
""" """
def __reduce_ex__(self, proto):
return self.__class__, (self._value_, )
_numeric_repr_ = repr _numeric_repr_ = repr
def _generate_next_value_(name, start, count, last_values): def _generate_next_value_(name, start, count, last_values):

View File

@ -1,3 +1,4 @@
import copy
import enum import enum
import doctest import doctest
import inspect import inspect
@ -734,6 +735,13 @@ class _MinimalOutputTests:
self.assertFormatIsValue('{:5.2}', TE.third) self.assertFormatIsValue('{:5.2}', TE.third)
self.assertFormatIsValue('{:f}', TE.third) self.assertFormatIsValue('{:f}', TE.third)
def test_copy(self):
TE = self.MainEnum
copied = copy.copy(TE)
self.assertEqual(copied, TE)
deep = copy.deepcopy(TE)
self.assertEqual(deep, TE)
class _FlagTests: class _FlagTests:
@ -2654,6 +2662,26 @@ class TestSpecial(unittest.TestCase):
self.assertTrue(isinstance(MyIntFlag.ONE | MyIntFlag.TWO, MyIntFlag), MyIntFlag.ONE | MyIntFlag.TWO) self.assertTrue(isinstance(MyIntFlag.ONE | MyIntFlag.TWO, MyIntFlag), MyIntFlag.ONE | MyIntFlag.TWO)
self.assertTrue(isinstance(MyIntFlag.ONE | 2, MyIntFlag)) self.assertTrue(isinstance(MyIntFlag.ONE | 2, MyIntFlag))
def test_int_flags_copy(self):
class MyIntFlag(IntFlag):
ONE = 1
TWO = 2
FOUR = 4
flags = MyIntFlag.ONE | MyIntFlag.TWO
copied = copy.copy(flags)
deep = copy.deepcopy(flags)
self.assertEqual(copied, flags)
self.assertEqual(deep, flags)
flags = MyIntFlag.ONE | MyIntFlag.TWO | 8
copied = copy.copy(flags)
deep = copy.deepcopy(flags)
self.assertEqual(copied, flags)
self.assertEqual(deep, flags)
self.assertEqual(copied.value, 1 | 2 | 8)
class TestOrder(unittest.TestCase): class TestOrder(unittest.TestCase):
"test usage of the `_order_` attribute" "test usage of the `_order_` attribute"

View File

@ -0,0 +1,2 @@
Fixed a regression when :func:`copy.copy`-ing :class:`enum.Flag` with
multiple flag members.