]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-115821: [Enum] better error message for calling super().__new__() (GH-116063)
authorEthan Furman <ethan@stoneleaf.us>
Wed, 28 Feb 2024 23:17:49 +0000 (15:17 -0800)
committerGitHub <noreply@github.com>
Wed, 28 Feb 2024 23:17:49 +0000 (15:17 -0800)
docs now state to not call super().__new__
if super().__new__ is called, a better error message is now used

Doc/library/enum.rst
Lib/enum.py
Lib/test/test_enum.py
Misc/NEWS.d/next/Library/2024-02-28-12-14-31.gh-issue-115821.YO2vKA.rst [new file with mode: 0644]

index 30d80ce8d488ccb366d102bd6a8df00590850f02..6e7de004cd52a1a083ee2b70b71b906106d01b46 100644 (file)
@@ -400,6 +400,9 @@ Data Types
 
       results in the call ``int('1a', 16)`` and a value of ``17`` for the member.
 
+      ..note:: When writing a custom ``__new__``, do not use ``super().__new__`` --
+               call the appropriate ``__new__`` instead.
+
    .. method:: Enum.__repr__(self)
 
       Returns the string used for *repr()* calls.  By default, returns the
index d10b99615981ba2f899717dd91f78e4218456e65..22963cca4466f2df2b6b0a57138026b4fde0ef18 100644 (file)
@@ -547,7 +547,10 @@ class EnumType(type):
         classdict['_inverted_'] = None
         try:
             exc = None
+            classdict['_%s__in_progress' % cls] = True
             enum_class = super().__new__(metacls, cls, bases, classdict, **kwds)
+            classdict['_%s__in_progress' % cls] = False
+            delattr(enum_class, '_%s__in_progress' % cls)
         except Exception as e:
             # since 3.12 the line "Error calling __set_name__ on '_proto_member' instance ..."
             # is tacked on to the error instead of raising a RuntimeError
@@ -1155,6 +1158,8 @@ class Enum(metaclass=EnumType):
         # still not found -- verify that members exist, in-case somebody got here mistakenly
         # (such as via super when trying to override __new__)
         if not cls._member_map_:
+            if getattr(cls, '_%s__in_progress' % cls.__name__, False):
+                raise TypeError('do not use `super().__new__; call the appropriate __new__ directly') from None
             raise TypeError("%r has no members defined" % cls)
         #
         # still not found -- try _missing_ hook
index cf3e042de1a4b4f691082103dea909e7019f9c29..27f8bbaf952afca97dc15cb3d5035096ede24edb 100644 (file)
@@ -447,7 +447,7 @@ class _EnumTests:
     def test_bad_new_super(self):
         with self.assertRaisesRegex(
                 TypeError,
-                'has no members defined',
+                'do not use .super...__new__;',
             ):
             class BadSuper(self.enum_type):
                 def __new__(cls, value):
@@ -3409,6 +3409,17 @@ class TestSpecial(unittest.TestCase):
         self.assertIs(Types(2), Types.NetList)
         self.assertIs(Types('nl'), Types.NetList)
 
+    def test_no_members(self):
+        with self.assertRaisesRegex(
+                TypeError,
+                'has no members',
+            ):
+            Enum(7)
+        with self.assertRaisesRegex(
+                TypeError,
+                'has no members',
+            ):
+            Flag(7)
 
 class TestOrder(unittest.TestCase):
     "test usage of the `_order_` attribute"
diff --git a/Misc/NEWS.d/next/Library/2024-02-28-12-14-31.gh-issue-115821.YO2vKA.rst b/Misc/NEWS.d/next/Library/2024-02-28-12-14-31.gh-issue-115821.YO2vKA.rst
new file mode 100644 (file)
index 0000000..7512a09
--- /dev/null
@@ -0,0 +1,2 @@
+[Enum] Improve error message when calling super().__new__() in custom
+__new__.