From 8a41060c0529d71538b21caccddcaf90dac2f470 Mon Sep 17 00:00:00 2001 From: Scott Sanderson Date: Thu, 28 Dec 2017 00:52:56 -0500 Subject: [PATCH] BUG: Handle instancemethods of builtin types. Fixes a crash in Python 2 when serializing non-hashable instancemethods of built-in types. --- cloudpickle/cloudpickle.py | 8 +++++++- tests/cloudpickle_test.py | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/cloudpickle/cloudpickle.py b/cloudpickle/cloudpickle.py index ad8166121..f3e2b93e0 100644 --- a/cloudpickle/cloudpickle.py +++ b/cloudpickle/cloudpickle.py @@ -339,7 +339,13 @@ def save_function(self, obj, name=None): Determines what kind of function obj is (e.g. lambda, defined at interactive prompt, etc) and handles the pickling appropriately. """ - if obj in _BUILTIN_TYPE_CONSTRUCTORS: + try: + should_special_case = obj in _BUILTIN_TYPE_CONSTRUCTORS + except TypeError: + # Methods of builtin types aren't hashable in python 2. + should_special_case = False + + if should_special_case: # We keep a special-cased cache of built-in type constructors at # global scope, because these functions are structured very # differently in different python versions and implementations (for diff --git a/tests/cloudpickle_test.py b/tests/cloudpickle_test.py index 44bb93709..e7b139266 100644 --- a/tests/cloudpickle_test.py +++ b/tests/cloudpickle_test.py @@ -877,6 +877,12 @@ def test_pickle_reraise(self): with pytest.raises((exc_type, pickle.PicklingError)): cloudpickle.dumps(obj) + def test_unhashable_function(self): + d = {'a': 1} + depickled_method = pickle_depickle(d.get) + self.assertEquals(depickled_method('a'), 1) + self.assertEquals(depickled_method('b'), None) + class Protocol2CloudPickleTest(CloudPickleTest):