Skip to content

Commit d9a43e2

Browse files
authored
bpo-40025: Require _generate_next_value_ to be defined before members (GH-19098)
require `_generate_next_value_` to be defined before members
1 parent a42ca74 commit d9a43e2

File tree

5 files changed

+21
-0
lines changed

5 files changed

+21
-0
lines changed

Doc/library/enum.rst

+4
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,10 @@ overridden::
273273
the next :class:`int` in sequence with the last :class:`int` provided, but
274274
the way it does this is an implementation detail and may change.
275275

276+
.. note::
277+
278+
The :meth:`_generate_next_value_` method must be defined before any members.
279+
276280
Iteration
277281
---------
278282

Lib/enum.py

+5
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ def __init__(self):
6060
self._member_names = []
6161
self._last_values = []
6262
self._ignore = []
63+
self._auto_called = False
6364

6465
def __setitem__(self, key, value):
6566
"""Changes anything not dundered or not a descriptor.
@@ -77,6 +78,9 @@ def __setitem__(self, key, value):
7778
):
7879
raise ValueError('_names_ are reserved for future Enum use')
7980
if key == '_generate_next_value_':
81+
# check if members already defined as auto()
82+
if self._auto_called:
83+
raise TypeError("_generate_next_value_ must be defined before members")
8084
setattr(self, '_generate_next_value', value)
8185
elif key == '_ignore_':
8286
if isinstance(value, str):
@@ -100,6 +104,7 @@ def __setitem__(self, key, value):
100104
# enum overwriting a descriptor?
101105
raise TypeError('%r already defined as: %r' % (key, self[key]))
102106
if isinstance(value, auto):
107+
self._auto_called = True
103108
if value.value == _auto_null:
104109
value.value = self._generate_next_value(key, 1, len(self._member_names), self._last_values[:])
105110
value = value.value

Lib/test/test_enum.py

+10
Original file line numberDiff line numberDiff line change
@@ -1751,6 +1751,16 @@ class Color(Enum):
17511751
self.assertEqual(Color.blue.value, 2)
17521752
self.assertEqual(Color.green.value, 3)
17531753

1754+
def test_auto_order(self):
1755+
with self.assertRaises(TypeError):
1756+
class Color(Enum):
1757+
red = auto()
1758+
green = auto()
1759+
blue = auto()
1760+
def _generate_next_value_(name, start, count, last):
1761+
return name
1762+
1763+
17541764
def test_duplicate_auto(self):
17551765
class Dupes(Enum):
17561766
first = primero = auto()

Misc/ACKS

+1
Original file line numberDiff line numberDiff line change
@@ -1240,6 +1240,7 @@ Bryan Olson
12401240
Grant Olson
12411241
Furkan Onder
12421242
Koray Oner
1243+
Ethan Onstott
12431244
Piet van Oostrum
12441245
Tomas Oppelstrup
12451246
Jason Orendorff
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Raise TypeError when _generate_next_value_ is defined after members. Patch by Ethan Onstott.

0 commit comments

Comments
 (0)