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.