Repository: OpenMined/PySyft
Pull request #1684 (2018-11-15 15:59:59)

Solved: Add serde logic for np.ndarray #1670
 added logic for np.ndarray serialization and deserialization
 added unit test demonstrating proper serde of np.ndarray objects
 added docstrings for all methods describing their functionality including an example of how to serialize/deserialize it.


Patch:
diff --git a/syft/serde.py b/syft/serde.py
index 40297c0a86..f917e38738 100644
--- a/syft/serde.py
+++ b/syft/serde.py
@@ -36,6 +36,7 @@ import torch
 import msgpack
 import lz4
 import io
+import numpy
 
 
 # High Level Public Functions (these are the ones you use)
@@ -303,6 +304,44 @@ def _detail_range(my_range_params: Tuple[int, int, int]) -> range:
     return range(my_range_params[0], my_range_params[1], my_range_params[2])
 
 
+#   numpy array
+
+def _simplify_ndarray(my_array: numpy.ndarray) -> bin:
+    """This function pickles a numpy array
+
+    Args:
+        numpy.ndarray: a numpy array
+
+    Returns:
+        bin: binary representation of the numpy array
+
+    Usage:
+
+        binary = _simplify_ndarray(numpy.random.random([1000, 1000])))
+
+    """
+    return pickle.dumps(my_array)
+
+def _detail_ndarray(binary: bin) -> numpy.ndarray:
+    """This function unpickles a binary to a numpy array
+
+    Args:
+        bin: binary representation of the numpy array
+
+    Returns:
+        numpy.ndarray: a numpy array
+
+    Usage:
+
+        arr = _detail_ndarray(pickle.dumps(numpy.random.random([1000, 1000])))
+        
+    """
+    res = pickle.loads(binary)
+
+    assert type(res) == numpy.ndarray
+
+    return res
+
 # High Level Simplification Router
 
 
@@ -353,6 +392,7 @@ simplifiers[list] = [2, _simplify_collection]
 simplifiers[set] = [3, _simplify_collection]
 simplifiers[dict] = [4, _simplify_dictionary]
 simplifiers[range] = [5, _simplify_range]
+simplifiers[numpy.ndarray] = [6, _simplify_ndarray]
 
 
 def _detail(obj: object) -> object:
@@ -381,4 +421,6 @@ detailers = [
     _detail_collection,
     _detail_collection,
     _detail_dictionary,
+    _detail_range,
+    _detail_ndarray
 ]


Test patch:
diff --git a/test/test_serde.py b/test/test_serde.py
index 53053aa212..6450f9b1fb 100644
--- a/test/test_serde.py
+++ b/test/test_serde.py
@@ -53,6 +53,11 @@ class TestSimplify(TestCase):
         assert type(output) == list
         assert type(output[1]) == bytes
 
+    def test_ndarray_simplify(self):
+        input = numpy.random.random((100, 100))
+        output = _simplify(input)
+        assert type(output[1]) == bytes
+
 
 class TestSerde(TestCase):
     def test_torch_tensor_serde(self):
@@ -76,3 +81,11 @@ class TestSerde(TestCase):
         assert type(tuple_serialized_deserialized) == type(tuple)
         assert (tuple_serialized_deserialized[0] == tensor_one).all()
         assert (tuple_serialized_deserialized[1] == tensor_two).all()
+
+
+    def test_ndarray_serde(self):
+        arr = numpy.random.random((100, 100))
+        arr_serialized = serialize(arr, compress=False)
+
+        arr_serialized_deserialized = deserialize(arr_serialized, compressed=False)
+        assert numpy.array_equal(arr,arr_serialized_deserialized)
\ No newline at end of file