[Python-checkins] [3.12] gh-105497: [Enum] Fix Flag inversion when alias/mask members exist. (GH-105542) (#105572)
ambv
webhook-mailer at python.org
Wed Jul 5 07:40:03 EDT 2023
https://github.com/python/cpython/commit/74d84cf84d18e8cf69ffef0d7955f80fbc47220a
commit: 74d84cf84d18e8cf69ffef0d7955f80fbc47220a
branch: 3.12
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: ambv <lukasz at langa.pl>
date: 2023-07-05T13:39:59+02:00
summary:
[3.12] gh-105497: [Enum] Fix Flag inversion when alias/mask members exist. (GH-105542) (#105572)
gh-105497: [Enum] Fix Flag inversion when alias/mask members exist. (GH-105542)
When inverting a Flag member (or boundary STRICT), only consider other canonical flags; when inverting an IntFlag member (or boundary KEEP), also consider aliases.
(cherry picked from commit 59f009e5898a006cdc8f5249be589de6edfe5cd0)
Co-authored-by: Ethan Furman <ethan at stoneleaf.us>
files:
A Misc/NEWS.d/next/Library/2023-06-08-17-49-46.gh-issue-105497.K6Q8nU.rst
M Lib/enum.py
M Lib/test/test_enum.py
diff --git a/Lib/enum.py b/Lib/enum.py
index 62df304057a10..92a9632dc892d 100644
--- a/Lib/enum.py
+++ b/Lib/enum.py
@@ -1463,12 +1463,11 @@ def _missing_(cls, value):
else:
pseudo_member._name_ = None
# use setdefault in case another thread already created a composite
- # with this value, but only if all members are known
- # note: zero is a special case -- add it
- if not unknown:
- pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member)
- if neg_value is not None:
- cls._value2member_map_[neg_value] = pseudo_member
+ # with this value
+ # note: zero is a special case -- always add it
+ pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member)
+ if neg_value is not None:
+ cls._value2member_map_[neg_value] = pseudo_member
return pseudo_member
def __contains__(self, other):
@@ -1544,8 +1543,8 @@ def __invert__(self):
# use all bits
self._inverted_ = self.__class__(~self._value_)
else:
- # calculate flags not in this member
- self._inverted_ = self.__class__(self._flag_mask_ ^ self._value_)
+ # use canonical bits (i.e. calculate flags not in this member)
+ self._inverted_ = self.__class__(self._singles_mask_ ^ self._value_)
if isinstance(self._inverted_, self.__class__):
self._inverted_._inverted_ = self
return self._inverted_
diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py
index b4ac3abfc7006..291213a13f36b 100644
--- a/Lib/test/test_enum.py
+++ b/Lib/test/test_enum.py
@@ -3045,6 +3045,33 @@ class Color(Flag):
WHITE = RED|GREEN|BLUE
BLANCO = RED|GREEN|BLUE
+ class Complete(Flag):
+ A = 0x01
+ B = 0x02
+
+ class Partial(Flag):
+ A = 0x01
+ B = 0x02
+ MASK = 0xff
+
+ class CompleteInt(IntFlag):
+ A = 0x01
+ B = 0x02
+
+ class PartialInt(IntFlag):
+ A = 0x01
+ B = 0x02
+ MASK = 0xff
+
+ class CompleteIntStrict(IntFlag, boundary=STRICT):
+ A = 0x01
+ B = 0x02
+
+ class PartialIntStrict(IntFlag, boundary=STRICT):
+ A = 0x01
+ B = 0x02
+ MASK = 0xff
+
def test_or(self):
Perm = self.Perm
for i in Perm:
@@ -3103,6 +3130,18 @@ def test_invert(self):
Open = self.Open
self.assertIs(Open.WO & ~Open.WO, Open.RO)
self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
+ Complete = self.Complete
+ self.assertIs(~Complete.A, Complete.B)
+ Partial = self.Partial
+ self.assertIs(~Partial.A, Partial.B)
+ CompleteInt = self.CompleteInt
+ self.assertIs(~CompleteInt.A, CompleteInt.B)
+ PartialInt = self.PartialInt
+ self.assertIs(~PartialInt.A, PartialInt(254))
+ CompleteIntStrict = self.CompleteIntStrict
+ self.assertIs(~CompleteIntStrict.A, CompleteIntStrict.B)
+ PartialIntStrict = self.PartialIntStrict
+ self.assertIs(~PartialIntStrict.A, PartialIntStrict.B)
def test_bool(self):
Perm = self.Perm
diff --git a/Misc/NEWS.d/next/Library/2023-06-08-17-49-46.gh-issue-105497.K6Q8nU.rst b/Misc/NEWS.d/next/Library/2023-06-08-17-49-46.gh-issue-105497.K6Q8nU.rst
new file mode 100644
index 0000000000000..2d4e2091b5071
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-08-17-49-46.gh-issue-105497.K6Q8nU.rst
@@ -0,0 +1 @@
+Fix flag inversion when alias/mask members exist.
More information about the Python-checkins
mailing list