Skip to content

Commit d48760b

Browse files
authored
gh-108682: [Enum] raise TypeError if super().__new__ called in custom __new__ (GH-108704)
When overriding the `__new__` method of an enum, the underlying data type should be created directly; i.e. . member = object.__new__(cls) member = int.__new__(cls, value) member = str.__new__(cls, value) Calling `super().__new__()` finds the lookup version of `Enum.__new__`, and will now raise an exception when detected.
1 parent 13a0007 commit d48760b

File tree

4 files changed

+260
-56
lines changed

4 files changed

+260
-56
lines changed

Doc/howto/enum.rst

+22-1
Original file line numberDiff line numberDiff line change
@@ -426,10 +426,17 @@ enumeration, with the exception of special methods (:meth:`__str__`,
426426
:meth:`__add__`, etc.), descriptors (methods are also descriptors), and
427427
variable names listed in :attr:`_ignore_`.
428428

429-
Note: if your enumeration defines :meth:`__new__` and/or :meth:`__init__` then
429+
Note: if your enumeration defines :meth:`__new__` and/or :meth:`__init__`,
430430
any value(s) given to the enum member will be passed into those methods.
431431
See `Planet`_ for an example.
432432

433+
.. note::
434+
435+
The :meth:`__new__` method, if defined, is used during creation of the Enum
436+
members; it is then replaced by Enum's :meth:`__new__` which is used after
437+
class creation for lookup of existing members. See :ref:`new-vs-init` for
438+
more details.
439+
433440

434441
Restricted Enum subclassing
435442
---------------------------
@@ -895,6 +902,8 @@ Some rules:
895902
:meth:`__str__` method has been reset to their data types'
896903
:meth:`__str__` method.
897904

905+
.. _new-vs-init:
906+
898907
When to use :meth:`__new__` vs. :meth:`__init__`
899908
------------------------------------------------
900909

@@ -927,6 +936,11 @@ want one of them to be the value::
927936
>>> print(Coordinate(3))
928937
Coordinate.VY
929938

939+
.. warning::
940+
941+
*Do not* call ``super().__new__()``, as the lookup-only ``__new__`` is the one
942+
that is found; instead, use the data type directly.
943+
930944

931945
Finer Points
932946
^^^^^^^^^^^^
@@ -1353,6 +1367,13 @@ to handle any extra arguments::
13531367
members; it is then replaced by Enum's :meth:`__new__` which is used after
13541368
class creation for lookup of existing members.
13551369

1370+
.. warning::
1371+
1372+
*Do not* call ``super().__new__()``, as the lookup-only ``__new__`` is the one
1373+
that is found; instead, use the data type directly -- e.g.::
1374+
1375+
obj = int.__new__(cls, value)
1376+
13561377

13571378
OrderedEnum
13581379
^^^^^^^^^^^

Lib/enum.py

+7
Original file line numberDiff line numberDiff line change
@@ -856,6 +856,8 @@ def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, s
856856
value = first_enum._generate_next_value_(name, start, count, last_values[:])
857857
last_values.append(value)
858858
names.append((name, value))
859+
if names is None:
860+
names = ()
859861

860862
# Here, names is either an iterable of (name, value) or a mapping.
861863
for item in names:
@@ -1112,6 +1114,11 @@ def __new__(cls, value):
11121114
for member in cls._member_map_.values():
11131115
if member._value_ == value:
11141116
return member
1117+
# still not found -- verify that members exist, in-case somebody got here mistakenly
1118+
# (such as via super when trying to override __new__)
1119+
if not cls._member_map_:
1120+
raise TypeError("%r has no members defined" % cls)
1121+
#
11151122
# still not found -- try _missing_ hook
11161123
try:
11171124
exc = None

0 commit comments

Comments
 (0)