Skip to content

Commit f0d2011

Browse files
Scott Sandersonrgbkrk
authored andcommitted
MAINT: Handle builtin type __new__ attrs.
1 parent 24a6b28 commit f0d2011

File tree

2 files changed

+36
-0
lines changed

2 files changed

+36
-0
lines changed

cloudpickle/cloudpickle.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,32 @@ def _builtin_type(name):
180180
return getattr(types, name)
181181

182182

183+
def _make__new__factory(type_):
184+
def _factory():
185+
return type_.__new__
186+
return _factory
187+
188+
189+
# NOTE: These need to be module globals so that they're pickleable as globals.
190+
_get_dict_new = _make__new__factory(dict)
191+
_get_frozenset_new = _make__new__factory(frozenset)
192+
_get_list_new = _make__new__factory(list)
193+
_get_set_new = _make__new__factory(set)
194+
_get_tuple_new = _make__new__factory(tuple)
195+
_get_object_new = _make__new__factory(object)
196+
197+
# Pre-defined set of builtin_function_or_method instances that can be
198+
# serialized.
199+
_BUILTIN_TYPE_ATTRS = {
200+
dict.__new__: _get_dict_new,
201+
frozenset.__new__: _get_frozenset_new,
202+
set.__new__: _get_set_new,
203+
list.__new__: _get_list_new,
204+
tuple.__new__: _get_tuple_new,
205+
object.__new__: _get_object_new,
206+
}
207+
208+
183209
if sys.version_info < (3, 4):
184210
def _walk_global_ops(code):
185211
"""
@@ -579,6 +605,8 @@ def extract_func_data(self, func):
579605
def save_builtin_function(self, obj):
580606
if obj.__module__ == "__builtin__":
581607
return self.save_global(obj)
608+
elif obj in _BUILTIN_TYPE_ATTRS:
609+
return self.save_reduce(_BUILTIN_TYPE_ATTRS[obj], (), obj=obj)
582610
return self.save_function(obj)
583611
dispatch[types.BuiltinFunctionType] = save_builtin_function
584612

tests/cloudpickle_test.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,5 +715,13 @@ def test_namedtuple(self):
715715
self.assertEqual(depickled_MyTuple.__name__, 'MyTuple')
716716
self.assertTrue(issubclass(depickled_MyTuple, tuple))
717717

718+
def test_builtin_type__new__(self):
719+
# Functions occasionally take the __new__ of these types as default
720+
# parameters for factories. For example, on Python 3.3,
721+
# `tuple.__new__` is a default value for some methods of namedtuple.
722+
for t in list, tuple, set, frozenset, dict, object:
723+
self.assertIs(pickle_depickle(t.__new__), t.__new__)
724+
725+
718726
if __name__ == '__main__':
719727
unittest.main()

0 commit comments

Comments
 (0)