Commit 0866bb68 authored by Ethan Furman's avatar Ethan Furman

Close #18924: Block naive attempts to change an Enum member.

parent 46abcaa5
...@@ -263,6 +263,19 @@ class EnumMeta(type): ...@@ -263,6 +263,19 @@ class EnumMeta(type):
def __repr__(cls): def __repr__(cls):
return "<enum %r>" % cls.__name__ return "<enum %r>" % cls.__name__
def __setattr__(cls, name, value):
"""Block attempts to reassign Enum members.
A simple assignment to the class namespace only changes one of the
several possible ways to get an Enum member from the Enum class,
resulting in an inconsistent Enumeration.
"""
member_map = cls.__dict__.get('_member_map_', {})
if name in member_map:
raise AttributeError('Cannot reassign members.')
super().__setattr__(name, value)
def _create_(cls, class_name, names=None, *, module=None, type=None): def _create_(cls, class_name, names=None, *, module=None, type=None):
"""Convenience method to create a new Enum class. """Convenience method to create a new Enum class.
......
...@@ -152,6 +152,11 @@ class TestEnum(unittest.TestCase): ...@@ -152,6 +152,11 @@ class TestEnum(unittest.TestCase):
with self.assertRaises(AttributeError): with self.assertRaises(AttributeError):
Season.SPRING.value = 2 Season.SPRING.value = 2
def test_changing_member(self):
Season = self.Season
with self.assertRaises(AttributeError):
Season.WINTER = 'really cold'
def test_invalid_names(self): def test_invalid_names(self):
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
class Wrong(Enum): class Wrong(Enum):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment