gh-78157: [Enum] nested classes will not be members in 3.13 (GH-92366)

- add member() and nonmember() functions
- add deprecation warning for internal classes in enums not
  becoming members in 3.13

Co-authored-by: edwardcwang
This commit is contained in:
Ethan Furman 2022-05-06 00:16:22 -07:00 committed by GitHub
parent fa4f0a134e
commit 93364f9716
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 219 additions and 4 deletions

View file

@ -12,6 +12,7 @@ from datetime import date
from enum import Enum, IntEnum, StrEnum, EnumType, Flag, IntFlag, unique, auto
from enum import STRICT, CONFORM, EJECT, KEEP, _simple_enum, _test_simple_enum
from enum import verify, UNIQUE, CONTINUOUS, NAMED_FLAGS, ReprEnum
from enum import member, nonmember
from io import StringIO
from pickle import dumps, loads, PicklingError, HIGHEST_PROTOCOL
from test import support
@ -938,6 +939,146 @@ class TestSpecial(unittest.TestCase):
raise Theory
self.assertEqual(Theory.__qualname__, 'spanish_inquisition')
def test_enum_of_types(self):
"""Support using Enum to refer to types deliberately."""
class MyTypes(Enum):
i = int
f = float
s = str
self.assertEqual(MyTypes.i.value, int)
self.assertEqual(MyTypes.f.value, float)
self.assertEqual(MyTypes.s.value, str)
class Foo:
pass
class Bar:
pass
class MyTypes2(Enum):
a = Foo
b = Bar
self.assertEqual(MyTypes2.a.value, Foo)
self.assertEqual(MyTypes2.b.value, Bar)
class SpamEnumNotInner:
pass
class SpamEnum(Enum):
spam = SpamEnumNotInner
self.assertEqual(SpamEnum.spam.value, SpamEnumNotInner)
@unittest.skipIf(
python_version >= (3, 13),
'inner classes are not members',
)
def test_nested_classes_in_enum_are_members(self):
"""
Check for warnings pre-3.13
"""
with self.assertWarnsRegex(DeprecationWarning, 'will not become a member'):
class Outer(Enum):
a = 1
b = 2
class Inner(Enum):
foo = 10
bar = 11
self.assertTrue(isinstance(Outer.Inner, Outer))
self.assertEqual(Outer.a.value, 1)
self.assertEqual(Outer.Inner.value.foo.value, 10)
self.assertEqual(
list(Outer.Inner.value),
[Outer.Inner.value.foo, Outer.Inner.value.bar],
)
self.assertEqual(
list(Outer),
[Outer.a, Outer.b, Outer.Inner],
)
@unittest.skipIf(
python_version < (3, 13),
'inner classes are still members',
)
def test_nested_classes_in_enum_are_not_members(self):
"""Support locally-defined nested classes."""
class Outer(Enum):
a = 1
b = 2
class Inner(Enum):
foo = 10
bar = 11
self.assertTrue(isinstance(Outer.Inner, type))
self.assertEqual(Outer.a.value, 1)
self.assertEqual(Outer.Inner.foo.value, 10)
self.assertEqual(
list(Outer.Inner),
[Outer.Inner.foo, Outer.Inner.bar],
)
self.assertEqual(
list(Outer),
[Outer.a, Outer.b],
)
def test_nested_classes_in_enum_with_nonmember(self):
class Outer(Enum):
a = 1
b = 2
@nonmember
class Inner(Enum):
foo = 10
bar = 11
self.assertTrue(isinstance(Outer.Inner, type))
self.assertEqual(Outer.a.value, 1)
self.assertEqual(Outer.Inner.foo.value, 10)
self.assertEqual(
list(Outer.Inner),
[Outer.Inner.foo, Outer.Inner.bar],
)
self.assertEqual(
list(Outer),
[Outer.a, Outer.b],
)
def test_enum_of_types_with_nonmember(self):
"""Support using Enum to refer to types deliberately."""
class MyTypes(Enum):
i = int
f = nonmember(float)
s = str
self.assertEqual(MyTypes.i.value, int)
self.assertTrue(MyTypes.f is float)
self.assertEqual(MyTypes.s.value, str)
class Foo:
pass
class Bar:
pass
class MyTypes2(Enum):
a = Foo
b = nonmember(Bar)
self.assertEqual(MyTypes2.a.value, Foo)
self.assertTrue(MyTypes2.b is Bar)
class SpamEnumIsInner:
pass
class SpamEnum(Enum):
spam = nonmember(SpamEnumIsInner)
self.assertTrue(SpamEnum.spam is SpamEnumIsInner)
def test_nested_classes_in_enum_with_member(self):
"""Support locally-defined nested classes."""
class Outer(Enum):
a = 1
b = 2
@member
class Inner(Enum):
foo = 10
bar = 11
self.assertTrue(isinstance(Outer.Inner, Outer))
self.assertEqual(Outer.a.value, 1)
self.assertEqual(Outer.Inner.value.foo.value, 10)
self.assertEqual(
list(Outer.Inner.value),
[Outer.Inner.value.foo, Outer.Inner.value.bar],
)
self.assertEqual(
list(Outer),
[Outer.a, Outer.b, Outer.Inner],
)
def test_enum_with_value_name(self):
class Huh(Enum):
name = 1