From cb06785549962f1fcdd852a7eb488d4a8db8b319 2014-01-31 19:54:30
From: Thomas Kluyver <takowl@gmail.com>
Date: 2014-01-31 19:54:30
Subject: [PATCH] Merge pull request #4937 from minrk/object-dtype

pickle arrays with dtype=object
---

diff --git a/IPython/parallel/tests/test_view.py b/IPython/parallel/tests/test_view.py
index bb3625c..e1ff878 100644
--- a/IPython/parallel/tests/test_view.py
+++ b/IPython/parallel/tests/test_view.py
@@ -287,6 +287,21 @@ class TestView(ClusterTestCase):
             assert_array_equal(B,C)
     
     @skip_without('numpy')
+    def test_apply_numpy_object_dtype(self):
+        """view.apply(f, ndarray) with dtype=object"""
+        import numpy
+        from numpy.testing.utils import assert_array_equal
+        view = self.client[-1]
+        
+        A = numpy.array([dict(a=5)])
+        B = view.apply_sync(lambda x:x, A)
+        assert_array_equal(A,B)
+        
+        A = numpy.array([(0, dict(b=10))], dtype=[('i', int), ('o', object)])
+        B = view.apply_sync(lambda x:x, A)
+        assert_array_equal(A,B)
+    
+    @skip_without('numpy')
     def test_push_pull_recarray(self):
         """push/pull recarrays"""
         import numpy
diff --git a/IPython/utils/pickleutil.py b/IPython/utils/pickleutil.py
index 4b85a22..d3fed87 100644
--- a/IPython/utils/pickleutil.py
+++ b/IPython/utils/pickleutil.py
@@ -192,7 +192,15 @@ class CannedArray(CannedObject):
         from numpy import ascontiguousarray
         self.shape = obj.shape
         self.dtype = obj.dtype.descr if obj.dtype.fields else obj.dtype.str
+        self.pickled = False
         if sum(obj.shape) == 0:
+            self.pickled = True
+        elif obj.dtype == 'O':
+            # can't handle object dtype with buffer approach
+            self.pickled = True
+        elif obj.dtype.fields and any(dt == 'O' for dt,sz in obj.dtype.fields.values()):
+            self.pickled = True
+        if self.pickled:
             # just pickle it
             self.buffers = [pickle.dumps(obj, -1)]
         else:
@@ -203,7 +211,7 @@ class CannedArray(CannedObject):
     def get_object(self, g=None):
         from numpy import frombuffer
         data = self.buffers[0]
-        if sum(self.shape) == 0:
+        if self.pickled:
             # no shape, we just pickled it
             return pickle.loads(data)
         else: