8000 [3.12] gh-114071: [Enum] update docs and code for tuples/subclasses (GH-114871) by miss-islington · Pull Request #114993 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

[3.12] gh-114071: [Enum] update docs and code for tuples/subclasses (GH-114871) #114993

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions Doc/library/enum.rst
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,17 @@ Data Types
>>> PowersOfThree.SECOND.value
9

.. method:: Enum.__init__(self, \*args, \**kwds)

By default, does nothing. If multiple values are given in the member
assignment, those values become separate arguments to ``__init__``; e.g.

>>> from enum import Enum
>>> class Weekday(Enum):
... MONDAY = 1, 'Mon'

``Weekday.__init__()`` would be called as ``Weekday.__init__(self, 1, 'Mon')``

.. method:: Enum.__init_subclass__(cls, \**kwds)

A *classmethod* that is used to further configure subsequent subclasses.
Expand Down Expand Up @@ -350,6 +361,18 @@ Data Types
>>> Build('deBUG')
<Build.DEBUG: 'debug'>

.. method:: Enum.__new__(cls, \*args, \**kwds)

By default, doesn't exist. If specified, either in the enum class
definition or in a mixin class (such as ``int``), all values given
in the member assignment will be passed; e.g.

>>> from enum import Enum
>>> class MyIntEnum(Enum):
... SEVENTEEN = '1a', 16

results in the call ``int('1a', 16)`` and a value of ``17`` for the member.

.. method:: Enum.__repr__(self)

Returns the string used for *repr()* calls. By default, returns the
Expand Down Expand Up @@ -463,9 +486,9 @@ Data Types

.. class:: Flag

*Flag* members support the bitwise operators ``&`` (*AND*), ``|`` (*OR*),
``^`` (*XOR*), and ``~`` (*INVERT*); the results of those operators are members
of the enumeration.
``Flag`` is the same as :class:`Enum`, but its members support the bitwise
operators ``&`` (*AND*), ``|`` (*OR*), ``^`` (*XOR*), and ``~`` (*INVERT*);
the results of those operators are members of the enumeration.

.. method:: __contains__(self, value)

Expand Down
10 changes: 8 additions & 2 deletions Lib/enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -457,10 +457,11 @@ def __setitem__(self, key, value):
if isinstance(value, auto):
single = True
value = (value, )
if type(value) is tuple and any(isinstance(v, auto) for v in value):
if isinstance(value, tuple) and any(isinstance(v, auto) for v in value):
# insist on an actual tuple, no subclasses, in keeping with only supporting
# top-level auto() usage (not contained in any other data structure)
auto_valued = []
t = type(value)
for v in value:
if isinstance(v, auto):
non_auto_store = False
Expand All @@ -475,7 +476,12 @@ def __setitem__(self, key, value):
if single:
value = auto_valued[0]
else:
value = tuple(auto_valued)
try:
# accepts iterable as multiple arguments?
value = t(auto_valued)
except TypeError:
# then pass them in singlely
value = t(*auto_valued)
self._member_names[key] = None
if non_auto_store:
self._last_values.append(value)
Expand Down
34 changes: 34 additions & 0 deletions Lib/test/test_enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -2308,6 +2308,40 @@ class SomeTuple(tuple, Enum):
globals()['SomeTuple'] = SomeTuple
test_pickle_dump_load(self.assertIs, SomeTuple.first)

def test_tuple_subclass_with_auto_1(self):
from collections import namedtuple
T = namedtuple('T', 'index desc')
class SomeEnum(T, Enum):
__qualname__ = 'SomeEnum' # needed for pickle protocol 4
first = auto(), 'for the money'
second = auto(), 'for the show'
third = auto(), 'for the music'
self.assertIs(type(SomeEnum.first), SomeEnum)
self.assertEqual(SomeEnum.third.value, (3, 'for the music'))
self.assertIsInstance(SomeEnum.third.value, T)
self.assertEqual(SomeEnum.first.index, 1)
self.assertEqual(SomeEnum.second.desc, 'for the show')
globals()['SomeEnum'] = SomeEnum
globals()['T'] = T
test_pickle_dump_load(self.assertIs, SomeEnum.first)

def test_tuple_subclass_with_auto_2(self):
from collections import namedtuple
T = namedtuple('T', 'index desc')
class SomeEnum(Enum):
__qualname__ = 'SomeEnum' # needed for pickle protocol 4
first = T(auto(), 'for the money')
second = T(auto(), 'for the show')
third = T(auto(), 'for the music')
self.assertIs(type(SomeEnum.first), SomeEnum)
self.assertEqual(SomeEnum.third.value, (3, 'for the music'))
self.assertIsInstance(SomeEnum.third.value, T)
self.assertEqual(SomeEnum.first.value.index, 1)
self.assertEqual(SomeEnum.second.value.desc, 'for the show')
globals()['SomeEnum'] = SomeEnum
globals()['T'] = T
test_pickle_dump_load(self.assertIs, SomeEnum.first)

def test_duplicate_values_give_unique_enum_items(self):
class AutoNumber(Enum):
first = ()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Support tuple subclasses using auto() for enum member value.
0