issue23591: bool(empty_flags) == False; more docs & tests

This commit is contained in:
Ethan Furman 2016-09-02 16:32:32 -07:00
parent 0443953067
commit 25d94bbf05
3 changed files with 78 additions and 3 deletions

View File

@ -546,6 +546,10 @@ members also subclass :class:`int` and can be used wherever an :class:`int` is.
Any operation on an :class:`IntFlag` member besides the bit-wise operations Any operation on an :class:`IntFlag` member besides the bit-wise operations
will lose the :class:`IntFlag` membership. will lose the :class:`IntFlag` membership.
.. versionadded:: 3.6
Sample :class:`IntFlag` class::
>>> from enum import IntFlag >>> from enum import IntFlag
>>> class Perm(IntFlag): >>> class Perm(IntFlag):
... R = 4 ... R = 4
@ -560,19 +564,71 @@ will lose the :class:`IntFlag` membership.
>>> Perm.R in RW >>> Perm.R in RW
True True
.. versionadded:: 3.6 It is also possible to name the combinations::
>>> class Perm(IntFlag):
... R = 4
... W = 2
... X = 1
... RWX = 7
>>> Perm.RWX
<Perm.RWX: 7>
>>> ~Perm.RWX
<Perm.0: 0>
Another important difference between :class:`IntFlag` and :class:`Enum` is that
if no flags are set (the value is 0), its boolean evaluation is :data:`False`::
>>> Perm.R & Perm.X
<Perm.0: 0>
>>> bool(Perm.R & Perm.X)
False
Because :class:`IntFlag` members are also subclasses of :class:`int` they can
be combined with them::
>>> Perm.X | 8
<Perm.8|X: 9>
Flag Flag
^^^^ ^^^^
The last variation is :class:`Flag`. Like :class:`IntFlag`, :class:`Flag` The last variation is :class:`Flag`. Like :class:`IntFlag`, :class:`Flag`
members can be combined using the bitwise operators (^, \|, ^, ~). Unlike members can be combined using the bitwise operators (&, \|, ^, ~). Unlike
:class:`IntFlag`, they cannot be combined with, nor compared against, any :class:`IntFlag`, they cannot be combined with, nor compared against, any
other :class:`Flag` enumeration nor :class:`int`. other :class:`Flag` enumeration, nor :class:`int`.
.. versionadded:: 3.6 .. versionadded:: 3.6
Like :class:`IntFlag`, if a combination of :class:`Flag` members results in no
flags being set, the boolean evaluation is :data:`False`::
>>> from enum import Flag
>>> class Color(Flag):
... red = 1
... blue = 2
... green = 4
...
>>> Color.red & Color.green
<Color.0: 0>
>>> bool(Color.red & Color.green)
False
Giving a name to the "no flags set" condition does not change its boolean
value::
>>> class Color(Flag):
... black = 0
... red = 1
... blue = 2
... green = 4
...
>>> Color.black
<Color.black: 0>
>>> bool(Color.black)
False
.. note:: .. note::
For the majority of new code, :class:`Enum` and :class:`Flag` are strongly For the majority of new code, :class:`Enum` and :class:`Flag` are strongly

View File

@ -714,6 +714,9 @@ class Flag(Enum):
'|'.join([str(m._name_ or m._value_) for m in members]), '|'.join([str(m._name_ or m._value_) for m in members]),
) )
def __bool__(self):
return bool(self._value_)
def __or__(self, other): def __or__(self, other):
if not isinstance(other, self.__class__): if not isinstance(other, self.__class__):
return NotImplemented return NotImplemented

View File

@ -1767,6 +1767,14 @@ class TestFlag(unittest.TestCase):
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)
def test_bool(self):
Perm = self.Perm
for f in Perm:
self.assertTrue(f)
Open = self.Open
for f in Open:
self.assertEqual(bool(f.value), bool(f))
def test_programatic_function_string(self): def test_programatic_function_string(self):
Perm = Flag('Perm', 'R W X') Perm = Flag('Perm', 'R W X')
lst = list(Perm) lst = list(Perm)
@ -2137,6 +2145,14 @@ class TestIntFlag(unittest.TestCase):
self.assertFalse(W in RX) self.assertFalse(W in RX)
self.assertFalse(X in RW) self.assertFalse(X in RW)
def test_bool(self):
Perm = self.Perm
for f in Perm:
self.assertTrue(f)
Open = self.Open
for f in Open:
self.assertEqual(bool(f.value), bool(f))
class TestUnique(unittest.TestCase): class TestUnique(unittest.TestCase):
def test_unique_clean(self): def test_unique_clean(self):