From cbe7a01f1693617c58cdbab53ff07f4dd5b873a3 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Wed, 6 Jul 2022 14:17:48 -0400 Subject: [PATCH 1/5] gh-93910: Return enum performance to 3.10 level This removes the performance regression in 3.11, at the expense of not fixing the "bug" that allows accessing values from values (e.g. `Color.RED.BLUE`). --- Lib/enum.py | 10 ++++++---- Lib/test/test_enum.py | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Lib/enum.py b/Lib/enum.py index 69216c97fa86bc..3cb44887888f98 100644 --- a/Lib/enum.py +++ b/Lib/enum.py @@ -310,15 +310,17 @@ def __set_name__(self, enum_class, member_name): # previous enum.property found, no further action needed pass else: - redirect = property() - redirect.__set_name__(enum_class, member_name) if descriptor and need_override: + redirect = property() + redirect.__set_name__(enum_class, member_name) # previous enum.property found, but some other inherited attribute # is in the way; copy fget, fset, fdel to this one redirect.fget = descriptor.fget redirect.fset = descriptor.fset redirect.fdel = descriptor.fdel - setattr(enum_class, member_name, redirect) + setattr(enum_class, member_name, redirect) + else: + setattr(enum_class, member_name, enum_member) # now add to _member_map_ (even aliases) enum_class._member_map_[member_name] = enum_member try: @@ -647,7 +649,7 @@ def __new__(metacls, cls, bases, classdict, *, boundary=None, _simple=False, **k 'member order does not match _order_:\n %r\n %r' % (enum_class._member_names_, _order_) ) - # + return enum_class def __bool__(cls): diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py index a26350992cf9d7..25362592dcae62 100644 --- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -2646,6 +2646,7 @@ class Private(Enum): self.assertEqual(Private._Private__corporal, 'Radar') self.assertEqual(Private._Private__major_, 'Hoolihan') + @unittest.skip("Accessing all values retained for performance reasons") def test_exception_for_member_from_member_access(self): with self.assertRaisesRegex(AttributeError, " member has no attribute .NO."): class Di(Enum): From 070e3200387701410fc1cceea545609e1f6e70c5 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Wed, 6 Jul 2022 14:38:27 -0400 Subject: [PATCH 2/5] Update Lib/test/test_enum.py Co-authored-by: Christian Heimes --- Lib/test/test_enum.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py index 25362592dcae62..aec18c79f7249e 100644 --- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -2646,7 +2646,7 @@ class Private(Enum): self.assertEqual(Private._Private__corporal, 'Radar') self.assertEqual(Private._Private__major_, 'Hoolihan') - @unittest.skip("Accessing all values retained for performance reasons") + @unittest.skip("Accessing all values retained for performance reasons, see GH-93910") def test_exception_for_member_from_member_access(self): with self.assertRaisesRegex(AttributeError, " member has no attribute .NO."): class Di(Enum): From 7d4375d4906e3489fc576fded6182397f001a360 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Wed, 6 Jul 2022 14:45:19 -0400 Subject: [PATCH 3/5] Add blurb --- .../next/Library/2022-07-06-14-45-12.gh-issue-93910.iZcp67.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2022-07-06-14-45-12.gh-issue-93910.iZcp67.rst diff --git a/Misc/NEWS.d/next/Library/2022-07-06-14-45-12.gh-issue-93910.iZcp67.rst b/Misc/NEWS.d/next/Library/2022-07-06-14-45-12.gh-issue-93910.iZcp67.rst new file mode 100644 index 00000000000000..2e589118e3efd3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-06-14-45-12.gh-issue-93910.iZcp67.rst @@ -0,0 +1,3 @@ +The ability to access the other values of an enum on an enum (e.g. +``Color.RED.BLUE``) has been restored in order to fix a performance +regression. From 44baac4ccb661981e593419383982ef77bfbc7d2 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Wed, 6 Jul 2022 14:48:29 -0400 Subject: [PATCH 4/5] Simplify if/else block --- Lib/enum.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/Lib/enum.py b/Lib/enum.py index 3cb44887888f98..d39e1b8be5f818 100644 --- a/Lib/enum.py +++ b/Lib/enum.py @@ -309,18 +309,17 @@ def __set_name__(self, enum_class, member_name): if descriptor and not need_override: # previous enum.property found, no further action needed pass + elif descriptor and need_override: + redirect = property() + redirect.__set_name__(enum_class, member_name) + # previous enum.property found, but some other inherited attribute + # is in the way; copy fget, fset, fdel to this one + redirect.fget = descriptor.fget + redirect.fset = descriptor.fset + redirect.fdel = descriptor.fdel + setattr(enum_class, member_name, redirect) else: - if descriptor and need_override: - redirect = property() - redirect.__set_name__(enum_class, member_name) - # previous enum.property found, but some other inherited attribute - # is in the way; copy fget, fset, fdel to this one - redirect.fget = descriptor.fget - redirect.fset = descriptor.fset - redirect.fdel = descriptor.fdel - setattr(enum_class, member_name, redirect) - else: - setattr(enum_class, member_name, enum_member) + setattr(enum_class, member_name, enum_member) # now add to _member_map_ (even aliases) enum_class._member_map_[member_name] = enum_member try: From 5fc34c1cf4ef6e348afc85fbb03b46ba0ffdd1e0 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Wed, 6 Jul 2022 16:16:53 -0400 Subject: [PATCH 5/5] Update Lib/enum.py Co-authored-by: Brett Cannon --- Lib/enum.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/enum.py b/Lib/enum.py index d39e1b8be5f818..652878ce1e1dfa 100644 --- a/Lib/enum.py +++ b/Lib/enum.py @@ -312,8 +312,8 @@ def __set_name__(self, enum_class, member_name): elif descriptor and need_override: redirect = property() redirect.__set_name__(enum_class, member_name) - # previous enum.property found, but some other inherited attribute - # is in the way; copy fget, fset, fdel to this one + # Previous enum.property found, but some other inherited attribute + # is in the way; copy fget, fset, fdel to this one. redirect.fget = descriptor.fget redirect.fset = descriptor.fset redirect.fdel = descriptor.fdel