changeset 56:43a413b7c151 pytave-new

improve conversions, handle POobject and char arrays
author Jaroslav Hajek <highegg@gmail.com>
date Mon, 08 Jun 2009 11:55:19 +0200
parents b001edc0f81a
children 732b6b4b2c45
files ChangeLog octave_to_python.cc package/pytave.py python_to_octave.cc test/test.py
diffstat 5 files changed, 192 insertions(+), 144 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Jun 03 16:41:44 2009 +0200
+++ b/ChangeLog	Mon Jun 08 11:55:19 2009 +0200
@@ -1,3 +1,21 @@
+2009-06-08  Jaroslav Hajek  <highegg@gmail.com>, David Grundberg  <individ@acc.umu.se>
+
+	* octave_to_python.cc (copy_octarray_to_pyarrobj<PyObject *,
+	Cell>): New template specialization.
+	(createPyArr): Simplify row vectors to 1D arrays.
+	(octvalue_to_pyarrobj): Add string and cell cases.
+	(octcell_to_pyobject): Create a PyObject array if not row vector.
+	(octmap_to_pyobject): Create a simple dict if scalar struct.
+	(octvalue_to_pyobj): Allow converting arbitrary character matrices.
+	* python_to_octave.cc (pydict_to_octmap): Make scalar structs by
+	default, detect matching dimensions.
+	* package/pytave.py (feval): Update doc string.
+	(getvar, setvar, isvar): Remove.
+	(_VariablesDict): New class.
+	(locals, globals): Default instances.
+	(_local_scope): Rename to _LocalScope
+	* test/test.py: New tests. Update old tests.
+
 2009-06-03  Jaroslav Hajek  <highegg@gmail.com>
 
 	* python_to_octave.cc (copy_pyarrobj_to_octarray<PyObject *,
--- a/octave_to_python.cc	Wed Jun 03 16:41:44 2009 +0200
+++ b/octave_to_python.cc	Mon Jun 08 11:55:19 2009 +0200
@@ -31,6 +31,7 @@
 #include <iostream>
 #include "pytavedefs.h"
 #include "exceptions.h"
+#include "octave_to_python.h"
 
 /* From docs:
  *  Note that the names of the element type constants refer to the C data
@@ -45,9 +46,6 @@
 
 namespace pytave {
 
-   void octvalue_to_pyobj(boost::python::object &py_object,
-                          const octave_value& octvalue);
-
    template <class PythonPrimitive, class OctaveBase>
    static void copy_octarray_to_pyarrobj(
                                   PyArrayObject *pyarr,
@@ -76,15 +74,52 @@
       }
    }
 
+   template <>
+   void copy_octarray_to_pyarrobj<PyObject *, Cell>(
+                                  PyArrayObject *pyarr,
+                                  const Cell &matrix,
+                                  const unsigned int matindex,
+                                  const unsigned int matstride,
+                                  const int dimension,
+                                  const unsigned int offset) {
+      unsigned char *ptr = (unsigned char*) pyarr->data;
+      if (dimension == pyarr->nd - 1) {
+         // Last dimension, base case
+         for (int i = 0; i < pyarr->dimensions[dimension]; i++) {
+            object pyobj;
+            octvalue_to_pyobj (pyobj, matrix.elem(matindex + i*matstride));
+            Py_INCREF (pyobj.ptr());
+            *(PyObject **)&ptr[offset + i*pyarr->strides[dimension]]
+               = pyobj.ptr();
+         }
+      } else {
+         for (int i = 0; i < pyarr->dimensions[dimension]; i++) {
+            copy_octarray_to_pyarrobj<PyObject *, Cell>(
+               pyarr,
+               matrix,
+               matindex + i*matstride,
+               matstride * pyarr->dimensions[dimension],
+               dimension + 1,
+               offset + i*pyarr->strides[dimension]);
+         }
+      }
+   }
+
    static PyArrayObject *createPyArr(const dim_vector &dims,
                                      int pyarrtype) {
-      int dimensions[dims.length()];
+      int len = dims.length();
+      int dimensions[len];
       for (int i = 0; i < dims.length(); i++) {
          dimensions[i] = dims(i);
       }
+      // Simplify row vectors to 1d arrays.
+      if (len == 2 && dimensions[0] == 1) {
+         dimensions[0] = dimensions[1];
+         len = 1;
+      }
 
       return (PyArrayObject *)PyArray_FromDims(
-         dims.length(), dimensions, pyarrtype);
+         len, dimensions, pyarrtype);
    }
 
    template <class PythonPrimitive, class OctaveBase>
@@ -211,6 +246,14 @@
          return create_sint_array<int8NDArray, sizeof(int8_t)>(
             matrix.int8_array_value());
       }
+      if (matrix.is_string()) {
+         return create_array<char, charNDArray>(
+            matrix.char_array_value(), PyArray_CHAR);
+      }
+      if (matrix.is_cell()) {
+         return create_array<PyObject *, Cell>(
+            matrix.cell_value(), PyArray_OBJECT);
+      }
 
       throw value_convert_exception("Octave matrix type not known, "
                                     "conversion not implemented");
@@ -228,19 +271,18 @@
 
    static void octcell_to_pyobject(boost::python::object &py_object,
                                    const Cell& cell) {
-      py_object = boost::python::list();
+      if (is_1xn_or_0x0 (cell.dims ())) {
+         py_object = boost::python::list();
 
-      if(!is_1xn_or_0x0(cell.dims())) {
-         throw value_convert_exception(
-            "Only one-dimensional (row mayor) cell arrays can be converted.");
-      }
+         for(octave_idx_type i = 0 ; i < cell.length(); i++) {
+            boost::python::object py_val;
 
-      for(octave_idx_type i = 0 ; i < cell.length(); i++) {
-         boost::python::object py_val;
+            octvalue_to_pyobj(py_val, cell.elem(i));
 
-         octvalue_to_pyobj(py_val, cell.elem(i));
-
-         ((boost::python::list&)py_object).insert(i, py_val);
+            ((boost::python::list&)py_object).insert(i, py_val);
+         }
+      } else {
+         octvalue_to_pyarr (py_object, octave_value (cell));
       }
    }
 
@@ -248,11 +290,18 @@
                                   const Octave_map& map) {
       py_object = boost::python::dict();
       string_vector keys = map.keys();
+      bool scalar = map.dims().all_ones();
 
       for(octave_idx_type i = 0 ; i < keys.length(); i++) {
          boost::python::object py_val;
 
-         octvalue_to_pyobj(py_val, map.contents(keys[i]));
+         const Cell c = map.contents(keys[i]);
+
+         if (scalar) {
+            octvalue_to_pyobj(py_val, c(0));
+         } else {
+            octcell_to_pyobject(py_val, c);
+         }
 
          py_object[keys[i]] = py_val;
       }
@@ -276,16 +325,17 @@
             throw value_convert_exception(
                "Conversion for this scalar not implemented");
       } else if (octvalue.is_string()) {
-         if (! is_1xn_or_0x0 (octvalue.dims ()))
-            throw value_convert_exception(
-               "Multi-row character matrices can not be converted.");
-         py_object = str(octvalue.string_value());
+         if (is_1xn_or_0x0 (octvalue.dims ())) {
+            py_object = object(octvalue.string_value());
+         } else {
+            octvalue_to_pyarr(py_object, octvalue);
+         }
       } else if (octvalue.is_matrix_type()) {
          octvalue_to_pyarr(py_object, octvalue);
       } else if (octvalue.is_map()) {
          octmap_to_pyobject(py_object, octvalue.map_value());
       } else if (octvalue.is_cell()) {
-         octcell_to_pyobject(py_object, octvalue.cell_value()); 
+         octcell_to_pyobject(py_object, octvalue.cell_value());
       } else
          throw value_convert_exception(
             "Conversion from Octave value not implemented");
--- a/package/pytave.py	Wed Jun 03 16:41:44 2009 +0200
+++ b/package/pytave.py	Mon Jun 08 11:55:19 2009 +0200
@@ -21,7 +21,9 @@
 """Python to Octave bridge"""
 
 import _pytave
+import UserDict
 import sys
+import Numeric
 
 arg0 = sys.argv[0]
 interactive = sys.stdin.isatty() and (arg0 == '' or arg0 == '-')
@@ -54,9 +56,9 @@
 	Objects:
 		int (32-bit)        int32
 		float (64-bit)      double
-		str                 string
+		str                 character array
 		dict                struct
-		list                cell
+		list                cell array
 		
 	Numeric Array:
 		UBYTE, SBYTE,       matrix of correct type
@@ -64,9 +66,17 @@
 		UINT, SINT,         -''-
 		LONG,               -''-
 		DOUBLE              -''-
+		CHAR                character array
+		OBJECT              cell array
 
 	All other objects causes a pytave.ObjectConvertError to be
 	raised. This exception inherits TypeError.
+
+	When dicts are converted, all keys must be strings and
+	constitute valid Octave identifiers. By default, scalar
+	structures are created. However, when all values evaluate
+	to cell arrays with matching dimensions, an Octave struct
+	array is created.
 	
 	Octave to Python
 	================
@@ -74,19 +84,18 @@
 	Scalar values to objects:
 		bool                bool
 		real scalar         float (64-bit)
-		any string*         str
 		struct              dict
-		cell*               list
 
-		* Cell arrays must be one-dimensional (row vector) and
-                  character matrices must only have one row.  Any
-                  other form will raise a ValueConvertError.
-		
 	Matrix values to Numeric arrays:
+	   	double              DOUBLE
+		single              FLOAT
+		logical             DOUBLE
 		int64               LONG
 		int32, uint32       INT, UINT
 		int16, uint16       SHORT, USHORT
 		int8, unint8        SBYTE, UBYTE
+		char                CHAR (if native = False)
+		cell                OBJECT (if native = False)
 
 	All other values causes a pytave.ValueConvertError to be
 	raised. This exception inherits TypeError.
@@ -210,7 +219,7 @@
 	 """
 	 _pytave.pop_scope()
  
-class _local_scope:
+class _LocalScope:
 	 def __init__(self, func):
 		  self.func = func
 		  self.__name__ = func.__name__
@@ -240,7 +249,7 @@
 		  finally:
 			  pytave.pop_scope()
 	 """
-	 return _local_scope(func)
+	 return _LocalScope(func)
 
 # Emacs
 #	Local Variables:
@@ -248,5 +257,6 @@
 #	coding:utf-8
 #	indent-tabs-mode:t
 #	tab-width:8
+#	python-indent:8
 #	End:
-# vim: set textwidth=70 noexpandtab tabstop=3 :
+# vim: set textwidth=70 noexpandtab tabstop=8 :
--- a/python_to_octave.cc	Wed Jun 03 16:41:44 2009 +0200
+++ b/python_to_octave.cc	Mon Jun 08 11:55:19 2009 +0200
@@ -310,11 +310,14 @@
 
       dim_vector dims = dim_vector(1, 1);
 
-      bool has_dimensions = false;
+      bool dims_match = true;
 
       Array<octave_value> vals (length);
       Array<std::string> keys (length);
 
+      // Extract all keys and convert values. Remember whether dimensions
+      // match.
+      
       for(octave_idx_type i = 0; i < length; i++) {
 
          std::string& key = keys(i);
@@ -343,23 +346,15 @@
 
          pyobj_to_octvalue(val, tuple[1]);
 
-         if(val.is_cell()) {
-            const Cell c(val.cell_value());
-            if (error_state)
-               throw object_convert_exception("Octave error");
-
-            // We do not bother measuring 1x1 values, since they are replicated
-            // to fill up the necessary dimensions.
-            if(!(c.dims().length() == 2 && c.dims()(0) == 1 && c.dims()(1) == 1)) {
-
-               if(!has_dimensions) {
-                  dims = c.dims();
-                  has_dimensions = true;
-               } else if(c.dims() != dims) {
-                  throw object_convert_exception(
-                     "Dimensions of the struct fields do not match");
-               }
+         if(dims_match && val.is_cell()) {
+            dim_vector dv = val.dims();
+            if(i == 0) {
+               dims = dv;
+            } else {
+               dims_match = dims == dv;
             }
+         } else {
+            dims_match = false;
          }
       }
 
@@ -370,23 +365,10 @@
          std::string& key = keys(i);
          octave_value val = vals(i);
 
-         if(!val.is_cell()) {
-            map.assign(key, Cell(dims, val));
+         if(dims_match) {
+            map.assign(key, val.cell_value ());
          } else {
-            const Cell c(val.cell_value());
-
-            if (error_state)
-               throw object_convert_exception("Octave error");
-
-            if(c.dims().length() == 2 && c.dims()(0) == 1 && c.dims()(1) == 1) {
-               map.assign(key, Cell(dims, c(0)));
-            }
-            else {
-               map.assign(key, c);
-            }
-         }
-         if (error_state) {
-            throw object_convert_exception("Octave error");
+            map.assign(key, val);
          }
       }
       oct_value = map;
--- a/test/test.py	Wed Jun 03 16:41:44 2009 +0200
+++ b/test/test.py	Mon Jun 08 11:55:19 2009 +0200
@@ -3,6 +3,7 @@
 
 import pytave
 import Numeric
+import traceback
 
 print "No messages indicates test pass."
 
@@ -11,72 +12,76 @@
 arr1_0 = Numeric.zeros((1,0));
 number = Numeric.array([1.32], Numeric.Float32)
 arr1fT = Numeric.array([[1.32], [2], [3], [4]], Numeric.Float32)
-arr1fT2 = Numeric.array([[1.32, 2, 3, 4]], Numeric.Float32)
-arr1f = Numeric.array([[1.32, 2, 3, 4]], Numeric.Float32)
-arr1b = Numeric.array([[8, 2, 3, 256]], Numeric.Int8)
-arr1i = Numeric.array([[17, 2, 3, 4]], Numeric.Int)
-arr1i32 = Numeric.array([[32, 2, 3, 4]], Numeric.Int32)
-arr1a = Numeric.array([[1, 2, 3, 4]])
+arr1fT2 = Numeric.array([1.32, 2, 3, 4], Numeric.Float32)
+arr1f = Numeric.array([1.32, 2, 3, 4], Numeric.Float32)
+arr1b = Numeric.array([8, 2, 3, 256], Numeric.Int8)
+arr1i = Numeric.array([17, 2, 3, 4], Numeric.Int)
+arr1i32 = Numeric.array([32, 2, 3, 4], Numeric.Int32)
+arr1a = Numeric.array([1, 2, 3, 4])
 arr2f = Numeric.array([[1.32, 2, 3, 4],[5,6,7,8]], Numeric.Float32)
 arr2d = Numeric.array([[1.17, 2, 3, 4],[5,6,7,8]], Numeric.Float)
 arr3f = Numeric.array([[[1.32, 2, 3, 4],[5,6,7,8]],[[9, 10, 11, 12],[13,14,15,16]]], Numeric.Float32)
-arr1c = Numeric.array([[1+2j, 3+4j, 5+6j, 7+0.5j]], Numeric.Complex)
-arr1fc = Numeric.array([[1+2j, 3+4j, 5+6j, 7+0.5j]], Numeric.Complex32)
-arr1o = Numeric.array([["abc",1.0,2+3j]],Numeric.PyObject)
-arr2o = Numeric.array([["abc",1.0,2+3j],[4.0,arr1i,"def"]],Numeric.PyObject)
-arr1ch = Numeric.array(["abc"],Numeric.Character)
+arr1c = Numeric.array([1+2j, 3+4j, 5+6j, 7+0.5j], Numeric.Complex)
+arr1fc = Numeric.array([1+2j, 3+4j, 5+6j, 7+0.5j], Numeric.Complex32)
+arr1ch = Numeric.array("abc",Numeric.Character)
 arr2ch = Numeric.array(["abc","def"],Numeric.Character)
+arr1o = Numeric.array([1.0,"abc",2+3j],Numeric.PyObject)
+arr2o = Numeric.array([[1.0,"abc",2+3j],[4.0,arr1i,"def"]],Numeric.PyObject)
 
-alimit_int32 = Numeric.array([[-2147483648, 2147483647]], Numeric.Int32);
-alimit_int16 = Numeric.array([[-32768, 32767, -32769, 32768]], Numeric.Int16);
-alimit_int8 = Numeric.array([[-128, 127, -129, 128]], Numeric.Int8);
-alimit_uint8 = Numeric.array([[0, 255, -1, 256]], Numeric.UnsignedInt8);
+alimit_int32 = Numeric.array([-2147483648, 2147483647], Numeric.Int32);
+alimit_int16 = Numeric.array([-32768, 32767, -32769, 32768], Numeric.Int16);
+alimit_int8 = Numeric.array([-128, 127, -129, 128], Numeric.Int8);
+alimit_uint8 = Numeric.array([0, 255, -1, 256], Numeric.UnsignedInt8);
 
 
 # This eval call is not to be seen as a encouragement to use Pytave
 # like this. Create a separate .m-file with your complex Octave code.
-pytave.feval(0, "eval", "function [result] = test_return(arg) "
-"result = arg; endfunction")
+pytave.eval(0, "function [result] = test_return(arg); result = arg; endfunction")
 
 pytave.feval(1, "test_return", 1)
 
+def fail(msg, exc=None):
+	print "FAIL:", msg
+	traceback.print_stack()
+	if exc is not None:
+		traceback.print_exc(exc)
+	print ""
+
 def testequal(value):
 	try:
 		nvalue, = pytave.feval(1, "test_return", value)
 		if nvalue != value:
-			print "FAIL as ", value, " != ", nvalue
+			fail("as %s != %s" % (value, nvalue))
 	except TypeError, e:
-		print "FAIL: ", value,":", e
+		fail(value, e)
 
 def testexpect(value, expected):
 	try:
 		nvalue, = pytave.feval(1, "test_return", value)
 		if nvalue != expected:
-			print "FAIL as ", nvalue, " != ", expected, ","
-			print "        sent in", value
+			fail("sent in %s, expecting %s, got %s", (value, expected, nvalue))
 	except TypeError, e:
-		print "FAIL: ", value,":", e
-
+		fail(value, e)
 
 def testmatrix(value):
 	try:
 		nvalue, = pytave.feval(1, "test_return", value)
-#		print "test", (value,)
-#		print "returned ", (nvalue,)
 		class1 = pytave.feval(1, "class", value)
 		class2 = pytave.feval(1, "class", nvalue)
 		if nvalue != value:
-			print "FAIL as ", value, " != ", nvalue
+			fail("as %s != %s" % (value, nvalue))
 		if value.shape != nvalue.shape:
-			print "Size check failed for: ", (value,) ,". Got ",value.shape, "and later", nvalue.shape, " =++ ", (nvalue,)
+			fail("Size check failed for: %s. Expected shape %s, got %s  with shape %s" \
+			%(value, value.shape, nvalue, nvalue.shape))
 		if class1 != class2:
-			print "Type check failed for: ", (value,) ,". Got ",class1, "and later", class2
+			fail( "Type check failed for: %s. Expected %s. Got %s."
+			%(value, class1, class2))
 	except TypeError, e:
-		print "Execute failed: ", value,":", e
+		fail("Execute failed: %s" % value, e)
 
 def testobjecterror(value):
 	try:
-		print pytave.feval(1, "test_return", value);
+		pytave.feval(1, "test_return", value);
 		print "FAIL:", (value,)
 	except pytave.ObjectConvertError:
 		pass
@@ -85,16 +90,16 @@
 
 def testvalueerror(*value):
 	try:
-		print pytave.feval(1, *value);
-		print "FAIL:", (value,)
+		pytave.feval(1, *value);
+		fail(value)
 	except pytave.ValueConvertError:
 		pass
 	except Exception, e:
-		print "FAIL", (value,), e
+		fail(value, e)
 
 def testparseerror(*value):
 	try:
-		print pytave.eval(*value);
+		pytave.eval(*value);
 		print "FAIL:", (value,)
 	except pytave.ParseError:
 		pass
@@ -111,11 +116,9 @@
 	try:
 		results = pytave.eval(numargout, code);
 		if results != expectations:
-			print "FAIL: eval: ", code, " because", results, " != ", expectations, ","
+			fail("eval: %s : because %s != %s" % (code, results, expectations))
 	except Exception, e:
-		print "FAIL: eval:", code, ":", e
-def testcellinvariant(value):
-	pass
+		fail("eval: %s" % code, e)
 
 def testsetget(name,value):
     try:
@@ -134,6 +137,9 @@
 	pass
     except Exception, e:
 	print "FAIL: ", name
+			fail("eval: %s : because %s != %s" % (code, results, expectations))
+	except Exception, e:
+		fail("eval: %s" % code, e)
 
 def testlocalscope(x):
 
@@ -145,7 +151,7 @@
 	    fxm1 = sloppy_factorial(xm1)
 	else:
 	    fxm1 = 1
-	pytave.setvar("fxm1",fxm1)
+	pytave.locals["fxm1"] = fxm1
 	fx, = pytave.eval(1,"x * fxm1")
 	return fx
 
@@ -155,12 +161,9 @@
 	for k in range(1,x+1):
 	    fx1 = k * fx1
 	if fx != fx1:
-	    print 'FAIL: testlocalscope: result incorrect'
+	    fail('testlocalscope: result incorrect')
     except Exception, e:
-	print "FAIL: testlocalscope:", (x,), e
-
-
-testequal('a')
+	fail("testlocalscope: %s" % (x,), e)
 
 
 testmatrix(alimit_int32)
@@ -169,11 +172,8 @@
 
 # Strings
 # Multi-row character matrix cannot be returned
-testvalueerror("eval", "['foo'; 'bar']")
-testequal('a')
 
 testequal("mystring")
-testequal('mystring')
 testequal("mystringåäöÅÄÖ")
 
 testequal(1)
@@ -188,12 +188,12 @@
 testmatrix(arr1fT2)
 testmatrix(arr1i)
 testmatrix(arr1b)
-testmatrix(arr1c)
 testmatrix(arr1fc)
 
 # 2d arrays
 testmatrix(arr2f)
 testmatrix(arr2d)
+testmatrix(arr2ch)
 
 # 3d arrays
 testmatrix(arr3f)
@@ -203,7 +203,6 @@
 	print "FAIL: Zero test", 
 
 testmatrix(arr0_0)
-testmatrix(arr1_0)
 testmatrix(arr0_1)
 
 # Lists
@@ -216,38 +215,24 @@
 testvalueok("cell", 1, 3);
 testvalueok("cell", 1, 0)
 testvalueok("cell", 0, 0)
-
-# Return cells with incompatible dimensions
-testvalueerror("cell", 3, 1)
-testvalueerror("cell", 0, 1)
+testvalueok("cell", 3, 1)
+testvalueok("cell", 0, 1)
 
 # Dictionaries
 
 # Simple dictionary tests
-testequal({"foo": [1], "bar": [2]})
+testequal({"foo": 1, "bar": 2})
 testequal({"x": [1, 3], "y": [2, 4]})
 testequal({"x": [1, "baz"], "y": [2, "foobar"]})
 testequal({"x": [arr1f], "y": [arr1i]})
 testequal({})
+testequal({"foo": arr1f,    "bar": arr2f})
+testequal({"foo": 1,        "bar": [2]})
+testexpect({"foo": [[1,2]],        "bar": [[3,2]]},
+	   {"foo": [1,2],        "bar": [3,2]})
 
 # Try some odd dictionaries
 # The implicit conversion makes Pytave return cell-wrapped results.
-testexpect({"foo": number,   "bar": 2},
-	   {"foo": [number], "bar": [2]})
-testexpect({"foo": arr1f,    "bar": arr2f},
-	   {"foo": [arr1f],  "bar": [arr2f]})
-testexpect({"foo": 1,        "bar": 2},
-	   {"foo": [1],      "bar": [2]})
-testexpect({"foo": 1,        "bar": [2]},
-	   {"foo": [1],      "bar": [2]})
-testexpect({"foo": 1,        "bar": [2, 3]},
-	   {"foo": [1, 1],   "bar": [2, 3]})
-testexpect({"foo": [1],      "bar": [2, 4]},
-	   {"foo": [1, 1],   "bar": [2, 4]})
-testexpect({"bar": 1,        "foo": [2, 3]},
-	   {"bar": [1, 1],   "foo": [2, 3]})
-testexpect({"bar": [1],      "foo": [2, 4]},
-	   {"bar": [1, 1],   "foo": [2, 4]})
 
 # Try some invalid keys
 testobjecterror({"this is not an Octave identifier": 1})
@@ -259,8 +244,8 @@
 testobjecterror(())
 
 result, = pytave.feval(1, "eval", "[1, 1, 1]")
-if result.shape != (1, 3):
-	print "FAIL: expected 1x3 matrix"
+if result.shape != (3,):
+	print "FAIL: expected length-3 vector"
 
 result, = pytave.feval(1, "eval", "[1; 2; 3]");
 if result.shape != (3, 1):
@@ -269,13 +254,16 @@
 testparseerror(1, "endfunction")
 testevalexpect(1, "2 + 2", (4,))
 testevalexpect(1, "{2}", ([2],))
-testevalexpect(2, "struct('foo', 2)", ({'foo': [2]},))
-
-testsetget("xxx", [1,2,3])
+testevalexpect(2, "struct('foo', 2)", ({'foo': 2},))
 
 testlocalscope(5)
 
-# Try converting Numeric arrays of objects and characters
-
-testexpect(arr1o,arr1o[0].tolist())
-testexpect(arr1ch,arr1ch.tostring())
+# Emacs
+#	Local Variables:
+#	fill-column:70
+#	coding:utf-8
+#	indent-tabs-mode:t
+#	tab-width:8
+#	python-indent:8
+#	End:
+# vim: set textwidth=70 noexpandtab tabstop=8 :