diff options
Diffstat (limited to 'Lib/test/test_enum.py')
-rw-r--r-- | Lib/test/test_enum.py | 316 |
1 files changed, 247 insertions, 69 deletions
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 unittest 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 ALWAYS_EQ 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 TestEnum(unittest.TestCase): 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 TestFlag(unittest.TestCase): 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 @@ class TestFlag(unittest.TestCase): 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 @@ class TestFlag(unittest.TestCase): 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 @@ class TestFlag(unittest.TestCase): 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 @@ class TestFlag(unittest.TestCase): 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 @@ class TestFlag(unittest.TestCase): 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 @@ class TestFlag(unittest.TestCase): 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 TestFlag(unittest.TestCase): 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 TestFlag(unittest.TestCase): 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 TestIntFlag(unittest.TestCase): 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 @@ class TestIntFlag(unittest.TestCase): 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 @@ class TestIntFlag(unittest.TestCase): 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 @@ class TestIntFlag(unittest.TestCase): 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 @@ class TestIntFlag(unittest.TestCase): 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 @@ class TestIntFlag(unittest.TestCase): 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 @@ class TestIntFlag(unittest.TestCase): 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 @@ expected_help_output_with_docs = """\ 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 @@ class TestStdLib(unittest.TestCase): 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 |