Skip to content

Commit

Permalink
Make cpdef enums pickleable (GH-5124)
Browse files Browse the repository at this point in the history
(on Python >= 3.4).

Closes #5120
  • Loading branch information
da-woods committed Jan 10, 2023
1 parent f58bfdb commit ac56a66
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 3 deletions.
2 changes: 2 additions & 0 deletions Cython/Compiler/PyrexTypes.py
Expand Up @@ -4277,6 +4277,7 @@ def create_type_wrapper(self, env):
"items": tuple(self.values),
"underlying_type": self.underlying_type.empty_declaration_code(),
"enum_doc": self.doc,
"static_modname": env.qualified_name,
},
outer_module_scope=env.global_scope())

Expand Down Expand Up @@ -4387,6 +4388,7 @@ def create_type_wrapper(self, env):
context={"name": self.name,
"items": tuple(self.values),
"enum_doc": self.doc,
"static_modname": env.qualified_name,
},
outer_module_scope=env.global_scope()))

Expand Down
6 changes: 3 additions & 3 deletions Cython/Utility/CpdefEnums.pyx
Expand Up @@ -54,7 +54,8 @@ if PY_VERSION_HEX >= 0x03040000:
{{for item in items}}
('{{item}}', {{item}}),
{{endfor}}
])
# Try to look up the module name dynamically if possible
], module=__Pyx_globals.get("__module__", '{{static_modname}}'))
{{if enum_doc is not None}}
{{name}}.__doc__ = {{ repr(enum_doc) }}
{{endif}}
Expand All @@ -79,8 +80,7 @@ if PY_VERSION_HEX >= 0x03040000:
{{for item in items}}
('{{item}}', <{{underlying_type}}>({{name}}.{{item}})),
{{endfor}}
])

], module=__Pyx_globals.get("__module__", '{{static_modname}}'))
else:
__Pyx_globals["{{name}}"] = type('{{name}}', (__Pyx_EnumBase,), {})
{{for item in items}}
Expand Down
15 changes: 15 additions & 0 deletions tests/run/cpdef_enums.pyx
Expand Up @@ -131,3 +131,18 @@ def check_docs():
'Home is where...'
"""
pass

def test_pickle():
"""
>>> from pickle import loads, dumps
>>> import sys
Pickling enums won't work without the enum module, so disable the test
>>> if sys.version_info < (3, 4):
... loads = dumps = lambda x: x
>>> loads(dumps(PyxEnum.TWO)) == PyxEnum.TWO
True
>>> loads(dumps(PxdEnum.RANK_2)) == PxdEnum.RANK_2
True
"""
pass
16 changes: 16 additions & 0 deletions tests/run/cpdef_scoped_enums.pyx
Expand Up @@ -40,3 +40,19 @@ def test_enum_doc():
True
"""
pass


def test_pickle():
"""
>>> from pickle import loads, dumps
>>> import sys
Pickling enums won't work without the enum module, so disable the test
>>> if sys.version_info < (3, 4):
... loads = dumps = lambda x: x
>>> loads(dumps(Enum1.Item2)) == Enum1.Item2
True
>>> loads(dumps(Enum2.Item4)) == Enum2.Item4
True
"""
pass

0 comments on commit ac56a66

Please sign in to comment.