mirror of
https://github.com/python/cpython.git
synced 2025-07-29 14:15:07 +00:00
[3.12] gh-105332: [Enum] Fix unpickling flags in edge-cases (GH-105348) (GH-105520)
* revert enum pickling from by-name to by-value
(cherry picked from commit 4ff5690e59
)
Co-authored-by: Nikita Sobolev <mail@sobolevn.me>
Co-authored-by: Ethan Furman <ethan@stoneleaf.us>
This commit is contained in:
parent
68eeab7fdd
commit
2f4a2d6c1b
4 changed files with 47 additions and 23 deletions
30
Lib/enum.py
30
Lib/enum.py
|
@ -12,6 +12,7 @@ __all__ = [
|
|||
'FlagBoundary', 'STRICT', 'CONFORM', 'EJECT', 'KEEP',
|
||||
'global_flag_repr', 'global_enum_repr', 'global_str', 'global_enum',
|
||||
'EnumCheck', 'CONTINUOUS', 'NAMED_FLAGS', 'UNIQUE',
|
||||
'pickle_by_global_name', 'pickle_by_enum_name',
|
||||
]
|
||||
|
||||
|
||||
|
@ -922,7 +923,6 @@ class EnumType(type):
|
|||
body['__module__'] = module
|
||||
tmp_cls = type(name, (object, ), body)
|
||||
cls = _simple_enum(etype=cls, boundary=boundary or KEEP)(tmp_cls)
|
||||
cls.__reduce_ex__ = _reduce_ex_by_global_name
|
||||
if as_global:
|
||||
global_enum(cls)
|
||||
else:
|
||||
|
@ -1240,7 +1240,7 @@ class Enum(metaclass=EnumType):
|
|||
return hash(self._name_)
|
||||
|
||||
def __reduce_ex__(self, proto):
|
||||
return getattr, (self.__class__, self._name_)
|
||||
return self.__class__, (self._value_, )
|
||||
|
||||
# enum.property is used to provide access to the `name` and
|
||||
# `value` attributes of enum members while keeping some measure of
|
||||
|
@ -1307,8 +1307,14 @@ class StrEnum(str, ReprEnum):
|
|||
return name.lower()
|
||||
|
||||
|
||||
def _reduce_ex_by_global_name(self, proto):
|
||||
def pickle_by_global_name(self, proto):
|
||||
# should not be used with Flag-type enums
|
||||
return self.name
|
||||
_reduce_ex_by_global_name = pickle_by_global_name
|
||||
|
||||
def pickle_by_enum_name(self, proto):
|
||||
# should not be used with Flag-type enums
|
||||
return getattr, (self.__class__, self._name_)
|
||||
|
||||
class FlagBoundary(StrEnum):
|
||||
"""
|
||||
|
@ -1330,23 +1336,6 @@ class Flag(Enum, boundary=STRICT):
|
|||
Support for flags
|
||||
"""
|
||||
|
||||
def __reduce_ex__(self, proto):
|
||||
cls = self.__class__
|
||||
unknown = self._value_ & ~cls._flag_mask_
|
||||
member_value = self._value_ & cls._flag_mask_
|
||||
if unknown and member_value:
|
||||
return _or_, (cls(member_value), unknown)
|
||||
for val in _iter_bits_lsb(member_value):
|
||||
rest = member_value & ~val
|
||||
if rest:
|
||||
return _or_, (cls(rest), cls._value2member_map_.get(val))
|
||||
else:
|
||||
break
|
||||
if self._name_ is None:
|
||||
return cls, (self._value_,)
|
||||
else:
|
||||
return getattr, (cls, self._name_)
|
||||
|
||||
_numeric_repr_ = repr
|
||||
|
||||
@staticmethod
|
||||
|
@ -2073,7 +2062,6 @@ def _old_convert_(etype, name, module, filter, source=None, *, boundary=None):
|
|||
# unless some values aren't comparable, in which case sort by name
|
||||
members.sort(key=lambda t: t[0])
|
||||
cls = etype(name, members, module=module, boundary=boundary or KEEP)
|
||||
cls.__reduce_ex__ = _reduce_ex_by_global_name
|
||||
return cls
|
||||
|
||||
_stdlib_enums = IntEnum, StrEnum, IntFlag
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue