Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
ca1b794d
Commit
ca1b794d
authored
Feb 08, 2014
by
Ethan Furman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Close issue20534: all pickle protocols now supported.
parent
01e46ee7
Changes
3
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
233 additions
and
21 deletions
+233
-21
Doc/library/enum.rst
Doc/library/enum.rst
+11
-3
Lib/enum.py
Lib/enum.py
+17
-11
Lib/test/test_enum.py
Lib/test/test_enum.py
+205
-7
No files found.
Doc/library/enum.rst
View file @
ca1b794d
...
...
@@ -369,10 +369,10 @@ The usual restrictions for pickling apply: picklable enums must be defined in
the top level of a module, since unpickling requires them to be importable
from that module.
..
warning
::
..
note
::
In order to support the singleton nature of enumeration members, pickle
protocol version 2 or higher must be used
.
With pickle protocol version 4 it is possible to easily pickle enums
nested in other classes
.
Functional API
...
...
@@ -420,6 +420,14 @@ The solution is to specify the module name explicitly as follows::
>>> Animals = Enum('Animals', 'ant bee cat dog', module=__name__)
The new pickle protocol 4 also, in some circumstances, relies on
:attr:``__qualname__`` being set to the location where pickle will be able
to find the class. For example, if the class was made available in class
SomeData in the global scope::
>>> Animals = Enum('Animals', 'ant bee cat dog', qualname='SomeData.Animals')
Derived Enumerations
--------------------
...
...
Lib/enum.py
View file @
ca1b794d
...
...
@@ -31,9 +31,9 @@ def _is_sunder(name):
def
_make_class_unpicklable
(
cls
):
"""Make the given class un-picklable."""
def
_break_on_call_reduce
(
self
):
def
_break_on_call_reduce
(
self
,
proto
):
raise
TypeError
(
'%r cannot be pickled'
%
self
)
cls
.
__reduce__
=
_break_on_call_reduce
cls
.
__reduce_
ex_
_
=
_break_on_call_reduce
cls
.
__module__
=
'<unknown>'
...
...
@@ -115,12 +115,13 @@ class EnumMeta(type):
# Reverse value->name map for hashable values.
enum_class
.
_value2member_map_
=
{}
# check for a
__getnewargs__
, and if not present sabotage
# check for a
supported pickle protocols
, and if not present sabotage
# pickling, since it won't work anyway
if
(
member_type
is
not
object
and
member_type
.
__dict__
.
get
(
'__getnewargs__'
)
is
None
):
_make_class_unpicklable
(
enum_class
)
if
member_type
is
not
object
:
methods
=
(
'__getnewargs_ex__'
,
'__getnewargs__'
,
'__reduce_ex__'
,
'__reduce__'
)
if
not
any
(
map
(
member_type
.
__dict__
.
get
,
methods
)):
_make_class_unpicklable
(
enum_class
)
# instantiate them, checking for duplicates as we go
# we instantiate first instead of checking for duplicates first in case
...
...
@@ -166,7 +167,7 @@ class EnumMeta(type):
# double check that repr and friends are not the mixin's or various
# things break (such as pickle)
for
name
in
(
'__repr__'
,
'__str__'
,
'__format__'
,
'__getnewargs__'
):
for
name
in
(
'__repr__'
,
'__str__'
,
'__format__'
,
'__getnewargs__'
,
'__reduce_ex__'
):
class_method
=
getattr
(
enum_class
,
name
)
obj_method
=
getattr
(
member_type
,
name
,
None
)
enum_method
=
getattr
(
first_enum
,
name
,
None
)
...
...
@@ -183,7 +184,7 @@ class EnumMeta(type):
enum_class
.
__new__
=
Enum
.
__new__
return
enum_class
def
__call__
(
cls
,
value
,
names
=
None
,
*
,
module
=
None
,
type
=
None
):
def
__call__
(
cls
,
value
,
names
=
None
,
*
,
module
=
None
,
qualname
=
None
,
type
=
None
):
"""Either returns an existing member, or creates a new enum class.
This method is used both when an enum class is given a value to match
...
...
@@ -202,7 +203,7 @@ class EnumMeta(type):
if
names
is
None
:
# simple value lookup
return
cls
.
__new__
(
cls
,
value
)
# otherwise, functional API: we're creating a new Enum type
return
cls
.
_create_
(
value
,
names
,
module
=
module
,
type
=
type
)
return
cls
.
_create_
(
value
,
names
,
module
=
module
,
qualname
=
qualname
,
type
=
type
)
def
__contains__
(
cls
,
member
):
return
isinstance
(
member
,
cls
)
and
member
.
name
in
cls
.
_member_map_
...
...
@@ -273,7 +274,7 @@ class EnumMeta(type):
raise
AttributeError
(
'Cannot reassign members.'
)
super
().
__setattr__
(
name
,
value
)
def
_create_
(
cls
,
class_name
,
names
=
None
,
*
,
module
=
None
,
type
=
None
):
def
_create_
(
cls
,
class_name
,
names
=
None
,
*
,
module
=
None
,
qualname
=
None
,
type
=
None
):
"""Convenience method to create a new Enum class.
`names` can be:
...
...
@@ -315,6 +316,8 @@ class EnumMeta(type):
_make_class_unpicklable
(
enum_class
)
else
:
enum_class
.
__module__
=
module
if
qualname
is
not
None
:
enum_class
.
__qualname__
=
qualname
return
enum_class
...
...
@@ -468,6 +471,9 @@ class Enum(metaclass=EnumMeta):
def
__hash__
(
self
):
return
hash
(
self
.
_name_
)
def
__reduce_ex__
(
self
,
proto
):
return
self
.
__class__
,
self
.
__getnewargs__
()
# DynamicClassAttribute is used to provide access to the `name` and
# `value` properties of enum members while keeping some measure of
# protection from modification, while still allowing for an enumeration
...
...
Lib/test/test_enum.py
View file @
ca1b794d
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment