diff options
| author | Ethan Furman <ethan@stoneleaf.us> | 2024-02-04 15:22:55 (GMT) |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-02-04 15:22:55 (GMT) |
| commit | ff7588b729a2a414ea189a2012904da3fbd1401c (patch) | |
| tree | cb5bcbe6dabb0c9458dc28491dd4172b65cf60e0 | |
| parent | ec69e1d0ddc9906e0fb755a5234aeabdc96450ab (diff) | |
| download | cpython-ff7588b729a2a414ea189a2012904da3fbd1401c.zip cpython-ff7588b729a2a414ea189a2012904da3fbd1401c.tar.gz cpython-ff7588b729a2a414ea189a2012904da3fbd1401c.tar.bz2 | |
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.
| -rw-r--r-- | Doc/library/enum.rst | 29 | ||||
| -rw-r--r-- | Lib/enum.py | 10 | ||||
| -rw-r--r-- | Lib/test/test_enum.py | 34 | ||||
| -rw-r--r-- | Misc/NEWS.d/next/Library/2024-02-01-10-19-11.gh-issue-114071.vkm2G_.rst | 1 |
4 files changed, 69 insertions, 5 deletions
diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst index 07b15e2..f31e6ea 100644 --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -337,6 +337,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. @@ -364,6 +375,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 @@ -477,9 +500,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) diff --git a/Lib/enum.py b/Lib/enum.py index a8a50a5..98a8966 100644 --- a/Lib/enum.py +++ b/Lib/enum.py @@ -409,10 +409,11 @@ class EnumDict(dict): 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 @@ -427,7 +428,12 @@ class EnumDict(dict): 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) diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py index d045739..39c1ae0 100644 --- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -2344,6 +2344,40 @@ class TestSpecial(unittest.TestCase): 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 = () diff --git a/Misc/NEWS.d/next/Library/2024-02-01-10-19-11.gh-issue-114071.vkm2G_.rst b/Misc/NEWS.d/next/Library/2024-02-01-10-19-11.gh-issue-114071.vkm2G_.rst new file mode 100644 index 0000000..587ce4d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-02-01-10-19-11.gh-issue-114071.vkm2G_.rst @@ -0,0 +1 @@ +Support tuple subclasses using auto() for enum member value. |
