changeset: 103011:f33fc2117bb2 user: Ethan Furman date: Fri Sep 02 16:32:32 2016 -0700 files: Doc/library/enum.rst Lib/enum.py Lib/test/test_enum.py description: issue23591: bool(empty_flags) == False; more docs & tests diff -r 31586a2f01b6 -r f33fc2117bb2 Doc/library/enum.rst --- a/Doc/library/enum.rst Fri Sep 02 15:50:21 2016 -0700 +++ b/Doc/library/enum.rst Fri Sep 02 16:32:32 2016 -0700 @@ -546,6 +546,10 @@ Any operation on an :class:`IntFlag` member besides the bit-wise operations will lose the :class:`IntFlag` membership. +.. versionadded:: 3.6 + +Sample :class:`IntFlag` class:: + >>> from enum import IntFlag >>> class Perm(IntFlag): ... R = 4 @@ -560,19 +564,71 @@ >>> Perm.R in RW 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 + + +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 + + >>> 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 + 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 -other :class:`Flag` enumeration nor :class:`int`. +other :class:`Flag` enumeration, nor :class:`int`. .. 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 + + >>> 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 + + >>> bool(Color.black) + False + .. note:: For the majority of new code, :class:`Enum` and :class:`Flag` are strongly diff -r 31586a2f01b6 -r f33fc2117bb2 Lib/enum.py --- a/Lib/enum.py Fri Sep 02 15:50:21 2016 -0700 +++ b/Lib/enum.py Fri Sep 02 16:32:32 2016 -0700 @@ -714,6 +714,9 @@ '|'.join([str(m._name_ or m._value_) for m in members]), ) + def __bool__(self): + return bool(self._value_) + def __or__(self, other): if not isinstance(other, self.__class__): return NotImplemented diff -r 31586a2f01b6 -r f33fc2117bb2 Lib/test/test_enum.py --- a/Lib/test/test_enum.py Fri Sep 02 15:50:21 2016 -0700 +++ b/Lib/test/test_enum.py Fri Sep 02 16:32:32 2016 -0700 @@ -1767,6 +1767,14 @@ self.assertIs(Open.WO & ~Open.WO, Open.RO) 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): Perm = Flag('Perm', 'R W X') lst = list(Perm) @@ -2137,6 +2145,14 @@ self.assertFalse(W in RX) 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): def test_unique_clean(self):