]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-41816: `StrEnum.__str__` is `str.__str__` (GH-22362)
authorEthan Furman <ethan@stoneleaf.us>
Tue, 22 Sep 2020 20:00:07 +0000 (13:00 -0700)
committerGitHub <noreply@github.com>
Tue, 22 Sep 2020 20:00:07 +0000 (13:00 -0700)
use `str.__str__` for `StrEnum` so that `str(StrEnum.member)` is the same as directly accessing the string value of the `StrEnum` member

Doc/library/enum.rst
Lib/enum.py
Lib/test/test_enum.py

index 3e9b1f9db3550f824f8de57ace0c915832b3864f..118002bef19f851dfc5f5295985d29e8bca47680 100644 (file)
@@ -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
 
 
@@ -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.
+
index 589b17fd6977754f499b237fe5ee498aa19bb399..40ff25b9cdad37bc31242bf55e0f84af54547c04 100644 (file)
@@ -718,6 +718,8 @@ class StrEnum(str, Enum):
         member._value_ = value
         return member
 
+    __str__ = str.__str__
+
 
 def _reduce_ex_by_name(self, proto):
     return self.name
index 8e84d929429ebf0bb6ecfe0abe1953f344d84fe3..3431040f98a726d28f737e30c47b10df8075c61b 100644 (file)
@@ -2036,6 +2036,37 @@ class TestEnum(unittest.TestCase):
             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