diff options
author | Ethan Furman <ethan@stoneleaf.us> | 2016-09-02 16:32:32 -0700 |
---|---|---|
committer | Ethan Furman <ethan@stoneleaf.us> | 2016-09-02 16:32:32 -0700 |
commit | 25d94bbf05f37151e7e6e3a2e1cd5af4a3e5f68c (patch) | |
tree | 910a33c185d1f732a9a7545a3e9460672b10318e | |
parent | 044395306702fc47e63b43d5ad961a127c19b262 (diff) | |
download | cpython-git-25d94bbf05f37151e7e6e3a2e1cd5af4a3e5f68c.tar.gz |
issue23591: bool(empty_flags) == False; more docs & tests
-rw-r--r-- | Doc/library/enum.rst | 62 | ||||
-rw-r--r-- | Lib/enum.py | 3 | ||||
-rw-r--r-- | Lib/test/test_enum.py | 16 |
3 files changed, 78 insertions, 3 deletions
diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst index 72218b9545..7a5bb5ffd4 100644 --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -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 diff --git a/Lib/enum.py b/Lib/enum.py index 8d23933d3e..1e028a364f 100644 --- a/Lib/enum.py +++ b/Lib/enum.py @@ -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 diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py index cfe1b18e9a..cf704edb1b 100644 --- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -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): |