mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
bpo-40025: Require _generate_next_value_ to be defined before members (GH-19098)
require `_generate_next_value_` to be defined before members
This commit is contained in:
parent
a42ca74fa3
commit
d9a43e20fa
5 changed files with 21 additions and 0 deletions
|
@ -273,6 +273,10 @@ overridden::
|
||||||
the next :class:`int` in sequence with the last :class:`int` provided, but
|
the next :class:`int` in sequence with the last :class:`int` provided, but
|
||||||
the way it does this is an implementation detail and may change.
|
the way it does this is an implementation detail and may change.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
The :meth:`_generate_next_value_` method must be defined before any members.
|
||||||
|
|
||||||
Iteration
|
Iteration
|
||||||
---------
|
---------
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,7 @@ class _EnumDict(dict):
|
||||||
self._member_names = []
|
self._member_names = []
|
||||||
self._last_values = []
|
self._last_values = []
|
||||||
self._ignore = []
|
self._ignore = []
|
||||||
|
self._auto_called = False
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
"""Changes anything not dundered or not a descriptor.
|
"""Changes anything not dundered or not a descriptor.
|
||||||
|
@ -77,6 +78,9 @@ class _EnumDict(dict):
|
||||||
):
|
):
|
||||||
raise ValueError('_names_ are reserved for future Enum use')
|
raise ValueError('_names_ are reserved for future Enum use')
|
||||||
if key == '_generate_next_value_':
|
if key == '_generate_next_value_':
|
||||||
|
# check if members already defined as auto()
|
||||||
|
if self._auto_called:
|
||||||
|
raise TypeError("_generate_next_value_ must be defined before members")
|
||||||
setattr(self, '_generate_next_value', value)
|
setattr(self, '_generate_next_value', value)
|
||||||
elif key == '_ignore_':
|
elif key == '_ignore_':
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
|
@ -100,6 +104,7 @@ class _EnumDict(dict):
|
||||||
# enum overwriting a descriptor?
|
# enum overwriting a descriptor?
|
||||||
raise TypeError('%r already defined as: %r' % (key, self[key]))
|
raise TypeError('%r already defined as: %r' % (key, self[key]))
|
||||||
if isinstance(value, auto):
|
if isinstance(value, auto):
|
||||||
|
self._auto_called = True
|
||||||
if value.value == _auto_null:
|
if value.value == _auto_null:
|
||||||
value.value = self._generate_next_value(key, 1, len(self._member_names), self._last_values[:])
|
value.value = self._generate_next_value(key, 1, len(self._member_names), self._last_values[:])
|
||||||
value = value.value
|
value = value.value
|
||||||
|
|
|
@ -1751,6 +1751,16 @@ class TestEnum(unittest.TestCase):
|
||||||
self.assertEqual(Color.blue.value, 2)
|
self.assertEqual(Color.blue.value, 2)
|
||||||
self.assertEqual(Color.green.value, 3)
|
self.assertEqual(Color.green.value, 3)
|
||||||
|
|
||||||
|
def test_auto_order(self):
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
class Color(Enum):
|
||||||
|
red = auto()
|
||||||
|
green = auto()
|
||||||
|
blue = auto()
|
||||||
|
def _generate_next_value_(name, start, count, last):
|
||||||
|
return name
|
||||||
|
|
||||||
|
|
||||||
def test_duplicate_auto(self):
|
def test_duplicate_auto(self):
|
||||||
class Dupes(Enum):
|
class Dupes(Enum):
|
||||||
first = primero = auto()
|
first = primero = auto()
|
||||||
|
|
|
@ -1240,6 +1240,7 @@ Bryan Olson
|
||||||
Grant Olson
|
Grant Olson
|
||||||
Furkan Onder
|
Furkan Onder
|
||||||
Koray Oner
|
Koray Oner
|
||||||
|
Ethan Onstott
|
||||||
Piet van Oostrum
|
Piet van Oostrum
|
||||||
Tomas Oppelstrup
|
Tomas Oppelstrup
|
||||||
Jason Orendorff
|
Jason Orendorff
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Raise TypeError when _generate_next_value_ is defined after members. Patch by Ethan Onstott.
|
Loading…
Add table
Add a link
Reference in a new issue