bpo-38250: [Enum] single-bit flags are canonical (GH-24215)
Flag members are now divided by one-bit verses multi-bit, with multi-bit being treated as aliases. Iterating over a flag only returns the contained single-bit flags.
Iterating, repr(), and str() show members in definition order.
When constructing combined-member flags, any extra integer values are either discarded (CONFORM), turned into ints (EJECT) or treated as errors (STRICT). Flag classes can specify which of those three behaviors is desired:
>>> class Test(Flag, boundary=CONFORM):
... ONE = 1
... TWO = 2
...
>>> Test(5)
<Test.ONE: 1>
Besides the three above behaviors, there is also KEEP, which should not be used unless necessary -- for example, _convert_ specifies KEEP as there are flag sets in the stdlib that are incomplete and/or inconsistent (e.g. ssl.Options). KEEP will, as the name suggests, keep all bits; however, iterating over a flag with extra bits will only return the canonical flags contained, not the extra bits.
Iteration is now in member definition order. If member definition order
matches increasing value order, then a more efficient method of flag
decomposition is used; otherwise, sort() is called on the results of
that method to get definition order.
``re`` module:
repr() has been modified to support as closely as possible its previous
output; the big difference is that inverted flags cannot be output as
before because the inversion operation now always returns the comparable
positive result; i.e.
re.A|re.I|re.M|re.S is ~(re.L|re.U|re.S|re.T|re.DEBUG)
in both of the above terms, the ``value`` is 282.
re's tests have been updated to reflect the modifications to repr().
diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py
index 3ea623e..daca2e3 100644
--- a/Lib/test/test_enum.py
+++ b/Lib/test/test_enum.py
@@ -1,4 +1,5 @@
import enum
+import doctest
import inspect
import pydoc
import sys
@@ -6,6 +7,7 @@
import threading
from collections import OrderedDict
from enum import Enum, IntEnum, StrEnum, EnumMeta, Flag, IntFlag, unique, auto
+from enum import STRICT, CONFORM, EJECT, KEEP
from io import StringIO
from pickle import dumps, loads, PicklingError, HIGHEST_PROTOCOL
from test import support
@@ -13,6 +15,13 @@
from test.support import threading_helper
from datetime import timedelta
+def load_tests(loader, tests, ignore):
+ tests.addTests(doctest.DocTestSuite(enum))
+ tests.addTests(doctest.DocFileSuite(
+ '../../Doc/library/enum.rst',
+ optionflags=doctest.ELLIPSIS|doctest.NORMALIZE_WHITESPACE,
+ ))
+ return tests
# for pickle tests
try:
@@ -2126,7 +2135,30 @@ class ThirdFailedStrEnum(StrEnum):
one = '1'
two = b'2', 'ascii', 9
-
+ def test_missing_value_error(self):
+ with self.assertRaisesRegex(TypeError, "_value_ not set in __new__"):
+ class Combined(str, Enum):
+ #
+ def __new__(cls, value, sequence):
+ enum = str.__new__(cls, value)
+ if '(' in value:
+ fis_name, segment = value.split('(', 1)
+ segment = segment.strip(' )')
+ else:
+ fis_name = value
+ segment = None
+ enum.fis_name = fis_name
+ enum.segment = segment
+ enum.sequence = sequence
+ return enum
+ #
+ def __repr__(self):
+ return "<%s.%s>" % (self.__class__.__name__, self._name_)
+ #
+ key_type = 'An$(1,2)', 0
+ company_id = 'An$(3,2)', 1
+ code = 'An$(5,1)', 2
+ description = 'Bn$', 3
@unittest.skipUnless(
sys.version_info[:2] == (3, 9),
@@ -2264,9 +2296,12 @@ class Open(Flag):
class Color(Flag):
BLACK = 0
RED = 1
+ ROJO = 1
GREEN = 2
BLUE = 4
PURPLE = RED|BLUE
+ WHITE = RED|GREEN|BLUE
+ BLANCO = RED|GREEN|BLUE
def test_str(self):
Perm = self.Perm
@@ -2275,12 +2310,12 @@ def test_str(self):
self.assertEqual(str(Perm.X), 'Perm.X')
self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W')
self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X')
- self.assertEqual(str(Perm(0)), 'Perm.0')
+ self.assertEqual(str(Perm(0)), 'Perm(0)')
self.assertEqual(str(~Perm.R), 'Perm.W|X')
self.assertEqual(str(~Perm.W), 'Perm.R|X')
self.assertEqual(str(~Perm.X), 'Perm.R|W')
self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X')
- self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.0')
+ self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm(0)')
self.assertEqual(str(Perm(~0)), 'Perm.R|W|X')
Open = self.Open
@@ -2288,10 +2323,11 @@ def test_str(self):
self.assertEqual(str(Open.WO), 'Open.WO')
self.assertEqual(str(Open.AC), 'Open.AC')
self.assertEqual(str(Open.RO | Open.CE), 'Open.CE')
- self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO')
- self.assertEqual(str(~Open.RO), 'Open.CE|AC|RW|WO')
- self.assertEqual(str(~Open.WO), 'Open.CE|RW')
+ self.assertEqual(str(Open.WO | Open.CE), 'Open.WO|CE')
+ self.assertEqual(str(~Open.RO), 'Open.WO|RW|CE')
+ self.assertEqual(str(~Open.WO), 'Open.RW|CE')
self.assertEqual(str(~Open.AC), 'Open.CE')
+ self.assertEqual(str(~Open.CE), 'Open.AC')
self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC')
self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW')
@@ -2302,12 +2338,12 @@ def test_repr(self):
self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
- self.assertEqual(repr(Perm(0)), '<Perm.0: 0>')
+ self.assertEqual(repr(Perm(0)), '<Perm: 0>')
self.assertEqual(repr(~Perm.R), '<Perm.W|X: 3>')
self.assertEqual(repr(~Perm.W), '<Perm.R|X: 5>')
self.assertEqual(repr(~Perm.X), '<Perm.R|W: 6>')
self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: 1>')
- self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm.0: 0>')
+ self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm: 0>')
self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: 7>')
Open = self.Open
@@ -2315,10 +2351,11 @@ def test_repr(self):
self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
- self.assertEqual(repr(Open.WO | Open.CE), '<Open.CE|WO: 524289>')
- self.assertEqual(repr(~Open.RO), '<Open.CE|AC|RW|WO: 524291>')
- self.assertEqual(repr(~Open.WO), '<Open.CE|RW: 524290>')
+ self.assertEqual(repr(Open.WO | Open.CE), '<Open.WO|CE: 524289>')
+ self.assertEqual(repr(~Open.RO), '<Open.WO|RW|CE: 524291>')
+ self.assertEqual(repr(~Open.WO), '<Open.RW|CE: 524290>')
self.assertEqual(repr(~Open.AC), '<Open.CE: 524288>')
+ self.assertEqual(repr(~Open.CE), '<Open.AC: 3>')
self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC: 3>')
self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: 2>')
@@ -2394,6 +2431,46 @@ def test_bool(self):
for f in Open:
self.assertEqual(bool(f.value), bool(f))
+ def test_boundary(self):
+ self.assertIs(enum.Flag._boundary_, STRICT)
+ class Iron(Flag, boundary=STRICT):
+ ONE = 1
+ TWO = 2
+ EIGHT = 8
+ self.assertIs(Iron._boundary_, STRICT)
+ #
+ class Water(Flag, boundary=CONFORM):
+ ONE = 1
+ TWO = 2
+ EIGHT = 8
+ self.assertIs(Water._boundary_, CONFORM)
+ #
+ class Space(Flag, boundary=EJECT):
+ ONE = 1
+ TWO = 2
+ EIGHT = 8
+ self.assertIs(Space._boundary_, EJECT)
+ #
+ class Bizarre(Flag, boundary=KEEP):
+ b = 3
+ c = 4
+ d = 6
+ #
+ self.assertRaisesRegex(ValueError, 'invalid value: 7', Iron, 7)
+ self.assertIs(Water(7), Water.ONE|Water.TWO)
+ self.assertIs(Water(~9), Water.TWO)
+ self.assertEqual(Space(7), 7)
+ self.assertTrue(type(Space(7)) is int)
+ self.assertEqual(list(Bizarre), [Bizarre.c])
+ self.assertIs(Bizarre(3), Bizarre.b)
+ self.assertIs(Bizarre(6), Bizarre.d)
+
+ def test_iter(self):
+ Color = self.Color
+ Open = self.Open
+ self.assertEqual(list(Color), [Color.RED, Color.GREEN, Color.BLUE])
+ self.assertEqual(list(Open), [Open.WO, Open.RW, Open.CE])
+
def test_programatic_function_string(self):
Perm = Flag('Perm', 'R W X')
lst = list(Perm)
@@ -2511,9 +2588,45 @@ def test_member_contains(self):
def test_member_iter(self):
Color = self.Color
- self.assertEqual(list(Color.PURPLE), [Color.BLUE, Color.RED])
+ self.assertEqual(list(Color.BLACK), [])
+ self.assertEqual(list(Color.PURPLE), [Color.RED, Color.BLUE])
self.assertEqual(list(Color.BLUE), [Color.BLUE])
self.assertEqual(list(Color.GREEN), [Color.GREEN])
+ self.assertEqual(list(Color.WHITE), [Color.RED, Color.GREEN, Color.BLUE])
+ self.assertEqual(list(Color.WHITE), [Color.RED, Color.GREEN, Color.BLUE])
+
+ def test_member_length(self):
+ self.assertEqual(self.Color.__len__(self.Color.BLACK), 0)
+ self.assertEqual(self.Color.__len__(self.Color.GREEN), 1)
+ self.assertEqual(self.Color.__len__(self.Color.PURPLE), 2)
+ self.assertEqual(self.Color.__len__(self.Color.BLANCO), 3)
+
+ def test_number_reset_and_order_cleanup(self):
+ class Confused(Flag):
+ _order_ = 'ONE TWO FOUR DOS EIGHT SIXTEEN'
+ ONE = auto()
+ TWO = auto()
+ FOUR = auto()
+ DOS = 2
+ EIGHT = auto()
+ SIXTEEN = auto()
+ self.assertEqual(
+ list(Confused),
+ [Confused.ONE, Confused.TWO, Confused.FOUR, Confused.EIGHT, Confused.SIXTEEN])
+ self.assertIs(Confused.TWO, Confused.DOS)
+ self.assertEqual(Confused.DOS._value_, 2)
+ self.assertEqual(Confused.EIGHT._value_, 8)
+ self.assertEqual(Confused.SIXTEEN._value_, 16)
+
+ def test_aliases(self):
+ Color = self.Color
+ self.assertEqual(Color(1).name, 'RED')
+ self.assertEqual(Color['ROJO'].name, 'RED')
+ self.assertEqual(Color(7).name, 'WHITE')
+ self.assertEqual(Color['BLANCO'].name, 'WHITE')
+ self.assertIs(Color.BLANCO, Color.WHITE)
+ Open = self.Open
+ self.assertIs(Open['AC'], Open.AC)
def test_auto_number(self):
class Color(Flag):
@@ -2532,20 +2645,6 @@ class Color(Flag):
red = 'not an int'
blue = auto()
- def test_cascading_failure(self):
- class Bizarre(Flag):
- c = 3
- d = 4
- f = 6
- # Bizarre.c | Bizarre.d
- name = "TestFlag.test_cascading_failure.<locals>.Bizarre"
- self.assertRaisesRegex(ValueError, "5 is not a valid " + name, Bizarre, 5)
- self.assertRaisesRegex(ValueError, "5 is not a valid " + name, Bizarre, 5)
- self.assertRaisesRegex(ValueError, "2 is not a valid " + name, Bizarre, 2)
- self.assertRaisesRegex(ValueError, "2 is not a valid " + name, Bizarre, 2)
- self.assertRaisesRegex(ValueError, "1 is not a valid " + name, Bizarre, 1)
- self.assertRaisesRegex(ValueError, "1 is not a valid " + name, Bizarre, 1)
-
def test_duplicate_auto(self):
class Dupes(Enum):
first = primero = auto()
@@ -2554,11 +2653,11 @@ class Dupes(Enum):
self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes))
def test_bizarre(self):
- class Bizarre(Flag):
- b = 3
- c = 4
- d = 6
- self.assertEqual(repr(Bizarre(7)), '<Bizarre.d|c|b: 7>')
+ with self.assertRaisesRegex(TypeError, "invalid Flag 'Bizarre' -- missing values: 1, 2"):
+ class Bizarre(Flag):
+ b = 3
+ c = 4
+ d = 6
def test_multiple_mixin(self):
class AllMixin:
@@ -2682,9 +2781,9 @@ class TestIntFlag(unittest.TestCase):
"""Tests of the IntFlags."""
class Perm(IntFlag):
- X = 1 << 0
- W = 1 << 1
R = 1 << 2
+ W = 1 << 1
+ X = 1 << 0
class Open(IntFlag):
RO = 0
@@ -2696,9 +2795,17 @@ class Open(IntFlag):
class Color(IntFlag):
BLACK = 0
RED = 1
+ ROJO = 1
GREEN = 2
BLUE = 4
PURPLE = RED|BLUE
+ WHITE = RED|GREEN|BLUE
+ BLANCO = RED|GREEN|BLUE
+
+ class Skip(IntFlag):
+ FIRST = 1
+ SECOND = 2
+ EIGHTH = 8
def test_type(self):
Perm = self.Perm
@@ -2723,31 +2830,35 @@ def test_str(self):
self.assertEqual(str(Perm.X), 'Perm.X')
self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W')
self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X')
- self.assertEqual(str(Perm.R | 8), 'Perm.8|R')
- self.assertEqual(str(Perm(0)), 'Perm.0')
- self.assertEqual(str(Perm(8)), 'Perm.8')
+ self.assertEqual(str(Perm.R | 8), '12')
+ self.assertEqual(str(Perm(0)), 'Perm(0)')
+ self.assertEqual(str(Perm(8)), '8')
self.assertEqual(str(~Perm.R), 'Perm.W|X')
self.assertEqual(str(~Perm.W), 'Perm.R|X')
self.assertEqual(str(~Perm.X), 'Perm.R|W')
self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X')
- self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.-8')
- self.assertEqual(str(~(Perm.R | 8)), 'Perm.W|X')
+ self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm(0)')
+ self.assertEqual(str(~(Perm.R | 8)), '-13')
self.assertEqual(str(Perm(~0)), 'Perm.R|W|X')
- self.assertEqual(str(Perm(~8)), 'Perm.R|W|X')
+ self.assertEqual(str(Perm(~8)), '-9')
Open = self.Open
self.assertEqual(str(Open.RO), 'Open.RO')
self.assertEqual(str(Open.WO), 'Open.WO')
self.assertEqual(str(Open.AC), 'Open.AC')
self.assertEqual(str(Open.RO | Open.CE), 'Open.CE')
- self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO')
- self.assertEqual(str(Open(4)), 'Open.4')
- self.assertEqual(str(~Open.RO), 'Open.CE|AC|RW|WO')
- self.assertEqual(str(~Open.WO), 'Open.CE|RW')
+ self.assertEqual(str(Open.WO | Open.CE), 'Open.WO|CE')
+ self.assertEqual(str(Open(4)), '4')
+ self.assertEqual(str(~Open.RO), 'Open.WO|RW|CE')
+ self.assertEqual(str(~Open.WO), 'Open.RW|CE')
self.assertEqual(str(~Open.AC), 'Open.CE')
- self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC|RW|WO')
+ self.assertEqual(str(~Open.CE), 'Open.AC')
+ self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC')
self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW')
- self.assertEqual(str(Open(~4)), 'Open.CE|AC|RW|WO')
+ self.assertEqual(str(Open(~4)), '-5')
+
+ Skip = self.Skip
+ self.assertEqual(str(Skip(~4)), 'Skip.FIRST|SECOND|EIGHTH')
def test_repr(self):
Perm = self.Perm
@@ -2756,31 +2867,34 @@ def test_repr(self):
self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
- self.assertEqual(repr(Perm.R | 8), '<Perm.8|R: 12>')
- self.assertEqual(repr(Perm(0)), '<Perm.0: 0>')
- self.assertEqual(repr(Perm(8)), '<Perm.8: 8>')
- self.assertEqual(repr(~Perm.R), '<Perm.W|X: -5>')
- self.assertEqual(repr(~Perm.W), '<Perm.R|X: -3>')
- self.assertEqual(repr(~Perm.X), '<Perm.R|W: -2>')
- self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: -7>')
- self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm.-8: -8>')
- self.assertEqual(repr(~(Perm.R | 8)), '<Perm.W|X: -13>')
- self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: -1>')
- self.assertEqual(repr(Perm(~8)), '<Perm.R|W|X: -9>')
+ self.assertEqual(repr(Perm.R | 8), '12')
+ self.assertEqual(repr(Perm(0)), '<Perm: 0>')
+ self.assertEqual(repr(Perm(8)), '8')
+ self.assertEqual(repr(~Perm.R), '<Perm.W|X: 3>')
+ self.assertEqual(repr(~Perm.W), '<Perm.R|X: 5>')
+ self.assertEqual(repr(~Perm.X), '<Perm.R|W: 6>')
+ self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: 1>')
+ self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm: 0>')
+ self.assertEqual(repr(~(Perm.R | 8)), '-13')
+ self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: 7>')
+ self.assertEqual(repr(Perm(~8)), '-9')
Open = self.Open
self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
- self.assertEqual(repr(Open.WO | Open.CE), '<Open.CE|WO: 524289>')
- self.assertEqual(repr(Open(4)), '<Open.4: 4>')
- self.assertEqual(repr(~Open.RO), '<Open.CE|AC|RW|WO: -1>')
- self.assertEqual(repr(~Open.WO), '<Open.CE|RW: -2>')
- self.assertEqual(repr(~Open.AC), '<Open.CE: -4>')
- self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC|RW|WO: -524289>')
- self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: -524290>')
- self.assertEqual(repr(Open(~4)), '<Open.CE|AC|RW|WO: -5>')
+ self.assertEqual(repr(Open.WO | Open.CE), '<Open.WO|CE: 524289>')
+ self.assertEqual(repr(Open(4)), '4')
+ self.assertEqual(repr(~Open.RO), '<Open.WO|RW|CE: 524291>')
+ self.assertEqual(repr(~Open.WO), '<Open.RW|CE: 524290>')
+ self.assertEqual(repr(~Open.AC), '<Open.CE: 524288>')
+ self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC: 3>')
+ self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: 2>')
+ self.assertEqual(repr(Open(~4)), '-5')
+
+ Skip = self.Skip
+ self.assertEqual(repr(Skip(~4)), '<Skip.FIRST|SECOND|EIGHTH: 11>')
def test_format(self):
Perm = self.Perm
@@ -2863,8 +2977,7 @@ def test_invert(self):
RWX = Perm.R | Perm.W | Perm.X
values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
for i in values:
- self.assertEqual(~i, ~i.value)
- self.assertEqual((~i).value, ~i.value)
+ self.assertEqual(~i, (~i).value)
self.assertIs(type(~i), Perm)
self.assertEqual(~~i, i)
for i in Perm:
@@ -2873,6 +2986,46 @@ def test_invert(self):
self.assertIs(Open.WO & ~Open.WO, Open.RO)
self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
+ def test_boundary(self):
+ self.assertIs(enum.IntFlag._boundary_, EJECT)
+ class Iron(IntFlag, boundary=STRICT):
+ ONE = 1
+ TWO = 2
+ EIGHT = 8
+ self.assertIs(Iron._boundary_, STRICT)
+ #
+ class Water(IntFlag, boundary=CONFORM):
+ ONE = 1
+ TWO = 2
+ EIGHT = 8
+ self.assertIs(Water._boundary_, CONFORM)
+ #
+ class Space(IntFlag, boundary=EJECT):
+ ONE = 1
+ TWO = 2
+ EIGHT = 8
+ self.assertIs(Space._boundary_, EJECT)
+ #
+ class Bizarre(IntFlag, boundary=KEEP):
+ b = 3
+ c = 4
+ d = 6
+ #
+ self.assertRaisesRegex(ValueError, 'invalid value: 5', Iron, 5)
+ self.assertIs(Water(7), Water.ONE|Water.TWO)
+ self.assertIs(Water(~9), Water.TWO)
+ self.assertEqual(Space(7), 7)
+ self.assertTrue(type(Space(7)) is int)
+ self.assertEqual(list(Bizarre), [Bizarre.c])
+ self.assertIs(Bizarre(3), Bizarre.b)
+ self.assertIs(Bizarre(6), Bizarre.d)
+
+ def test_iter(self):
+ Color = self.Color
+ Open = self.Open
+ self.assertEqual(list(Color), [Color.RED, Color.GREEN, Color.BLUE])
+ self.assertEqual(list(Open), [Open.WO, Open.RW, Open.CE])
+
def test_programatic_function_string(self):
Perm = IntFlag('Perm', 'R W X')
lst = list(Perm)
@@ -3014,9 +3167,27 @@ def test_member_contains(self):
def test_member_iter(self):
Color = self.Color
- self.assertEqual(list(Color.PURPLE), [Color.BLUE, Color.RED])
+ self.assertEqual(list(Color.BLACK), [])
+ self.assertEqual(list(Color.PURPLE), [Color.RED, Color.BLUE])
self.assertEqual(list(Color.BLUE), [Color.BLUE])
self.assertEqual(list(Color.GREEN), [Color.GREEN])
+ self.assertEqual(list(Color.WHITE), [Color.RED, Color.GREEN, Color.BLUE])
+
+ def test_member_length(self):
+ self.assertEqual(self.Color.__len__(self.Color.BLACK), 0)
+ self.assertEqual(self.Color.__len__(self.Color.GREEN), 1)
+ self.assertEqual(self.Color.__len__(self.Color.PURPLE), 2)
+ self.assertEqual(self.Color.__len__(self.Color.BLANCO), 3)
+
+ def test_aliases(self):
+ Color = self.Color
+ self.assertEqual(Color(1).name, 'RED')
+ self.assertEqual(Color['ROJO'].name, 'RED')
+ self.assertEqual(Color(7).name, 'WHITE')
+ self.assertEqual(Color['BLANCO'].name, 'WHITE')
+ self.assertIs(Color.BLANCO, Color.WHITE)
+ Open = self.Open
+ self.assertIs(Open['AC'], Open.AC)
def test_bool(self):
Perm = self.Perm
@@ -3026,6 +3197,13 @@ def test_bool(self):
for f in Open:
self.assertEqual(bool(f.value), bool(f))
+ def test_bizarre(self):
+ with self.assertRaisesRegex(TypeError, "invalid Flag 'Bizarre' -- missing values: 1, 2"):
+ class Bizarre(IntFlag):
+ b = 3
+ c = 4
+ d = 6
+
def test_multiple_mixin(self):
class AllMixin:
@classproperty
@@ -3176,7 +3354,7 @@ class Sillier(IntEnum):
Help on class Color in module %s:
class Color(enum.Enum)
- | Color(value, names=None, *, module=None, qualname=None, type=None, start=1)
+ | Color(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)
|\x20\x20
| An enumeration.
|\x20\x20
@@ -3328,7 +3506,7 @@ def test_inspect_classify_class_attrs(self):
class MiscTestCase(unittest.TestCase):
def test__all__(self):
- support.check__all__(self, enum)
+ support.check__all__(self, enum, not_exported={'bin'})
# These are unordered here on purpose to ensure that declaration order