Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb613132

Browse files
bpo-44342: [Enum] changed pickling from by-value to by-name (GH-26658) (GH-26660)
by-value lookups could fail on complex enums, necessitating a check for__reduce__ and possibly sabotaging the final enum;by-name lookups should never fail, and sabotaging is no longer necessaryfor class-based enum creation.(cherry picked from commit62f1d2b)Co-authored-by: Ethan Furman <ethan@stoneleaf.us>Co-authored-by: Ethan Furman <ethan@stoneleaf.us>
1 parent3e13742 commitb613132

File tree

3 files changed

+9
-25
lines changed

3 files changed

+9
-25
lines changed

‎Lib/enum.py‎

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -456,23 +456,6 @@ def __new__(metacls, cls, bases, classdict, *, boundary=None, _simple=False, **k
456456
classdict['_all_bits_']=2** ((flag_mask).bit_length())-1
457457
classdict['_inverted_']=None
458458
#
459-
# If a custom type is mixed into the Enum, and it does not know how
460-
# to pickle itself, pickle.dumps will succeed but pickle.loads will
461-
# fail. Rather than have the error show up later and possibly far
462-
# from the source, sabotage the pickle protocol for this class so
463-
# that pickle.dumps also fails.
464-
#
465-
# However, if the new class implements its own __reduce_ex__, do not
466-
# sabotage -- it's on them to make sure it works correctly. We use
467-
# __reduce_ex__ instead of any of the others as it is preferred by
468-
# pickle over __reduce__, and it handles all pickle protocols.
469-
if'__reduce_ex__'notinclassdict:
470-
ifmember_typeisnotobject:
471-
methods= ('__getnewargs_ex__','__getnewargs__',
472-
'__reduce_ex__','__reduce__')
473-
ifnotany(minmember_type.__dict__forminmethods):
474-
_make_class_unpicklable(classdict)
475-
#
476459
# create a default docstring if one has not been provided
477460
if'__doc__'notinclassdict:
478461
classdict['__doc__']='An enumeration.'
@@ -792,7 +775,7 @@ def _convert_(cls, name, module, filter, source=None, *, boundary=None):
792775
body['__module__']=module
793776
tmp_cls=type(name, (object, ),body)
794777
cls=_simple_enum(etype=cls,boundary=boundaryorKEEP)(tmp_cls)
795-
cls.__reduce_ex__=_reduce_ex_by_name
778+
cls.__reduce_ex__=_reduce_ex_by_global_name
796779
global_enum(cls)
797780
module_globals[name]=cls
798781
returncls
@@ -1030,7 +1013,7 @@ def __hash__(self):
10301013
returnhash(self._name_)
10311014

10321015
def__reduce_ex__(self,proto):
1033-
returnself.__class__, (self._value_,)
1016+
returngetattr, (self.__class__,self._name_)
10341017

10351018
# enum.property is used to provide access to the `name` and
10361019
# `value` attributes of enum members while keeping some measure of
@@ -1091,7 +1074,7 @@ def _generate_next_value_(name, start, count, last_values):
10911074
returnname.lower()
10921075

10931076

1094-
def_reduce_ex_by_name(self,proto):
1077+
def_reduce_ex_by_global_name(self,proto):
10951078
returnself.name
10961079

10971080
classFlagBoundary(StrEnum):
@@ -1795,6 +1778,6 @@ def _old_convert_(etype, name, module, filter, source=None, *, boundary=None):
17951778
# unless some values aren't comparable, in which case sort by name
17961779
members.sort(key=lambdat:t[0])
17971780
cls=etype(name,members,module=module,boundary=boundaryorKEEP)
1798-
cls.__reduce_ex__=_reduce_ex_by_name
1781+
cls.__reduce_ex__=_reduce_ex_by_global_name
17991782
cls.__repr__=global_enum_repr
18001783
returncls

‎Lib/test/test_enum.py‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -830,7 +830,7 @@ def test_pickle_by_name(self):
830830
classReplaceGlobalInt(IntEnum):
831831
ONE=1
832832
TWO=2
833-
ReplaceGlobalInt.__reduce_ex__=enum._reduce_ex_by_name
833+
ReplaceGlobalInt.__reduce_ex__=enum._reduce_ex_by_global_name
834834
forprotoinrange(HIGHEST_PROTOCOL):
835835
self.assertEqual(ReplaceGlobalInt.TWO.__reduce_ex__(proto),'TWO')
836836

@@ -1527,10 +1527,10 @@ class NEI(NamedInt, Enum):
15271527
NI5=NamedInt('test',5)
15281528
self.assertEqual(NI5,5)
15291529
self.assertEqual(NEI.y.value,2)
1530-
test_pickle_exception(self.assertRaises,TypeError,NEI.x)
1531-
test_pickle_exception(self.assertRaises,PicklingError,NEI)
1530+
test_pickle_dump_load(self.assertIs,NEI.y)
1531+
test_pickle_dump_load(self.assertIs,NEI)
15321532

1533-
deftest_subclasses_without_direct_pickle_support_using_name(self):
1533+
deftest_subclasses_with_direct_pickle_support(self):
15341534
classNamedInt(int):
15351535
__qualname__='NamedInt'
15361536
def__new__(cls,*args):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[Enum] Change pickling from by-value to by-name.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp