Skip to content

Commit

Permalink
bpo-41816: StrEnum.__str__ is str.__str__ (GH-22362)
Browse files Browse the repository at this point in the history
use `str.__str__` for `StrEnum` so that `str(StrEnum.member)` is the same as directly accessing the string value of the `StrEnum` member
  • Loading branch information
ethanfurman authored Sep 22, 2020
1 parent 947adca commit d986d16
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 0 deletions.
15 changes: 15 additions & 0 deletions Doc/library/enum.rst
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,11 @@ an incorrect member::
Before :class:`StrEnum`, ``Directions.NORTH`` would have been the :class:`tuple`
``('north',)``.

.. note::

Unlike other Enum's, ``str(StrEnum.member)`` will return the value of the
member instead of the usual ``"EnumClass.member"``.

.. versionadded:: 3.10


Expand Down Expand Up @@ -1243,3 +1248,13 @@ all named flags and all named combinations of flags that are in the value::
>>> Color(7) # not named combination
<Color.CYAN|MAGENTA|BLUE|YELLOW|GREEN|RED: 7>

``StrEnum`` and :meth:`str.__str__`
"""""""""""""""""""""""""""""""""""

An important difference between :class:`StrEnum` and other Enums is the
:meth:`__str__` method; because :class:`StrEnum` members are strings, some
parts of Python will read the string data directly, while others will call
:meth:`str()`. To make those two operations have the same result,
:meth:`StrEnum.__str__` will be the same as :meth:`str.__str__` so that
``str(StrEnum.member) == StrEnum.member`` is true.

2 changes: 2 additions & 0 deletions Lib/enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,8 @@ def __new__(cls, *values):
member._value_ = value
return member

__str__ = str.__str__


def _reduce_ex_by_name(self, proto):
return self.name
Expand Down
31 changes: 31 additions & 0 deletions Lib/test/test_enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -2036,6 +2036,37 @@ class GoodStrEnum(StrEnum):
two = '2'
three = b'3', 'ascii'
four = b'4', 'latin1', 'strict'
self.assertEqual(GoodStrEnum.one, '1')
self.assertEqual(str(GoodStrEnum.one), '1')
self.assertEqual(GoodStrEnum.one, str(GoodStrEnum.one))
self.assertEqual(GoodStrEnum.one, '{}'.format(GoodStrEnum.one))
#
class DumbMixin:
def __str__(self):
return "don't do this"
class DumbStrEnum(DumbMixin, StrEnum):
five = '5'
six = '6'
seven = '7'
self.assertEqual(DumbStrEnum.seven, '7')
self.assertEqual(str(DumbStrEnum.seven), "don't do this")
#
class EnumMixin(Enum):
def hello(self):
print('hello from %s' % (self, ))
class HelloEnum(EnumMixin, StrEnum):
eight = '8'
self.assertEqual(HelloEnum.eight, '8')
self.assertEqual(HelloEnum.eight, str(HelloEnum.eight))
#
class GoodbyeMixin:
def goodbye(self):
print('%s wishes you a fond farewell')
class GoodbyeEnum(GoodbyeMixin, EnumMixin, StrEnum):
nine = '9'
self.assertEqual(GoodbyeEnum.nine, '9')
self.assertEqual(GoodbyeEnum.nine, str(GoodbyeEnum.nine))
#
with self.assertRaisesRegex(TypeError, '1 is not a string'):
class FirstFailedStrEnum(StrEnum):
one = 1
Expand Down

0 comments on commit d986d16

Please sign in to comment.