mirror of
https://github.com/python/cpython.git
synced 2025-08-15 06:10:47 +00:00
[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 59f009e589
)
Co-authored-by: Ethan Furman <ethan@stoneleaf.us>
This commit is contained in:
parent
da672b2d24
commit
74d84cf84d
3 changed files with 47 additions and 8 deletions
|
@ -1463,9 +1463,8 @@ class Flag(Enum, boundary=STRICT):
|
||||||
else:
|
else:
|
||||||
pseudo_member._name_ = None
|
pseudo_member._name_ = None
|
||||||
# use setdefault in case another thread already created a composite
|
# use setdefault in case another thread already created a composite
|
||||||
# with this value, but only if all members are known
|
# with this value
|
||||||
# note: zero is a special case -- add it
|
# note: zero is a special case -- always add it
|
||||||
if not unknown:
|
|
||||||
pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member)
|
pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member)
|
||||||
if neg_value is not None:
|
if neg_value is not None:
|
||||||
cls._value2member_map_[neg_value] = pseudo_member
|
cls._value2member_map_[neg_value] = pseudo_member
|
||||||
|
@ -1544,8 +1543,8 @@ class Flag(Enum, boundary=STRICT):
|
||||||
# use all bits
|
# use all bits
|
||||||
self._inverted_ = self.__class__(~self._value_)
|
self._inverted_ = self.__class__(~self._value_)
|
||||||
else:
|
else:
|
||||||
# calculate flags not in this member
|
# use canonical bits (i.e. calculate flags not in this member)
|
||||||
self._inverted_ = self.__class__(self._flag_mask_ ^ self._value_)
|
self._inverted_ = self.__class__(self._singles_mask_ ^ self._value_)
|
||||||
if isinstance(self._inverted_, self.__class__):
|
if isinstance(self._inverted_, self.__class__):
|
||||||
self._inverted_._inverted_ = self
|
self._inverted_._inverted_ = self
|
||||||
return self._inverted_
|
return self._inverted_
|
||||||
|
|
|
@ -3045,6 +3045,33 @@ class OldTestFlag(unittest.TestCase):
|
||||||
WHITE = RED|GREEN|BLUE
|
WHITE = RED|GREEN|BLUE
|
||||||
BLANCO = 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):
|
def test_or(self):
|
||||||
Perm = self.Perm
|
Perm = self.Perm
|
||||||
for i in Perm:
|
for i in Perm:
|
||||||
|
@ -3103,6 +3130,18 @@ class OldTestFlag(unittest.TestCase):
|
||||||
Open = self.Open
|
Open = self.Open
|
||||||
self.assertIs(Open.WO & ~Open.WO, Open.RO)
|
self.assertIs(Open.WO & ~Open.WO, Open.RO)
|
||||||
self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
|
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):
|
def test_bool(self):
|
||||||
Perm = self.Perm
|
Perm = self.Perm
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fix flag inversion when alias/mask members exist.
|
Loading…
Add table
Add a link
Reference in a new issue