From 903788eaddb0d730fb100fb065a346967ee29f9b Mon Sep 17 00:00:00 2001 From: Philipp Moritz Date: Mon, 4 Feb 2019 12:51:17 -0800 Subject: [PATCH 1/2] fix serialization of objects that contain themselves --- cpp/src/arrow/python/serialize.cc | 6 ++-- python/pyarrow/tests/test_serialization.py | 36 ++++++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/cpp/src/arrow/python/serialize.cc b/cpp/src/arrow/python/serialize.cc index 4dd4c04a6ccb..3ccdfc8eee5b 100644 --- a/cpp/src/arrow/python/serialize.cc +++ b/cpp/src/arrow/python/serialize.cc @@ -203,19 +203,19 @@ class SequenceBuilder { Status AppendList(PyObject* context, PyObject* list, int32_t recursion_depth, SerializedPyObject* blobs_out) { return AppendSequence(context, list, PythonType::LIST, lists_, list_values_, - recursion_depth, blobs_out); + recursion_depth + 1, blobs_out); } Status AppendTuple(PyObject* context, PyObject* tuple, int32_t recursion_depth, SerializedPyObject* blobs_out) { return AppendSequence(context, tuple, PythonType::TUPLE, tuples_, tuple_values_, - recursion_depth, blobs_out); + recursion_depth + 1, blobs_out); } Status AppendSet(PyObject* context, PyObject* set, int32_t recursion_depth, SerializedPyObject* blobs_out) { return AppendSequence(context, set, PythonType::SET, sets_, set_values_, - recursion_depth, blobs_out); + recursion_depth + 1, blobs_out); } Status AppendDict(PyObject* context, PyObject* dict, int32_t recursion_depth, diff --git a/python/pyarrow/tests/test_serialization.py b/python/pyarrow/tests/test_serialization.py index 5f76ff62d200..e5c9f475704d 100644 --- a/python/pyarrow/tests/test_serialization.py +++ b/python/pyarrow/tests/test_serialization.py @@ -814,3 +814,39 @@ def test_serialization_determinism(): buf1 = pa.serialize(obj).to_buffer() buf2 = pa.serialize(obj).to_buffer() assert buf1.to_pybytes() == buf2.to_pybytes() + + +def test_serialize_recursive_objects(): + class ClassA(object): + pass + + # Make a list that contains itself. + lst = [] + lst.append(lst) + + # Make an object that contains itself as a field. + a1 = ClassA() + a1.field = a1 + + # Make two objects that contain each other as fields. + a2 = ClassA() + a3 = ClassA() + a2.field = a3 + a3.field = a2 + + # Make a dictionary that contains itself. + d1 = {} + d1["key"] = d1 + + # Make a numpy array that contains itself. + arr = np.array([None], dtype=object) + arr[0] = arr + + # Create a list of recursive objects. + recursive_objects = [lst, a1, a2, a3, d1, arr] + + # Check that exceptions are thrown when we serialize the recursive + # objects. + for obj in recursive_objects: + with pytest.raises(Exception): + pyarrow.serialize(obj).deserialize() From f83cff992a96d0c4e054e6747acd655608acb3d7 Mon Sep 17 00:00:00 2001 From: Philipp Moritz Date: Mon, 4 Feb 2019 13:06:36 -0800 Subject: [PATCH 2/2] fix --- python/pyarrow/tests/test_serialization.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/pyarrow/tests/test_serialization.py b/python/pyarrow/tests/test_serialization.py index e5c9f475704d..c37e8b6a7815 100644 --- a/python/pyarrow/tests/test_serialization.py +++ b/python/pyarrow/tests/test_serialization.py @@ -849,4 +849,4 @@ class ClassA(object): # objects. for obj in recursive_objects: with pytest.raises(Exception): - pyarrow.serialize(obj).deserialize() + pa.serialize(obj).deserialize()