changeset 303:0d94e42bacf6

Convert Octave cell array to Python list (fixes issue #41) * octave_to_python.cc (pytave::octcell_to_pyobject): New function. (pytave::octvalue_to_pyobj): Call octcell_to_pyobject on cell arrays. (pytave::octvalue_to_pyarrobj): Delete cell array case. * pycall.cc: Add %!tests for construction of Python sequence types from cell array.
author Mike Miller <mtmiller@octave.org>
date Tue, 02 Aug 2016 13:53:12 -0700
parents de98627cf8ae
children a133564f4af7
files octave_to_python.cc pycall.cc
diffstat 2 files changed, 35 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/octave_to_python.cc	Wed Aug 03 21:11:14 2016 -0700
+++ b/octave_to_python.cc	Tue Aug 02 13:53:12 2016 -0700
@@ -181,8 +181,6 @@
       return create_array<bool, boolNDArray> (matrix.bool_array_value (), NPY_BOOL);
     if (matrix.is_string ())
       return create_array<char, charNDArray> (matrix.char_array_value (), NPY_CHAR);
-    if (matrix.is_cell ())
-      return create_array<PyObject *, Cell> (matrix.cell_value (), NPY_OBJECT);
 
     throw value_convert_exception ("Octave matrix type not known, conversion not implemented");
   }
@@ -196,6 +194,26 @@
   }
 
   static void
+  octcell_to_pyobject (boost::python::object& py_object,
+                       const Cell& cell)
+  {
+    if (! (cell.is_empty () || cell.is_vector ()))
+      throw value_convert_exception (
+        "unable to convert multidimensional cell array into Python sequence");
+
+    boost::python::list sequence;
+
+    for (octave_idx_type i = 0; i < cell.numel (); i++)
+      {
+        boost::python::object py_val;
+        octvalue_to_pyobj (py_val, cell(i));
+        sequence.append (py_val);
+      }
+
+    py_object = sequence;
+  }
+
+  static void
   octmap_to_pyobject (boost::python::object& py_object,
                       const octave_map& map)
   {
@@ -273,8 +291,10 @@
       octstring_to_pyobject (py_object, octvalue.string_value ());
     else if (octvalue.is_scalar_type ())
       octscalar_to_pyobject (py_object, octvalue);
+    else if (octvalue.is_cell ())
+      octcell_to_pyobject (py_object, octvalue.cell_value ());
     else if (octvalue.is_numeric_type () || octvalue.is_string ()
-             || octvalue.is_cell () || octvalue.is_bool_type ())
+             || octvalue.is_bool_type ())
       octvalue_to_pyarr (py_object, octvalue);
     else if (octvalue.is_map ())
       octmap_to_pyobject (py_object, octvalue.map_value ());
--- a/pycall.cc	Wed Aug 03 21:11:14 2016 -0700
+++ b/pycall.cc	Tue Aug 02 13:53:12 2016 -0700
@@ -257,6 +257,18 @@
 %!assert (pycall ("typename", "Hello world"), "str")
 %!assert (pycall ("typename", char ([1, 2, 3])), "str")
 
+## Test construction of sequence types from cell arrays
+%!assert (char (pycall ("list")), "[]")
+%!assert (char (pycall ("list", {})), "[]")
+%!assert (char (pycall ("list", {1, 2, 3})), "[1.0, 2.0, 3.0]")
+%!assert (char (pycall ("list", {int8(1), int8(2), int8(3)})), "[1, 2, 3]")
+%!assert (char (pycall ("tuple")), "()")
+%!assert (char (pycall ("tuple", {})), "()")
+%!assert (char (pycall ("tuple", {1, 2, 3})), "(1.0, 2.0, 3.0)")
+%!assert (char (pycall ("tuple", {int8(1), int8(2), int8(3)})), "(1, 2, 3)")
+%!error (pycall ("list", {1, 2, 3; 4, 5, 6}))
+%!error (pycall ("dict", {1, 2, 3}))
+
 ## Test round trip type preservation / conversion
 %!test
 %! pyexec ("def roundtrip(x): return x");