Permalink
Browse files

Merge pull request #2755 from minrk/canclass

can interactively defined classes

*Only* interactively defined classes are canned.

closes #2754
  • Loading branch information...
2 parents c2bdc77 + 96df8a4 commit e8c3ce594b1592a891a290c3beb04627e7e22c7a @minrk minrk committed Jan 11, 2013
Showing with 78 additions and 1 deletion.
  1. +35 −0 IPython/utils/pickleutil.py
  2. +43 −1 IPython/zmq/tests/test_serialize.py
@@ -38,6 +38,10 @@
if py3compat.PY3:
buffer = memoryview
+ class_type = type
+else:
+ from types import ClassType
+ class_type = (type, ClassType)
#-------------------------------------------------------------------------------
# Classes
@@ -110,6 +114,30 @@ def get_object(self, g=None):
newFunc = FunctionType(self.code, g, self.__name__, defaults)
return newFunc
+class CannedClass(CannedObject):
+
+ def __init__(self, cls):
+ self._check_type(cls)
+ self.name = cls.__name__
+ self.old_style = not isinstance(cls, type)
+ self._canned_dict = {}
+ for k,v in cls.__dict__.items():
+ if k not in ('__weakref__', '__dict__'):
+ self._canned_dict[k] = can(v)
+ if self.old_style:
+ mro = []
+ else:
+ mro = cls.mro()
@ogrisel
ogrisel Jan 12, 2013

Actually I think it might be better to use:

import inspect
mro = inspect.getmro(cls)
@minrk
minrk Jan 13, 2013 IPython member

good call, added.

+
+ self.parents = [ can(c) for c in mro[1:] ]
+ self.buffers = []
+
+ def _check_type(self, obj):
+ assert isinstance(obj, class_type), "Not a class type"
+
+ def get_object(self, g=None):
+ parents = tuple(uncan(p, g) for p in self.parents)
+ return type(self.name, parents, uncan_dict(self._canned_dict, g=g))
class CannedArray(CannedObject):
def __init__(self, obj):
@@ -200,6 +228,12 @@ def can(obj):
return obj
+def can_class(obj):
+ if isinstance(obj, class_type) and obj.__module__ == '__main__':
+ return CannedClass(obj)
+ else:
+ return obj
+
def can_dict(obj):
"""can the *values* of a dict"""
if isinstance(obj, dict):
@@ -266,6 +300,7 @@ def uncan_sequence(obj, g=None):
FunctionType : CannedFunction,
bytes : CannedBytes,
buffer : CannedBuffer,
+ class_type : can_class,
}
uncan_map = {
@@ -18,7 +18,8 @@
# from unittest import TestCaes
from IPython.zmq.serialize import serialize_object, unserialize_object
from IPython.testing import decorators as dec
-from IPython.utils.pickleutil import CannedArray
+from IPython.utils.pickleutil import CannedArray, CannedClass
+from IPython.parallel import interactive
#-------------------------------------------------------------------------------
# Globals and Utilities
@@ -164,5 +165,46 @@ def test_numpy_in_dict():
yield nt.assert_equals(A.shape, B.shape)
yield nt.assert_equals(A.dtype, B.dtype)
yield assert_array_equal(A,B)
+
+@dec.parametric
+def test_class():
+ @interactive
+ class C(object):
+ a=5
+ bufs = serialize_object(dict(C=C))
+ canned = pickle.loads(bufs[0])
+ yield nt.assert_true(canned['C'], CannedClass)
+ d, r = unserialize_object(bufs)
+ C2 = d['C']
+ yield nt.assert_equal(C2.a, C.a)
+
+@dec.parametric
+def test_class_oldstyle():
+ @interactive
+ class C:
+ a=5
+ bufs = serialize_object(dict(C=C))
+ canned = pickle.loads(bufs[0])
+ yield nt.assert_true(canned['C'], CannedClass)
+ d, r = unserialize_object(bufs)
+ C2 = d['C']
+ yield nt.assert_equal(C2.a, C.a)
+@dec.parametric
+def test_class_inheritance():
+ @interactive
+ class C(object):
+ a=5
+
+ @interactive
+ class D(C):
+ b=10
+
+ bufs = serialize_object(dict(D=D))
+ canned = pickle.loads(bufs[0])
+ yield nt.assert_true(canned['D'], CannedClass)
+ d, r = unserialize_object(bufs)
+ D2 = d['D']
+ yield nt.assert_equal(D2.a, D.a)
+ yield nt.assert_equal(D2.b, D.b)

0 comments on commit e8c3ce5

Please sign in to comment.