]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-93820: Fix copy() regression in enum.Flag (GH-93876) (#93886)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Fri, 17 Jun 2022 03:56:20 +0000 (20:56 -0700)
committerGitHub <noreply@github.com>
Fri, 17 Jun 2022 03:56:20 +0000 (06:56 +0300)
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.
(cherry picked from commit 05b32c1c796d6c80479756ae898f488eac5f4f71)

Co-authored-by: Christian Heimes <christian@python.org>
Co-authored-by: Christian Heimes <christian@python.org>
Lib/enum.py
Lib/test/test_enum.py
Misc/NEWS.d/next/Library/2022-06-15-21-20-02.gh-issue-93820.FAMLY8.rst [new file with mode: 0644]

index fe521b1018d481e537975d64d560e8aab5cb00d3..091acb3e7f343208d90162b964fac357ed252ab6 100644 (file)
@@ -1372,6 +1372,9 @@ class Flag(Enum, boundary=STRICT):
     Support for flags
     """
 
+    def __reduce_ex__(self, proto):
+        return self.__class__, (self._value_, )
+
     _numeric_repr_ = repr
 
     def _generate_next_value_(name, start, count, last_values):
index 56cebfea3f1ba9bc82b1eeb10bbc54543918c478..b44c5664e5104eccc28b53bbf7e644102be9ee88 100644 (file)
@@ -1,3 +1,4 @@
+import copy
 import enum
 import doctest
 import inspect
@@ -732,6 +733,13 @@ class _MinimalOutputTests:
             self.assertFormatIsValue('{:5.2}', 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:
 
@@ -2652,6 +2660,26 @@ class TestSpecial(unittest.TestCase):
         self.assertTrue(isinstance(MyIntFlag.ONE | MyIntFlag.TWO, MyIntFlag), MyIntFlag.ONE | MyIntFlag.TWO)
         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):
     "test usage of the `_order_` attribute"
 
diff --git a/Misc/NEWS.d/next/Library/2022-06-15-21-20-02.gh-issue-93820.FAMLY8.rst b/Misc/NEWS.d/next/Library/2022-06-15-21-20-02.gh-issue-93820.FAMLY8.rst
new file mode 100644 (file)
index 0000000..e06d897
--- /dev/null
@@ -0,0 +1,2 @@
+Fixed a regression when :func:`copy.copy`-ing :class:`enum.Flag` with
+multiple flag members.