bpo-34750: [Enum] add `_EnumDict.update()` support (GH-23725)
This allows easier Enum construction in unusual cases, such as including dynamic member definitions into a class definition: # created dynamically foo_defines = {'FOO_CAT': 'aloof', 'BAR_DOG': 'friendly', 'FOO_HORSE': 'big'} class Foo(Enum): vars().update({ k: v for k, v in foo_defines.items() if k.startswith('FOO_') }) def upper(self): # example method return self.value.upper()
This commit is contained in:
parent
efb13be72c
commit
a658287179
12
Lib/enum.py
12
Lib/enum.py
|
@ -136,7 +136,7 @@ class _EnumDict(dict):
|
||||||
key = '_order_'
|
key = '_order_'
|
||||||
elif key in self._member_names:
|
elif key in self._member_names:
|
||||||
# descriptor overwriting an enum?
|
# descriptor overwriting an enum?
|
||||||
raise TypeError('Attempted to reuse key: %r' % key)
|
raise TypeError('%r already defined as: %r' % (key, self[key]))
|
||||||
elif key in self._ignore:
|
elif key in self._ignore:
|
||||||
pass
|
pass
|
||||||
elif not _is_descriptor(value):
|
elif not _is_descriptor(value):
|
||||||
|
@ -157,6 +157,16 @@ class _EnumDict(dict):
|
||||||
self._last_values.append(value)
|
self._last_values.append(value)
|
||||||
super().__setitem__(key, value)
|
super().__setitem__(key, value)
|
||||||
|
|
||||||
|
def update(self, members, **more_members):
|
||||||
|
try:
|
||||||
|
for name in members.keys():
|
||||||
|
self[name] = members[name]
|
||||||
|
except AttributeError:
|
||||||
|
for name, value in members:
|
||||||
|
self[name] = value
|
||||||
|
for name, value in more_members.items():
|
||||||
|
self[name] = value
|
||||||
|
|
||||||
|
|
||||||
# Dummy value for Enum as EnumMeta explicitly checks for it, but of course
|
# Dummy value for Enum as EnumMeta explicitly checks for it, but of course
|
||||||
# until EnumMeta finishes running the first time the Enum class doesn't exist.
|
# until EnumMeta finishes running the first time the Enum class doesn't exist.
|
||||||
|
|
|
@ -2186,6 +2186,34 @@ class TestEnum(unittest.TestCase):
|
||||||
self.assertEqual([Strings.ONE, Strings.TWO], ['one', 'two'])
|
self.assertEqual([Strings.ONE, Strings.TWO], ['one', 'two'])
|
||||||
|
|
||||||
|
|
||||||
|
def test_dynamic_members_with_static_methods(self):
|
||||||
|
#
|
||||||
|
foo_defines = {'FOO_CAT': 'aloof', 'BAR_DOG': 'friendly', 'FOO_HORSE': 'big'}
|
||||||
|
class Foo(Enum):
|
||||||
|
vars().update({
|
||||||
|
k: v
|
||||||
|
for k, v in foo_defines.items()
|
||||||
|
if k.startswith('FOO_')
|
||||||
|
})
|
||||||
|
def upper(self):
|
||||||
|
return self.value.upper()
|
||||||
|
self.assertEqual(list(Foo), [Foo.FOO_CAT, Foo.FOO_HORSE])
|
||||||
|
self.assertEqual(Foo.FOO_CAT.value, 'aloof')
|
||||||
|
self.assertEqual(Foo.FOO_HORSE.upper(), 'BIG')
|
||||||
|
#
|
||||||
|
with self.assertRaisesRegex(TypeError, "'FOO_CAT' already defined as: 'aloof'"):
|
||||||
|
class FooBar(Enum):
|
||||||
|
vars().update({
|
||||||
|
k: v
|
||||||
|
for k, v in foo_defines.items()
|
||||||
|
if k.startswith('FOO_')
|
||||||
|
},
|
||||||
|
**{'FOO_CAT': 'small'},
|
||||||
|
)
|
||||||
|
def upper(self):
|
||||||
|
return self.value.upper()
|
||||||
|
|
||||||
|
|
||||||
class TestOrder(unittest.TestCase):
|
class TestOrder(unittest.TestCase):
|
||||||
|
|
||||||
def test_same_members(self):
|
def test_same_members(self):
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
[Enum] `_EnumDict.update()` is now supported
|
Loading…
Reference in New Issue