##// END OF EJS Templates
Merge pull request #8176 from gilbertw/master...
Merge pull request #8176 from gilbertw/master Fixes bug that would show "null" as the reason in the don't leave dialog

File last commit:

r19204:b0fb0657
r20947:99aaca48 merge
Show More
serialize.py
181 lines | 5.9 KiB | text/x-python | PythonLexer
MinRK
add pickleutil.PICKLE_PROTOCOL...
r17044 """serialization utilities for apply messages"""
MinRK
move apply serialization into zmq.serialize
r6788
MinRK
add pickleutil.PICKLE_PROTOCOL...
r17044 # Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
MinRK
move apply serialization into zmq.serialize
r6788
try:
import cPickle
pickle = cPickle
except:
cPickle = None
import pickle
# IPython imports
Min RK
cast buffers to bytes on Python 2 for pickle.loads...
r19204 from IPython.utils.py3compat import PY3, buffer_to_bytes_py2
MinRK
serialize elements of args/kwargs in pack_apply message...
r8133 from IPython.utils.data import flatten
MinRK
better serialization for parallel code...
r7967 from IPython.utils.pickleutil import (
MinRK
use istype instead of isinstance for canning tuples/lists...
r9712 can, uncan, can_sequence, uncan_sequence, CannedObject,
MinRK
add pickleutil.PICKLE_PROTOCOL...
r17044 istype, sequence_types, PICKLE_PROTOCOL,
MinRK
remove unused newserialized imports
r7969 )
MinRK
move apply serialization into zmq.serialize
r6788
Min RK
cast buffers to bytes on Python 2 for pickle.loads...
r19204 if PY3:
MinRK
move apply serialization into zmq.serialize
r6788 buffer = memoryview
#-----------------------------------------------------------------------------
# Serialization Functions
#-----------------------------------------------------------------------------
MinRK
allow configuration of item/buffer thresholds
r8033 # default values for the thresholds:
MinRK
better serialization for parallel code...
r7967 MAX_ITEMS = 64
MinRK
allow configuration of item/buffer thresholds
r8033 MAX_BYTES = 1024
MinRK
better serialization for parallel code...
r7967
MinRK
allow configuration of item/buffer thresholds
r8033 def _extract_buffers(obj, threshold=MAX_BYTES):
MinRK
better serialization for parallel code...
r7967 """extract buffers larger than a certain threshold"""
buffers = []
if isinstance(obj, CannedObject) and obj.buffers:
for i,buf in enumerate(obj.buffers):
if len(buf) > threshold:
# buffer larger than threshold, prevent pickling
obj.buffers[i] = None
buffers.append(buf)
elif isinstance(buf, buffer):
# buffer too small for separate send, coerce to bytes
# because pickling buffer objects just results in broken pointers
obj.buffers[i] = bytes(buf)
return buffers
def _restore_buffers(obj, buffers):
"""restore buffers extracted by """
if isinstance(obj, CannedObject) and obj.buffers:
for i,buf in enumerate(obj.buffers):
if buf is None:
obj.buffers[i] = buffers.pop(0)
MinRK
allow configuration of item/buffer thresholds
r8033 def serialize_object(obj, buffer_threshold=MAX_BYTES, item_threshold=MAX_ITEMS):
MinRK
move apply serialization into zmq.serialize
r6788 """Serialize an object into a list of sendable buffers.
Parameters
----------
obj : object
The object to be serialized
MinRK
allow configuration of item/buffer thresholds
r8033 buffer_threshold : int
MinRK
better serialization for parallel code...
r7967 The threshold (in bytes) for pulling out data buffers
to avoid pickling them.
MinRK
allow configuration of item/buffer thresholds
r8033 item_threshold : int
The maximum number of items over which canning will iterate.
Containers (lists, dicts) larger than this will be pickled without
introspection.
MinRK
move apply serialization into zmq.serialize
r6788
Returns
-------
MinRK
better serialization for parallel code...
r7967 [bufs] : list of buffers representing the serialized object.
MinRK
move apply serialization into zmq.serialize
r6788 """
MinRK
better serialization for parallel code...
r7967 buffers = []
MinRK
use istype instead of isinstance for canning tuples/lists...
r9712 if istype(obj, sequence_types) and len(obj) < item_threshold:
MinRK
better serialization for parallel code...
r7967 cobj = can_sequence(obj)
for c in cobj:
MinRK
allow configuration of item/buffer thresholds
r8033 buffers.extend(_extract_buffers(c, buffer_threshold))
MinRK
use istype instead of isinstance for canning tuples/lists...
r9712 elif istype(obj, dict) and len(obj) < item_threshold:
MinRK
better serialization for parallel code...
r7967 cobj = {}
Thomas Kluyver
Remove uses of iterkeys
r13360 for k in sorted(obj):
MinRK
better serialization for parallel code...
r7967 c = can(obj[k])
MinRK
allow configuration of item/buffer thresholds
r8033 buffers.extend(_extract_buffers(c, buffer_threshold))
MinRK
better serialization for parallel code...
r7967 cobj[k] = c
MinRK
move apply serialization into zmq.serialize
r6788 else:
MinRK
better serialization for parallel code...
r7967 cobj = can(obj)
MinRK
allow configuration of item/buffer thresholds
r8033 buffers.extend(_extract_buffers(cobj, buffer_threshold))
MinRK
better serialization for parallel code...
r7967
MinRK
add pickleutil.PICKLE_PROTOCOL...
r17044 buffers.insert(0, pickle.dumps(cobj, PICKLE_PROTOCOL))
MinRK
better serialization for parallel code...
r7967 return buffers
MinRK
s/unserialize/deserialize
r18330 def deserialize_object(buffers, g=None):
MinRK
better serialization for parallel code...
r7967 """reconstruct an object serialized by serialize_object from data buffers.
Parameters
----------
bufs : list of buffers/bytes
g : globals to be used when uncanning
Returns
-------
(newobj, bufs) : unpacked object, and the list of remaining unused buffers.
"""
bufs = list(buffers)
Min RK
cast buffers to bytes on Python 2 for pickle.loads...
r19204 pobj = buffer_to_bytes_py2(bufs.pop(0))
MinRK
serialize elements of args/kwargs in pack_apply message...
r8133 canned = pickle.loads(pobj)
MinRK
use istype instead of isinstance for canning tuples/lists...
r9712 if istype(canned, sequence_types) and len(canned) < MAX_ITEMS:
MinRK
better serialization for parallel code...
r7967 for c in canned:
_restore_buffers(c, bufs)
newobj = uncan_sequence(canned, g)
Stephan Rave
Use istype() when checking if canned object is a dict...
r12199 elif istype(canned, dict) and len(canned) < MAX_ITEMS:
MinRK
move apply serialization into zmq.serialize
r6788 newobj = {}
Thomas Kluyver
Remove uses of iterkeys
r13360 for k in sorted(canned):
MinRK
better serialization for parallel code...
r7967 c = canned[k]
_restore_buffers(c, bufs)
newobj[k] = uncan(c, g)
MinRK
move apply serialization into zmq.serialize
r6788 else:
MinRK
better serialization for parallel code...
r7967 _restore_buffers(canned, bufs)
newobj = uncan(canned, g)
return newobj, bufs
MinRK
move apply serialization into zmq.serialize
r6788
MinRK
allow configuration of item/buffer thresholds
r8033 def pack_apply_message(f, args, kwargs, buffer_threshold=MAX_BYTES, item_threshold=MAX_ITEMS):
MinRK
move apply serialization into zmq.serialize
r6788 """pack up a function, args, and kwargs to be sent over the wire
MinRK
allow configuration of item/buffer thresholds
r8033
MinRK
serialize elements of args/kwargs in pack_apply message...
r8133 Each element of args/kwargs will be canned for special treatment,
but inspection will not go any deeper than that.
Any object whose data is larger than `threshold` will not have their data copied
(only numpy arrays and bytes/buffers support zero-copy)
Message will be a list of bytes/buffers of the format:
[ cf, pinfo, <arg_bufs>, <kwarg_bufs> ]
With length at least two + len(args) + len(kwargs)
MinRK
better serialization for parallel code...
r7967 """
MinRK
serialize elements of args/kwargs in pack_apply message...
r8133
arg_bufs = flatten(serialize_object(arg, buffer_threshold, item_threshold) for arg in args)
kw_keys = sorted(kwargs.keys())
kwarg_bufs = flatten(serialize_object(kwargs[key], buffer_threshold, item_threshold) for key in kw_keys)
info = dict(nargs=len(args), narg_bufs=len(arg_bufs), kw_keys=kw_keys)
MinRK
add pickleutil.PICKLE_PROTOCOL...
r17044 msg = [pickle.dumps(can(f), PICKLE_PROTOCOL)]
msg.append(pickle.dumps(info, PICKLE_PROTOCOL))
MinRK
serialize elements of args/kwargs in pack_apply message...
r8133 msg.extend(arg_bufs)
msg.extend(kwarg_bufs)
MinRK
move apply serialization into zmq.serialize
r6788 return msg
def unpack_apply_message(bufs, g=None, copy=True):
"""unpack f,args,kwargs from buffers packed by pack_apply_message()
Returns: original f,args,kwargs"""
bufs = list(bufs) # allow us to pop
MinRK
serialize elements of args/kwargs in pack_apply message...
r8133 assert len(bufs) >= 2, "not enough buffers!"
Min RK
cast buffers to bytes on Python 2 for pickle.loads...
r19204 pf = buffer_to_bytes_py2(bufs.pop(0))
f = uncan(pickle.loads(pf), g)
pinfo = buffer_to_bytes_py2(bufs.pop(0))
info = pickle.loads(pinfo)
MinRK
serialize elements of args/kwargs in pack_apply message...
r8133 arg_bufs, kwarg_bufs = bufs[:info['narg_bufs']], bufs[info['narg_bufs']:]
args = []
for i in range(info['nargs']):
MinRK
s/unserialize/deserialize
r18330 arg, arg_bufs = deserialize_object(arg_bufs, g)
MinRK
serialize elements of args/kwargs in pack_apply message...
r8133 args.append(arg)
args = tuple(args)
assert not arg_bufs, "Shouldn't be any arg bufs left over"
kwargs = {}
for key in info['kw_keys']:
MinRK
s/unserialize/deserialize
r18330 kwarg, kwarg_bufs = deserialize_object(kwarg_bufs, g)
MinRK
serialize elements of args/kwargs in pack_apply message...
r8133 kwargs[key] = kwarg
assert not kwarg_bufs, "Shouldn't be any kwarg bufs left over"
MinRK
move apply serialization into zmq.serialize
r6788
return f,args,kwargs