From 27829178219cac7e46e04f036b3ab4b4d4eaf94a 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 d21877450..ea845b98b 100644 --- a/cloudpickle/cloudpickle.py +++ b/cloudpickle/cloudpickle.py @@ -331,7 +331,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 0da0a49da..445baa003 100644 --- a/tests/cloudpickle_test.py +++ b/tests/cloudpickle_test.py @@ -835,6 +835,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) + if __name__ == '__main__': unittest.main()