diff --git a/cloudpickle/cloudpickle.py b/cloudpickle/cloudpickle.py index e8c278020..1d9861d21 100644 --- a/cloudpickle/cloudpickle.py +++ b/cloudpickle/cloudpickle.py @@ -943,7 +943,17 @@ def __reduce__(cls): return cls.__name__ -def _fill_function(func, globals, defaults, dict, module, closure_values): +def _fill_function(*args): + if len(args) == 5: + # Backwards compat for cloudpickle v0.4.0, after which the `module` + # argument was introduced + updated_args = args[:-1] + (None, args[-1],) + return _fill_function_internal(*updated_args) + else: + return _fill_function_internal(*args) + + +def _fill_function_internal(func, globals, defaults, dict, module, closure_values): """ Fills in the rest of function data into the skeleton function object that were created via _make_skel_func(). """ diff --git a/tests/cloudpickle_test.py b/tests/cloudpickle_test.py index 70424311d..898e11ea4 100644 --- a/tests/cloudpickle_test.py +++ b/tests/cloudpickle_test.py @@ -724,6 +724,33 @@ def test_builtin_type__new__(self): for t in list, tuple, set, frozenset, dict, object: self.assertTrue(pickle_depickle(t.__new__) is t.__new__) + @pytest.mark.skipif(sys.version_info >= (3, 0), + reason="hardcoded pickle bytes for 2.7") + def test_function_pickle_compat_0_4_0(self): + # The result of `cloudpickle.dumps(lambda x: x)` in cloudpickle 0.4.0, + # Python 2.7 + pickled = (b'\x80\x02ccloudpickle.cloudpickle\n_fill_function\nq\x00(c' + b'cloudpickle.cloudpickle\n_make_skel_func\nq\x01ccloudpickle.clou' + b'dpickle\n_builtin_type\nq\x02U\x08CodeTypeq\x03\x85q\x04Rq\x05(K' + b'\x01K\x01K\x01KCU\x04|\x00\x00Sq\x06N\x85q\x07)U\x01xq\x08\x85q' + b'\tU\x07q\nU\x08q\x0bK\x01U\x00q\x0c))tq\rRq\x0eJ' + b'\xff\xff\xff\xff}q\x0f\x87q\x10Rq\x11}q\x12N}q\x13NtR.') + self.assertEquals(42, cloudpickle.loads(pickled)(42)) + + @pytest.mark.skipif(sys.version_info >= (3, 0), + reason="hardcoded pickle bytes for 2.7") + def test_function_pickle_compat_0_4_1(self): + # The result of `cloudpickle.dumps(lambda x: x)` in cloudpickle 0.4.1, + # Python 2.7 + pickled = (b'\x80\x02ccloudpickle.cloudpickle\n_fill_function\nq\x00(c' + b'cloudpickle.cloudpickle\n_make_skel_func\nq\x01ccloudpickle.clou' + b'dpickle\n_builtin_type\nq\x02U\x08CodeTypeq\x03\x85q\x04Rq\x05(K' + b'\x01K\x01K\x01KCU\x04|\x00\x00Sq\x06N\x85q\x07)U\x01xq\x08\x85q' + b'\tU\x07q\nU\x08q\x0bK\x01U\x00q\x0c))tq\rRq\x0eJ' + b'\xff\xff\xff\xff}q\x0f\x87q\x10Rq\x11}q\x12N}q\x13U\x08__main__q' + b'\x14NtR.') + self.assertEquals(42, cloudpickle.loads(pickled)(42)) + if __name__ == '__main__': unittest.main()