8000 gh-114071: [Enum] update docs and code for tuples/subclasses (GH-114871) · python/cpython@ff7588b · GitHub
[go: up one dir, main page]

Skip to content

Commit ff7588b

Browse files
authored
gh-114071: [Enum] update docs and code for tuples/subclasses (GH-114871)
Update documentation with `__new__` and `__init__` entries. Support use of `auto()` in tuple subclasses on member assignment lines. Previously, auto() was only supported on the member definition line either solo or as part of a tuple: RED = auto() BLUE = auto(), 'azul' However, since Python itself supports using tuple subclasses where tuples are expected, e.g.: from collections import namedtuple T = namedtuple('T', 'first second third') def test(one, two, three): print(one, two, three) test(*T(4, 5, 6)) # 4 5 6 it made sense to also support tuple subclasses in enum definitions.
1 parent ec69e1d commit ff7588b

File tree

4 files changed

+69
-5
lines changed

4 files changed

+69
-5
lines changed

Doc/library/enum.rst

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,17 @@ Data Types
337337
>>> PowersOfThree.SECOND.value
338338
9
339339

340+
.. method:: Enum.__init__(self, \*args, \**kwds)
341+
342+
By default, does nothing. If multiple values are given in the member
343+
assignment, those values become separate arguments to ``__init__``; e.g.
344+
345+
>>> from enum import Enum
346+
>>> class Weekday(Enum):
347+
... MONDAY = 1, 'Mon'
348+
349+
``Weekday.__init__()`` would be called as ``Weekday.__init__(self, 1, 'Mon')``
350+
340351
.. method:: Enum.__init_subclass__(cls, \**kwds)
341352

342353
A *classmethod* that is used to further configure subsequent subclasses.
@@ -364,6 +375,18 @@ Data Types
364375
>>> Build('deBUG')
365376
<Build.DEBUG: 'debug'>
366377

378+
.. method:: Enum.__new__(cls, \*args, \**kwds)
379+
380+
By default, doesn't exist. If specified, either in the enum class
381+
definition or in a mixin class (such as ``int``), all values given
382+
in the member assignment will be passed; e.g.
383+
384+
>>> from enum import Enum
385+
>>> class MyIntEnum(Enum):
386+
... SEVENTEEN = '1a', 16
387+
388+
results in the call ``int('1a', 16)`` and a value of ``17`` for the member.
389+
367390
.. method:: Enum.__repr__(self)
368391

369392
Returns the string used for *repr()* calls. By default, returns the
@@ -477,9 +500,9 @@ Data Types
477500

478501
.. class:: Flag
479502

480-
*Flag* members support the bitwise operators ``&`` (*AND*), ``|`` (*OR*),
481-
``^`` (*XOR*), and ``~`` (*INVERT*); the results of those operators are members
482-
of the enumeration.
503+
``Flag`` is the same as :class:`Enum`, but its members support the bitwise
504+
operators ``&`` (*AND*), ``|`` (*OR*), ``^`` (*XOR*), and ``~`` (*INVERT*);
505+
the results of those operators are members of the enumeration.
483506

484507
.. method:: __contains__(self, value)
485508

Lib/enum.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -409,10 +409,11 @@ def __setitem__(self, key, value):
409409
if isinstance(value, auto):
410410
single = True
411411
value = (value, )
412-
if type(value) is tuple and any(isinstance(v, auto) for v in value):
412+
if isinstance(value, tuple) and any(isinstance(v, auto) for v in value):
413413
# insist on an actual tuple, no subclasses, in keeping with only supporting
414414
# top-level auto() usage (not contained in any other data structure)
415415
auto_valued = []
416+
t = type(value)
416417
for v in value:
417418
if isinstance(v, auto):
418419
non_auto_store = False
@@ -427,7 +428,12 @@ def __setitem__(self, key, value):
427428
if single:
428429
value = auto_valued[0]
429430
else:
430-
value = tuple(auto_valued)
431+
try:
432+
# accepts iterable as multiple arguments?
433+
value = t(auto_valued)
434+
except TypeError:
435+
# then pass them in singlely
436+
value = t(*auto_valued)
431437
self._member_names[key] = None
432438
if non_auto_store:
433439
self._last_values.append(value)

Lib/test/test_enum.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2344,6 +2344,40 @@ class SomeTuple(tuple, Enum):
23442344
globals()['SomeTuple'] = SomeTuple
23452345
test_pickle_dump_load(self.assertIs, SomeTuple.first)
23462346

2347+
def test_tuple_subclass_with_auto_1(self):
2348+
from collections import namedtuple
2349+
T = namedtuple('T', 'index desc')
2350+
class SomeEnum(T, Enum):
2351+
__qualname__ = 'SomeEnum' # needed for pickle protocol 4
2352+
first = auto(), 'for the money'
2353+
second = auto(), 'for the show'
2354+
third = auto(), 'for the music'
2355+
self.assertIs(type(SomeEnum.first), SomeEnum)
2356+
self.assertEqual(SomeEnum.third.value, (3, 'for the music'))
2357+
self.assertIsInstance(SomeEnum.third.value, T)
2358+
self.assertEqual(SomeEnum.first.index, 1)
2359+
self.assertEqual(SomeEnum.second.desc, 'for the show')
2360+
globals()['SomeEnum'] = SomeEnum
2361+
globals()['T'] = T
2362+
test_pickle_dump_load(self.assertIs, SomeEnum.first)
2363+
2364+
def test_tuple_subclass_with_auto_2(self):
2365+
from collections import namedtuple
2366+
T = namedtuple('T', 'index desc')
2367+
class SomeEnum(Enum):
2368+
__qualname__ = 'SomeEnum' # needed for pickle protocol 4
2369+
first = T(auto(), 'for the money')
2370+
second = T(auto(), 'for the show')
2371+
third = T(auto(), 'for the music')
2372+
self.assertIs(type(SomeEnum.first), SomeEnum)
2373+
self.assertEqual(SomeEnum.third.value, (3, 'for the music'))
2374+
self.assertIsInstance(SomeEnum.third.value, T)
2375+
self.assertEqual(SomeEnum.first.value.index, 1)
2376+
self.assertEqual(SomeEnum.second.value.desc, & 83F3 #39;for the show')
2377+
globals()['SomeEnum'] = SomeEnum
2378+
globals()['T'] = T
2379+
test_pickle_dump_load(self.assertIs, SomeEnum.first)
2380+
23472381
def test_duplicate_values_give_unique_enum_items(self):
23482382
class AutoNumber(Enum):
23492383
first = ()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Support tuple subclasses using auto() for enum member value.

0 commit comments

Comments
 (0)
0