]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-43162: [Enum] deprecate enum member.member access (GH-24486)
authorEthan Furman <ethan@stoneleaf.us>
Tue, 9 Feb 2021 01:32:38 +0000 (17:32 -0800)
committerGitHub <noreply@github.com>
Tue, 9 Feb 2021 01:32:38 +0000 (17:32 -0800)
In 3.5 (?) a speed optimization made it possible to access members as
attributes of other members, i.e. ``Color.RED.BLUE``.  This was always
discouraged in the docs, and other recent optimizations has made that
one no longer necessary.  Because some may be relying on it anyway, it
is being deprecated in 3.10, and will be removed in 3.11.

Lib/enum.py
Lib/test/test_enum.py
Misc/NEWS.d/next/Library/2021-02-08-16-27-00.bpo-43162.t-W7h3.rst [new file with mode: 0644]

index d4b11521ab27f38d28f2ed73c3fdca7205b7fffa..55299c5788244639125ee80a6fbb38694ec871e1 100644 (file)
@@ -139,12 +139,22 @@ class property(DynamicClassAttribute):
                 return ownerclass._member_map_[self.name]
             except KeyError:
                 raise AttributeError(
-                        '%s: no attribute %r' % (ownerclass.__name__, self.name)
+                        '%s: no class attribute %r' % (ownerclass.__name__, self.name)
                         )
         else:
             if self.fget is None:
+                # check for member
+                if self.name in ownerclass._member_map_:
+                    import warnings
+                    warnings.warn(
+                            "accessing one member from another is not supported, "
+                            " and will be disabled in 3.11",
+                            DeprecationWarning,
+                            stacklevel=2,
+                            )
+                    return ownerclass._member_map_[self.name]
                 raise AttributeError(
-                        '%s: no attribute %r' % (ownerclass.__name__, self.name)
+                        '%s: no instance attribute %r' % (ownerclass.__name__, self.name)
                         )
             else:
                 return self.fget(instance)
@@ -152,7 +162,7 @@ class property(DynamicClassAttribute):
     def __set__(self, instance, value):
         if self.fset is None:
             raise AttributeError(
-                    "%s: cannot set attribute %r" % (self.clsname, self.name)
+                    "%s: cannot set instance attribute %r" % (self.clsname, self.name)
                     )
         else:
             return self.fset(instance, value)
@@ -160,7 +170,7 @@ class property(DynamicClassAttribute):
     def __delete__(self, instance):
         if self.fdel is None:
             raise AttributeError(
-                    "%s: cannot delete attribute %r" % (self.clsname, self.name)
+                    "%s: cannot delete instance attribute %r" % (self.clsname, self.name)
                     )
         else:
             return self.fdel(instance)
index 96de878faf72d4127d971786592754f338f19c1a..3982d1d6430430e8b437897cd4c17f8aeebff6e7 100644 (file)
@@ -2185,6 +2185,29 @@ class TestEnum(unittest.TestCase):
         self.assertEqual(Private._Private__corporal, 'Radar')
         self.assertEqual(Private._Private__major_, 'Hoolihan')
 
+    @unittest.skipUnless(
+            sys.version_info[:2] == (3, 10),
+            'member-member access now raises an exception',
+            )
+    def test_warning_for_member_from_member_access(self):
+        with self.assertWarns(DeprecationWarning):
+            class Di(Enum):
+                YES = 1
+                NO = 0
+            nope = Di.YES.NO
+        self.assertIs(Di.NO, nope)
+
+    @unittest.skipUnless(
+            sys.version_info[:2] > (3, 10),
+            'member-member access currently issues a warning',
+            )
+    def test_exception_for_member_from_member_access(self):
+        with self.assertRaisesRegex(AttributeError, "Di: no instance attribute .NO."):
+            class Di(Enum):
+                YES = 1
+                NO = 0
+            nope = Di.YES.NO
+
     def test_strenum_auto(self):
         class Strings(StrEnum):
             ONE = auto()
diff --git a/Misc/NEWS.d/next/Library/2021-02-08-16-27-00.bpo-43162.t-W7h3.rst b/Misc/NEWS.d/next/Library/2021-02-08-16-27-00.bpo-43162.t-W7h3.rst
new file mode 100644 (file)
index 0000000..fef5915
--- /dev/null
@@ -0,0 +1,2 @@
+deprecate unsupported ability to access enum members as attributes of other
+enum members