]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-40025: Require _generate_next_value_ to be defined before members (GH-19762)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Thu, 11 Jun 2020 21:48:47 +0000 (14:48 -0700)
committerGitHub <noreply@github.com>
Thu, 11 Jun 2020 21:48:47 +0000 (14:48 -0700)
require `_generate_next_value_` to be defined before members
(cherry picked from commit d9a43e20facdf4ad10186f820601c6580e1baa80)

Doc/library/enum.rst
Lib/enum.py
Lib/test/test_enum.py
Misc/ACKS
Misc/NEWS.d/next/Library/2020-03-21-05-26-38.bpo-40025.DTLtyq.rst [new file with mode: 0644]

index 38221199dcdb745042add81fac5b661ec702d3a5..e340f3ba643e71b7292e5629b0d13792c1eb5fc6 100644 (file)
@@ -273,6 +273,10 @@ overridden::
     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.
 
+.. note::
+
+    The :meth:`_generate_next_value_` method must be defined before any members.
+
 Iteration
 ---------
 
index d0b03b4aa56ce4713356d0f23aa91293aaaf999a..83e6410107ce0baa91873292405522736d3fbfb1 100644 (file)
@@ -66,6 +66,7 @@ class _EnumDict(dict):
         self._member_names = []
         self._last_values = []
         self._ignore = []
+        self._auto_called = False
 
     def __setitem__(self, key, value):
         """Changes anything not dundered or not a descriptor.
@@ -83,6 +84,9 @@ class _EnumDict(dict):
                     ):
                 raise ValueError('_names_ are reserved for future Enum use')
             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)
             elif key == '_ignore_':
                 if isinstance(value, str):
@@ -106,6 +110,7 @@ class _EnumDict(dict):
                 # enum overwriting a descriptor?
                 raise TypeError('%r already defined as: %r' % (key, self[key]))
             if isinstance(value, auto):
+                self._auto_called = True
                 if value.value == _auto_null:
                     value.value = self._generate_next_value(key, 1, len(self._member_names), self._last_values[:])
                 value = value.value
index 29a429ccd998f2c1d9c361826bc8b58d2fbced37..d9260f4cb475f78fefc36a1a803f90c17eeca2d4 100644 (file)
@@ -1710,6 +1710,16 @@ class TestEnum(unittest.TestCase):
         self.assertEqual(Color.blue.value, 2)
         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):
         class Dupes(Enum):
             first = primero = auto()
index ce269edbd51bf1d91aa29b1c3861e73719577a25..a6da4f128982838e58f832154b120edc97ce9c64 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1185,6 +1185,7 @@ Adam Olsen
 Bryan Olson
 Grant Olson
 Koray Oner
+Ethan Onstott
 Piet van Oostrum
 Tomas Oppelstrup
 Jason Orendorff
diff --git a/Misc/NEWS.d/next/Library/2020-03-21-05-26-38.bpo-40025.DTLtyq.rst b/Misc/NEWS.d/next/Library/2020-03-21-05-26-38.bpo-40025.DTLtyq.rst
new file mode 100644 (file)
index 0000000..7b699de
--- /dev/null
@@ -0,0 +1 @@
+Raise TypeError when _generate_next_value_ is defined after members. Patch by Ethan Onstott.
\ No newline at end of file