]> granicus.if.org Git - python/commitdiff
issue23591: bool(empty_flags) == False; more docs & tests
authorEthan Furman <ethan@stoneleaf.us>
Fri, 2 Sep 2016 23:32:32 +0000 (16:32 -0700)
committerEthan Furman <ethan@stoneleaf.us>
Fri, 2 Sep 2016 23:32:32 +0000 (16:32 -0700)
Doc/library/enum.rst
Lib/enum.py
Lib/test/test_enum.py

index 72218b95457829564d523ff4fe7c9c9eccf8d87d..7a5bb5ffd466dacdeeada0e1565904786eb80d02 100644 (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
 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 @@ will lose the :class:`IntFlag` membership.
     >>> 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: 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
 ^^^^
 
 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
+    <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::
 
     For the majority of new code, :class:`Enum` and :class:`Flag` are strongly
index 8d23933d3ed7d63bf639eba65924afda576c08af..1e028a364f29cecaf8d54a03ab3937ff0a59d3da 100644 (file)
@@ -714,6 +714,9 @@ class Flag(Enum):
                     '|'.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
index cfe1b18e9a18f5f439845e22a780ee8ca2cb0a5b..cf704edb1bcbd2b3176c3ea67d03fad181d5c25f 100644 (file)
@@ -1767,6 +1767,14 @@ class TestFlag(unittest.TestCase):
         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 @@ class TestIntFlag(unittest.TestCase):
         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):