From ca976c9d4cf29467c949efe3811bb8e1ee1dddd3 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 12 Oct 2024 15:49:22 +0300 Subject: [PATCH 1/2] gh-125316: Fix using partial() as Enum member A FutureWarning with suggestion to use enum.member() is now emitted when the partial instance is used as an enum member. --- Lib/enum.py | 9 ++++++++- Lib/test/test_enum.py | 14 ++++++++++++++ .../2024-10-12-15-49-17.gh-issue-125316.t15RnJ.rst | 3 +++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2024-10-12-15-49-17.gh-issue-125316.t15RnJ.rst diff --git a/Lib/enum.py b/Lib/enum.py index 0c2135f9040bac..78df81d24a9adf 100644 --- a/Lib/enum.py +++ b/Lib/enum.py @@ -1,5 +1,6 @@ import sys import builtins as bltns +from functools import partial from types import MappingProxyType, DynamicClassAttribute @@ -37,7 +38,7 @@ def _is_descriptor(obj): """ Returns True if obj is a descriptor, False otherwise. """ - return ( + return not isinstance(obj, partial) and ( hasattr(obj, '__get__') or hasattr(obj, '__set__') or hasattr(obj, '__delete__') @@ -402,6 +403,12 @@ def __setitem__(self, key, value): elif isinstance(value, nonmember): # unwrap value here; it won't be processed by the below `else` value = value.value + elif isinstance(value, partial): + import warnings + warnings.warn('functools.partial will be a method descriptor ' + 'in future Python versions; wrap it in ' + 'enum.member() if you want to preserve the ' + 'old behavior', FutureWarning, stacklevel=2) elif _is_descriptor(value): pass elif _is_internal_class(self._cls_name, value): diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py index 5b4a8070526fcf..46f57b2d9b641a 100644 --- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -11,6 +11,7 @@ import builtins as bltns from collections import OrderedDict from datetime import date +from functools import partial from enum import Enum, EnumMeta, IntEnum, StrEnum, EnumType, Flag, IntFlag, unique, auto from enum import STRICT, CONFORM, EJECT, KEEP, _simple_enum, _test_simple_enum from enum import verify, UNIQUE, CONTINUOUS, NAMED_FLAGS, ReprEnum @@ -1537,6 +1538,19 @@ class Inner(Enum): [Outer.a, Outer.b, Outer.Inner], ) + def test_partial(self): + def func(a, b=5): + return a, b + with self.assertWarnsRegex(FutureWarning, r'partial.*enum\.member') as cm: + class E(Enum): + a = 1 + b = partial(func) + self.assertEqual(cm.filename, __file__) + self.assertIsInstance(E.b, partial) + self.assertEqual(E.b(2), (2, 5)) + with self.assertWarnsRegex(FutureWarning, 'partial'): + self.assertEqual(E.a.b(2), (2, 5)) + def test_enum_with_value_name(self): class Huh(Enum): name = 1 diff --git a/Misc/NEWS.d/next/Library/2024-10-12-15-49-17.gh-issue-125316.t15RnJ.rst b/Misc/NEWS.d/next/Library/2024-10-12-15-49-17.gh-issue-125316.t15RnJ.rst new file mode 100644 index 00000000000000..5f32238152258a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-10-12-15-49-17.gh-issue-125316.t15RnJ.rst @@ -0,0 +1,3 @@ +Fix using :func:`funclib.partial` as :class:`enum.Enum` member. A +FutureWarning with suggestion to use :func:`enum.member` is now emitted when +the ``partial`` instance is used as an enum member. From 136f7f2c63906f4c041ba00fafa60985218a9f6e Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 12 Oct 2024 16:21:07 +0300 Subject: [PATCH 2/2] Update 2024-10-12-15-49-17.gh-issue-125316.t15RnJ.rst --- .../next/Library/2024-10-12-15-49-17.gh-issue-125316.t15RnJ.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2024-10-12-15-49-17.gh-issue-125316.t15RnJ.rst b/Misc/NEWS.d/next/Library/2024-10-12-15-49-17.gh-issue-125316.t15RnJ.rst index 5f32238152258a..07b642d69995d5 100644 --- a/Misc/NEWS.d/next/Library/2024-10-12-15-49-17.gh-issue-125316.t15RnJ.rst +++ b/Misc/NEWS.d/next/Library/2024-10-12-15-49-17.gh-issue-125316.t15RnJ.rst @@ -1,3 +1,3 @@ -Fix using :func:`funclib.partial` as :class:`enum.Enum` member. A +Fix using :func:`functools.partial` as :class:`enum.Enum` member. A FutureWarning with suggestion to use :func:`enum.member` is now emitted when the ``partial`` instance is used as an enum member.