Skip to content

Commit 6cb4718

Browse files
pierreglaserogrisel
authored andcommitted
Write kw only arguments to pickle (#264)
1 parent 8df6a7b commit 6cb4718

File tree

3 files changed

+33
-0
lines changed

3 files changed

+33
-0
lines changed

Diff for: CHANGES.md

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
0.9.0
2+
=====
3+
4+
- Fix a bug making functions with keyword-only arguments forget the default
5+
values of these arguments after being pickled.
6+
([issue #264](https://github.com/cloudpipe/cloudpickle/pull/264))
7+
18
0.8.1
29
=====
310

Diff for: cloudpickle/cloudpickle.py

+4
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,8 @@ def save_function_tuple(self, func):
591591
state['annotations'] = func.__annotations__
592592
if hasattr(func, '__qualname__'):
593593
state['qualname'] = func.__qualname__
594+
if hasattr(func, '__kwdefaults__'):
595+
state['kwdefaults'] = func.__kwdefaults__
594596
save(state)
595597
write(pickle.TUPLE)
596598
write(pickle.REDUCE) # applies _fill_function on the tuple
@@ -1075,6 +1077,8 @@ def _fill_function(*args):
10751077
func.__module__ = state['module']
10761078
if 'qualname' in state:
10771079
func.__qualname__ = state['qualname']
1080+
if 'kwdefaults' in state:
1081+
func.__kwdefaults__ = state['kwdefaults']
10781082

10791083
cells = func.__closure__
10801084
if cells is not None:

Diff for: tests/cloudpickle_test.py

+22
Original file line numberDiff line numberDiff line change
@@ -1392,6 +1392,28 @@ def g():
13921392
cloned_func = pickle_depickle(func, protocol=self.protocol)
13931393
assert cloned_func() == "hello from a {}!".format(source)
13941394

1395+
@pytest.mark.skipif(sys.version_info[0] < 3,
1396+
reason="keyword only arguments were introduced in "
1397+
"python 3")
1398+
def test_interactively_defined_func_with_keyword_only_argument(self):
1399+
# fixes https://github.com/cloudpipe/cloudpickle/issues/263
1400+
# The source code of this test is bundled in a string and is ran from
1401+
# the __main__ module of a subprocess in order to avoid a SyntaxError
1402+
# in python2 when pytest imports this file, as the keyword-only syntax
1403+
# is python3-only.
1404+
code = """
1405+
from cloudpickle import loads, dumps
1406+
1407+
def f(a, *, b=1):
1408+
return a + b
1409+
1410+
depickled_f = loads(dumps(f, protocol={protocol}))
1411+
1412+
for func in (f, depickled_f):
1413+
assert func(2) == 3
1414+
assert func.__kwdefaults__ == {{'b': 1}}
1415+
""".format(protocol=self.protocol)
1416+
assert_run_python_script(textwrap.dedent(code))
13951417

13961418
class Protocol2CloudPickleTest(CloudPickleTest):
13971419

0 commit comments

Comments
 (0)