# HG changeset patch # User Mike Miller # Date 1459868925 25200 # Node ID 8e3d06f2f5cf3a3289aa014040c09c18c4b085da # Parent a5ec9bbd94ccf56c2b8499cd3a953d8c52903284 Use Octave coding style for C++ sources, PEP8 style for Python sources * exceptions.{cc,h}, octave_to_python.{cc,h}, pytave.cc, python_to_octave.{cc,h}: Use Octave coding style. * pytave.py, test/exceptions.py, test/test.py: Use PEP8 coding style. diff -r a5ec9bbd94cc -r 8e3d06f2f5cf exceptions.cc --- a/exceptions.cc Tue Apr 05 00:16:53 2016 -0700 +++ b/exceptions.cc Tue Apr 05 08:08:45 2016 -0700 @@ -27,12 +27,13 @@ #include #include "exceptions.h" -namespace pytave { +namespace pytave +{ - PyObject *octave_error_exception::excclass = NULL; - PyObject *value_convert_exception::excclass = NULL; - PyObject *object_convert_exception::excclass = NULL; - PyObject *octave_parse_exception::excclass = NULL; - PyObject *variable_name_exception::excclass = NULL; + PyObject *octave_error_exception::excclass = 0; + PyObject *value_convert_exception::excclass = 0; + PyObject *object_convert_exception::excclass = 0; + PyObject *octave_parse_exception::excclass = 0; + PyObject *variable_name_exception::excclass = 0; } diff -r a5ec9bbd94cc -r 8e3d06f2f5cf exceptions.h --- a/exceptions.h Tue Apr 05 00:16:53 2016 -0700 +++ b/exceptions.h Tue Apr 05 08:08:45 2016 -0700 @@ -26,119 +26,136 @@ #include #include -namespace pytave { +namespace pytave +{ + class pytave_exception + { + public: + static void translate_exception (const pytave_exception& py_ex) + { + PyErr_SetString (PyExc_Exception, py_ex.error.c_str ()); + } + + pytave_exception (const std::string& err) { error = err; }; - class pytave_exception { - public: - static void translate_exception(pytave_exception const &py_ex) { - PyErr_SetString(PyExc_Exception, py_ex.error.c_str()); - } + private: + std::string error; + }; - pytave_exception(std::string err) { error = err; }; + class octave_error_exception + { + public: + static bool init () + { + excclass = PyErr_NewException (const_cast ("pytave.OctaveError"), + PyExc_RuntimeError, 0); + return (excclass != 0); + }; - private: - std::string error; - - }; + static void translate_exception (const octave_error_exception& py_ex) + { + PyErr_SetString (excclass, py_ex.error.c_str ()); + } - class octave_error_exception { - public: - static bool init() { - excclass = PyErr_NewException( - const_cast("pytave.OctaveError"), - PyExc_RuntimeError, NULL); - return excclass != NULL; - }; - static void translate_exception(octave_error_exception const &py_ex) { - PyErr_SetString(excclass, py_ex.error.c_str()); - } - static PyObject *excclass; + static PyObject *excclass; + + octave_error_exception (const std::string& err) { error = err; }; - octave_error_exception(std::string err) { error = err; }; - - private: - std::string error; + private: + std::string error; + }; - }; + class octave_parse_exception + { + public: + static bool init () + { + excclass = PyErr_NewException (const_cast ("pytave.ParseError"), + PyExc_RuntimeError, 0); + return (excclass != 0); + }; - class octave_parse_exception { - public: - static bool init() { - excclass = PyErr_NewException( - const_cast("pytave.ParseError"), - PyExc_RuntimeError, NULL); - return excclass != NULL; - }; - static void translate_exception(octave_parse_exception const &py_ex) { - PyErr_SetString(excclass, py_ex.error.c_str()); - } - static PyObject *excclass; + static void translate_exception (const octave_parse_exception& py_ex) + { + PyErr_SetString (excclass, py_ex.error.c_str ()); + } - octave_parse_exception(std::string err) { error = err; }; + static PyObject *excclass; + + octave_parse_exception (const std::string& err) { error = err; }; - private: - std::string error; - }; + private: + std::string error; + }; - class value_convert_exception { - public: - static bool init() { - excclass = PyErr_NewException( - const_cast("pytave.ValueConvertError"), - PyExc_TypeError, NULL); - return excclass != NULL; - }; - static void translate_exception(value_convert_exception const &py_ex) { - PyErr_SetString(excclass, py_ex.error.c_str()); - } - static PyObject *excclass; + class value_convert_exception + { + public: + static bool init () + { + excclass = PyErr_NewException (const_cast ("pytave.ValueConvertError"), + PyExc_TypeError, 0); + return (excclass != 0); + }; + + static void translate_exception (const value_convert_exception& py_ex) + { + PyErr_SetString (excclass, py_ex.error.c_str ()); + } - value_convert_exception(std::string err) { error = err; }; + static PyObject *excclass; + + value_convert_exception (const std::string& err) { error = err; }; + + private: + std::string error; + }; - private: - std::string error; - }; + class object_convert_exception + { + public: + static bool init () + { + excclass = PyErr_NewException (const_cast ("pytave.ObjectConvertError"), + PyExc_TypeError, 0); + return (excclass != 0); + }; - class object_convert_exception { - public: - static bool init() { - excclass = PyErr_NewException( - const_cast("pytave.ObjectConvertError"), - PyExc_TypeError, NULL); - return excclass != NULL; - }; - static void translate_exception( - object_convert_exception const &py_ex) { - PyErr_SetString(excclass, py_ex.error.c_str()); - } - static PyObject *excclass; + static void translate_exception (const object_convert_exception& py_ex) + { + PyErr_SetString (excclass, py_ex.error.c_str ()); + } - object_convert_exception(std::string err) { error = err; }; + static PyObject *excclass; + + object_convert_exception (const std::string& err) { error = err; }; - private: - std::string error; - }; + private: + std::string error; + }; - class variable_name_exception { - public: - static bool init() { - excclass = PyErr_NewException( - const_cast("pytave.VarNameError"), - PyExc_RuntimeError, NULL); - return excclass != NULL; - }; - static void translate_exception(variable_name_exception const &py_ex) { - PyErr_SetString(excclass, py_ex.error.c_str()); - } - static PyObject *excclass; + class variable_name_exception + { + public: + static bool init () + { + excclass = PyErr_NewException (const_cast ("pytave.VarNameError"), + PyExc_RuntimeError, 0); + return (excclass != 0); + }; - variable_name_exception(std::string err) { error = err; }; + static void translate_exception (const variable_name_exception& py_ex) + { + PyErr_SetString (excclass, py_ex.error.c_str ()); + } - private: - std::string error; + static PyObject *excclass; + + variable_name_exception (const std::string& err) { error = err; }; - }; - + private: + std::string error; + }; } #endif diff -r a5ec9bbd94cc -r 8e3d06f2f5cf octave_to_python.cc --- a/octave_to_python.cc Tue Apr 05 00:16:53 2016 -0700 +++ b/octave_to_python.cc Tue Apr 05 08:08:45 2016 -0700 @@ -38,220 +38,212 @@ using namespace boost::python; -namespace pytave { +namespace pytave +{ - template - static void copy_octarray_to_pyarrobj( - PyArrayObject *pyarr, - const OctaveBase &matrix, - const unsigned int matindex, - const unsigned int matstride, - const int dimension, - const unsigned int offset) { - unsigned char *ptr = (unsigned char*) PyArray_DATA (pyarr); - if (dimension == PyArray_NDIM (pyarr) - 1) { - // Last dimension, base case - for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) { + template + static void + copy_octarray_to_pyarrobj (PyArrayObject *pyarr, const OctaveBase& matrix, + const unsigned int matindex, + const unsigned int matstride, + const int dimension, const unsigned int offset) + { + unsigned char *ptr = (unsigned char*) PyArray_DATA (pyarr); + if (dimension == PyArray_NDIM (pyarr) - 1) + { + // Last dimension, base case + for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) + { *(PythonPrimitive *)&ptr[offset + i*PyArray_STRIDE (pyarr, dimension)] - = matrix.elem(matindex + i*matstride); - } - } else { - for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) { - copy_octarray_to_pyarrobj( - pyarr, - matrix, - matindex + i*matstride, - matstride * PyArray_DIM (pyarr, dimension), - dimension + 1, - offset + i*PyArray_STRIDE (pyarr, dimension)); - } + = matrix.elem (matindex + i*matstride); + } } - } + else + { + for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) + { + copy_octarray_to_pyarrobj ( + pyarr, + matrix, + matindex + i*matstride, + matstride * PyArray_DIM (pyarr, dimension), + dimension + 1, + offset + i*PyArray_STRIDE (pyarr, dimension)); + } + } + } - template <> - void copy_octarray_to_pyarrobj( - 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*) PyArray_DATA (pyarr); - if (dimension == PyArray_NDIM (pyarr) - 1) { - // Last dimension, base case - for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) { + template <> + void + copy_octarray_to_pyarrobj (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*) PyArray_DATA (pyarr); + if (dimension == PyArray_NDIM (pyarr) - 1) + { + // Last dimension, base case + for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) + { object pyobj; - octvalue_to_pyobj (pyobj, matrix.elem(matindex + i*matstride)); - Py_INCREF (pyobj.ptr()); + octvalue_to_pyobj (pyobj, matrix.elem (matindex + i*matstride)); + Py_INCREF (pyobj.ptr ()); *(PyObject **)&ptr[offset + i*PyArray_STRIDE (pyarr, dimension)] - = pyobj.ptr(); - } - } else { - for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) { - copy_octarray_to_pyarrobj( - pyarr, - matrix, - matindex + i*matstride, - matstride * PyArray_DIM (pyarr, dimension), - dimension + 1, - offset + i*PyArray_STRIDE (pyarr, dimension)); - } + = pyobj.ptr (); + } + } + else + { + for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) + { + copy_octarray_to_pyarrobj ( + pyarr, + matrix, + matindex + i*matstride, + matstride * PyArray_DIM (pyarr, dimension), + dimension + 1, + offset + i*PyArray_STRIDE (pyarr, dimension)); + } } - } + } + + static PyArrayObject * + createPyArr (const dim_vector& dims, int pyarrtype) + { + int len = dims.length (); + npy_intp dimensions[len]; + for (int i = 0; i < dims.length (); i++) + dimensions[i] = dims(i); + + return (PyArrayObject *)PyArray_SimpleNew (len, dimensions, pyarrtype); + } - static PyArrayObject *createPyArr(const dim_vector &dims, - int pyarrtype) { - int len = dims.length(); - npy_intp dimensions[len]; - for (int i = 0; i < dims.length(); i++) { - dimensions[i] = dims(i); + template + static PyArrayObject * + create_array (const OctaveBase& octarr, int pyarraytype) + { + PyArrayObject *pyarr = createPyArr (octarr.dims (), pyarraytype); + try + { + copy_octarray_to_pyarrobj (pyarr, octarr, 0, 1, 0, 0); + } + catch (const value_convert_exception&) + { + Py_DECREF (pyarr); + throw; } + return pyarr; + } + + static PyArrayObject * + octvalue_to_pyarrobj (const octave_value& matrix) + { + if (matrix.is_double_type ()) + if (matrix.is_complex_type ()) + return create_array (matrix.complex_array_value (), NPY_CDOUBLE); + else if (matrix.is_real_type ()) + return create_array (matrix.array_value (), NPY_DOUBLE); + else + throw value_convert_exception ("Unknown double matrix type"); + + if (matrix.is_single_type ()) + if (matrix.is_complex_type ()) + return create_array (matrix.float_complex_array_value (), NPY_CFLOAT); + else if (matrix.is_real_type ()) + return create_array (matrix.float_array_value (), NPY_FLOAT); + else + throw value_convert_exception ("Unknown float matrix type"); + + if (matrix.is_int8_type ()) + return create_array (matrix.int8_array_value (), NPY_INT8); + if (matrix.is_int16_type ()) + return create_array (matrix.int16_array_value (), NPY_INT16); + if (matrix.is_int32_type ()) + return create_array (matrix.int32_array_value (), NPY_INT32); + if (matrix.is_int64_type ()) + return create_array (matrix.int64_array_value (), NPY_INT64); - return (PyArrayObject *)PyArray_SimpleNew( - len, dimensions, pyarrtype); - } + if (matrix.is_uint8_type ()) + return create_array (matrix.uint8_array_value (), NPY_UINT8); + if (matrix.is_uint16_type ()) + return create_array (matrix.uint16_array_value (), NPY_UINT16); + if (matrix.is_uint32_type ()) + return create_array (matrix.uint32_array_value (), NPY_UINT32); + if (matrix.is_uint64_type ()) + return create_array (matrix.uint64_array_value (), NPY_UINT64); + + if (matrix.is_bool_type ()) + return create_array (matrix.bool_array_value (), NPY_BOOL); + if (matrix.is_string ()) + return create_array (matrix.char_array_value (), NPY_CHAR); + if (matrix.is_cell ()) + return create_array (matrix.cell_value (), NPY_OBJECT); + + throw value_convert_exception ("Octave matrix type not known, conversion not implemented"); + } + + static void + octvalue_to_pyarr (boost::python::object& py_object, + const octave_value& octvalue) + { + PyArrayObject *pyarr = octvalue_to_pyarrobj (octvalue); + py_object = object (handle ((PyObject *)pyarr)); + } + + static void + octmap_to_pyobject (boost::python::object& py_object, + const octave_map& map) + { + py_object = boost::python::dict (); + string_vector keys = map.keys (); - template - static PyArrayObject *create_array(const OctaveBase &octarr, - int pyarraytype) { - PyArrayObject *pyarr = createPyArr(octarr.dims(), pyarraytype); - try { - copy_octarray_to_pyarrobj - (pyarr, octarr, 0, 1, 0, 0); - } catch (value_convert_exception &pe) { - Py_DECREF(pyarr); - throw; + for (octave_idx_type i = 0 ; i < keys.numel (); i++) + { + boost::python::object py_val; + const Cell c = map.contents (keys[i]); + octvalue_to_pyarr (py_val, c); + py_object[keys[i]] = py_val; } - return pyarr; - } + } + + void octvalue_to_pyobj (boost::python::object& py_object, + const octave_value& octvalue) + { + if (octvalue.is_undefined ()) + throw value_convert_exception ( + "Octave value `undefined'. Can not convert to a Python object"); + else if (octvalue.is_numeric_type () || octvalue.is_string () + || octvalue.is_cell ()) + octvalue_to_pyarr (py_object, octvalue); + else if (octvalue.is_map ()) + octmap_to_pyobject (py_object, octvalue.map_value ()); + else + throw value_convert_exception ( + "Conversion from Octave value not implemented"); + } - static PyArrayObject *octvalue_to_pyarrobj(const octave_value &matrix) { - if (matrix.is_double_type ()) { - if (matrix.is_complex_type ()) { - return create_array - (matrix.complex_array_value(), NPY_CDOUBLE); - } else if (matrix.is_real_type()) { - return create_array(matrix.array_value(), - NPY_DOUBLE); - } else - throw value_convert_exception("Unknown double matrix type"); + void octlist_to_pytuple (boost::python::tuple& python_tuple, + const octave_value_list& octave_list) + { + boost::python::list seq; + int length = octave_list.length (); + + // FIXME: due to bugs in Octave 3.2.3 and earlier, lists returned from + // eval_string and feval may be padded by trailing undefined values. + // Fix is already upstream, so this may be eventually removed. + while (length > 0 && octave_list(length-1).is_undefined ()) + length--; + + for (int i = 0; i < length; i++) + { + boost::python::object py_object; + octvalue_to_pyobj (py_object, octave_list(i)); + seq.append (py_object); } - if (matrix.is_single_type ()) { - if (matrix.is_complex_type ()) { - return create_array - (matrix.float_complex_array_value(), NPY_CFLOAT); - } else if (matrix.is_real_type()) { - return create_array( - matrix.float_array_value(), NPY_FLOAT); - } else - throw value_convert_exception("Unknown float matrix type"); - } - - if (matrix.is_int8_type()) { - return create_array( - matrix.int8_array_value(), NPY_INT8); - } - if (matrix.is_int16_type()) { - return create_array( - matrix.int16_array_value(), NPY_INT16); - } - if (matrix.is_int32_type()) { - return create_array( - matrix.int32_array_value(), NPY_INT32); - } - if (matrix.is_int64_type()) { - return create_array( - matrix.int64_array_value(), NPY_INT64); - } - - if (matrix.is_uint8_type()) { - return create_array( - matrix.uint8_array_value(), NPY_UINT8); - } - if (matrix.is_uint16_type()) { - return create_array( - matrix.uint16_array_value(), NPY_UINT16); - } - if (matrix.is_uint32_type()) { - return create_array( - matrix.uint32_array_value(), NPY_UINT32); - } - if (matrix.is_uint64_type()) { - return create_array( - matrix.uint64_array_value(), NPY_UINT64); - } - - if (matrix.is_bool_type()) { - return create_array( - matrix.bool_array_value(), NPY_BOOL); - } - if (matrix.is_string()) { - return create_array( - matrix.char_array_value(), NPY_CHAR); - } - if (matrix.is_cell()) { - return create_array( - matrix.cell_value(), NPY_OBJECT); - } - - throw value_convert_exception("Octave matrix type not known, " - "conversion not implemented"); - } - - static void octvalue_to_pyarr(boost::python::object &py_object, - const octave_value& octvalue) { - PyArrayObject *pyarr = octvalue_to_pyarrobj(octvalue); - py_object = object(handle((PyObject *)pyarr)); - } - - static void octmap_to_pyobject(boost::python::object &py_object, - const octave_map& map) { - py_object = boost::python::dict(); - string_vector keys = map.keys(); - - for(octave_idx_type i = 0 ; i < keys.numel(); i++) { - boost::python::object py_val; - - const Cell c = map.contents(keys[i]); - - octvalue_to_pyarr(py_val, c); - - py_object[keys[i]] = py_val; - } - } - - void octvalue_to_pyobj(boost::python::object &py_object, - const octave_value& octvalue) { - if (octvalue.is_undefined()) { - throw value_convert_exception( - "Octave value `undefined'. Can not convert to a Python object"); - } else if (octvalue.is_numeric_type() || octvalue.is_string() - || octvalue.is_cell()) { - octvalue_to_pyarr(py_object, octvalue); - } else if (octvalue.is_map()) { - octmap_to_pyobject(py_object, octvalue.map_value()); - } else - throw value_convert_exception( - "Conversion from Octave value not implemented"); - } - - void octlist_to_pytuple(boost::python::tuple &python_tuple, - const octave_value_list &octave_list) { - boost::python::list seq; - int length = octave_list.length(); - - // FIXME: due to bugs in Octave 3.2.3 and earlier, lists returned from - // eval_string and feval may be padded by trailing undefined values. - // Fix is already upstream, so this may be eventually removed. - while (length > 0 && octave_list(length-1).is_undefined()) - length--; - - for (int i = 0; i < length; i++) { - boost::python::object py_object; - octvalue_to_pyobj(py_object, octave_list(i)); - seq.append(py_object); - } - python_tuple = tuple(seq); - } + python_tuple = tuple (seq); + } } diff -r a5ec9bbd94cc -r 8e3d06f2f5cf octave_to_python.h --- a/octave_to_python.h Tue Apr 05 00:16:53 2016 -0700 +++ b/octave_to_python.h Tue Apr 05 08:08:45 2016 -0700 @@ -27,11 +27,12 @@ #include #include -namespace pytave { - void octvalue_to_pyobj(boost::python::object &py_object, +namespace pytave +{ + void octvalue_to_pyobj (boost::python::object& py_object, const octave_value& octvalue); - void octlist_to_pytuple(boost::python::tuple &python_tuple, - const octave_value_list &octave_list); + void octlist_to_pytuple (boost::python::tuple& python_tuple, + const octave_value_list& octave_list); } #endif diff -r a5ec9bbd94cc -r 8e3d06f2f5cf package/pytave.py --- a/package/pytave.py Tue Apr 05 00:16:53 2016 -0700 +++ b/package/pytave.py Tue Apr 05 08:08:45 2016 -0700 @@ -23,6 +23,7 @@ import _pytave import atexit +import numpy import sys try: @@ -40,16 +41,16 @@ interactive = False _pytave.init(interactive) -(OctaveError, ValueConvertError, ObjectConvertError, ParseError, \ - VarNameError) = _pytave.get_exceptions(); +(OctaveError, ValueConvertError, ObjectConvertError, ParseError, + VarNameError) = _pytave.get_exceptions() -import numpy def _atexit(): _pytave.atexit() atexit.register(_atexit) + def feval(nargout, funcname, *arguments): """Executes an Octave function called funcname. @@ -129,6 +130,7 @@ return _pytave.feval(nargout, funcname, arguments) + def eval(nargout, code, silent=True): """Executes a given Octave code. @@ -164,6 +166,7 @@ return _pytave.eval(nargout, code, silent) + def stripdict(dictarray): """A helper function to convert structures obtained from Octave. Because in Octave, all structs are also arrays, they are returned @@ -172,9 +175,10 @@ sdict = {} for key in dictarray: - sdict[key] = dictarray[key][0,0] + sdict[key] = dictarray[key][0, 0] return sdict + def narrowlist(objarray): """A helper function to convert cell arrays obtained from Octave. Octave cells are returned as NumPy object arrays. This function @@ -182,42 +186,42 @@ return numpy.ravel(objarray).tolist() + def simplify(obj): """A helper function to convert results obtained from Octave. This will convert all 1x1 arrays to scalars, vectors to 1D arrays, 1xN and 0x0 character arrays to strings, 1xN, Nx1 and 0x0 cell arrays to lists, and strip scalar dicts. It will work recursively.""" - def vectordims(dims,column_allowed = True): + def vectordims(dims, column_allowed=True): return (len(dims) == 2 and ((dims[0] == 1 or (column_allowed and dims[1] == 1)) or (dims[0] == 0 and dims[1] == 0))) - if isinstance(obj,numpy.ndarray): + if isinstance(obj, numpy.ndarray): tc = obj.dtype.char if tc == 'O': if vectordims(numpy.shape(obj)): - return map(simplify,narrowlist(obj)) + return map(simplify, narrowlist(obj)) elif tc == 'c': if vectordims(numpy.shape(obj), False): return obj.tostring() else: dims = numpy.shape(obj) - if dims == (1,1): - return obj[0,0] + if dims == (1, 1): + return obj[0, 0] elif vectordims(dims): return numpy.ravel(obj) - elif isinstance(obj,dict): + elif isinstance(obj, dict): sobj = {} for key in obj: sval = simplify(obj[key]) - if isinstance(sval,list) and len(sval) == 1: + if isinstance(sval, list) and len(sval) == 1: sval = sval[0] sobj[key] = sval return sobj - elif isinstance(obj,tuple): - return tuple(map(simplify,obj)) - ## default. + elif isinstance(obj, tuple): + return tuple(map(simplify, obj)) return obj @@ -225,22 +229,27 @@ """See Octave documentation""" return _pytave.feval(1, "addpath", arguments)[0] + def rmpath(*paths): """See Octave documentation""" return _pytave.feval(1, "rmpath", paths)[0] + def path(*paths): """See Octave documentation""" return _pytave.feval(1, "path", paths)[0] + def load_package(pkg_name): """Equivalent to pkg load. See Octave documentation.""" return _pytave.feval(0, "pkg", ("load", pkg_name)) + def unload_package(pkg_name): """Equivalent to pkg unload. See Octave documentation.""" return _pytave.feval(0, "pkg", ("unload", pkg_name)) + class _VariablesDict(MutableMapping): def __init__(self, global_variables, native=False): self.global_variables = global_variables @@ -279,6 +288,7 @@ locals = _VariablesDict(global_variables=False) globals = _VariablesDict(global_variables=True) + def push_scope(): """Creates a new anonymous local variable scope on the Octave call stack and sets it as the current Octave scope. Subsequent eval, @@ -291,6 +301,7 @@ """ return _pytave.push_scope() + def pop_scope(): """Pops the current active scope (created previously by push_scope) off the Octave call stack. The previous scope @@ -300,6 +311,7 @@ """ _pytave.pop_scope() + class _LocalScope: def __init__(self, func): self.func = func @@ -313,17 +325,18 @@ finally: _pytave.pop_scope() + def local_scope(func): """Decorates a function to use local Octave scope. Example: @pytave.local_scope - def myfunc(a,b): + def myfunc(a, b): is equivalent to: - def myfunc(a,b): + def myfunc(a, b): try: pytave.push_scope() diff -r a5ec9bbd94cc -r 8e3d06f2f5cf pytave.cc --- a/pytave.cc Tue Apr 05 00:16:53 2016 -0700 +++ b/pytave.cc Tue Apr 05 08:08:45 2016 -0700 @@ -52,309 +52,339 @@ using namespace boost::python; -namespace pytave { /* {{{ */ +namespace pytave +{ #ifdef HAVE_USELOCALE - locale_t c_locale; + locale_t c_locale; #endif #if defined (PYTHON_ABI_VERSION) - PyObject* + PyObject * #else - void + void #endif - init(bool silent = true) { + init (bool silent = true) + { #ifdef HAVE_USELOCALE - c_locale = newlocale(LC_ALL, "C", 0); + c_locale = newlocale (LC_ALL, "C", 0); #endif - if (!octave_error_exception::init() - || !value_convert_exception::init() - || !object_convert_exception::init() - || !octave_parse_exception::init() - || !variable_name_exception::init ()) { - PyErr_SetString(PyExc_ImportError, "_pytave: init failed"); + if (! octave_error_exception::init () + || ! value_convert_exception::init () + || ! object_convert_exception::init () + || ! octave_parse_exception::init () + || ! variable_name_exception::init ()) + { + PyErr_SetString (PyExc_ImportError, "_pytave: init failed"); #if defined (PYTHON_ABI_VERSION) - return 0; + return 0; #else - return; + return; #endif } - // Initialize Octave. - // Also print Octave startup message. - const char* argv[] = {"octave", - "--no-line-editing", - "--no-history", - "--no-init-file", - "--silent", - NULL}; - int argc = 5; + // Initialize Octave. + // Also print Octave startup message. + int argc = 5; + const char *argv[] = + { + "octave", + "--no-line-editing", + "--no-history", + "--no-init-file", + "--silent", + 0 + }; - if (silent) { + if (silent) + { argc--; argv[argc] = 0; } #ifdef HAVE_USELOCALE - // Set C locale - locale_t old_locale = uselocale(c_locale); + // Set C locale + locale_t old_locale = uselocale (c_locale); #endif - octave_main(argc, const_cast(argv), 1); + octave_main (argc, const_cast (argv), 1); #ifdef HAVE_USELOCALE - // Reset locale - uselocale(old_locale); + // Reset locale + uselocale (old_locale); #endif - // Initialize NumPy Array + // Initialize NumPy Array - // Let boost use numpy - numeric::array::set_module_and_type ("numpy", "ndarray"); + // Let boost use numpy + numeric::array::set_module_and_type ("numpy", "ndarray"); - // This is actually a macro that becomes a block expression. If an error - // occurs, e.g. NumPy not installed, an exception is set. - import_array() - } + // This is actually a macro that becomes a block expression. If an error + // occurs, e.g. NumPy not installed, an exception is set. + import_array () + } - boost::python::tuple get_exceptions() { - return make_tuple(object(handle( - octave_error_exception::excclass)), - object(handle( - value_convert_exception::excclass)), - object(handle( - object_convert_exception::excclass)), - object(handle( - octave_parse_exception::excclass)), - object(handle( - variable_name_exception::excclass))); - } - - std::string make_error_message () { - std::ostringstream exceptionmsg; + boost::python::tuple + get_exceptions () + { + return make_tuple (object (handle ( + octave_error_exception::excclass)), + object (handle ( + value_convert_exception::excclass)), + object (handle ( + object_convert_exception::excclass)), + object (handle ( + octave_parse_exception::excclass)), + object (handle ( + variable_name_exception::excclass))); + } - std::string message = last_error_message (); - std::string identifier = last_error_id (); + std::string + make_error_message () + { + std::ostringstream exceptionmsg; - // Trim trailing new lines - message = message.substr(0, message.find_last_not_of("\r\n") + 1); + std::string message = last_error_message (); + std::string identifier = last_error_id (); - octave_map stack = last_error_stack (); + // Trim trailing new lines + message = message.substr (0, message.find_last_not_of ("\r\n") + 1); - if (! stack.is_empty ()) { - std::string file = stack(0).getfield("file").string_value(); - std::string name = stack(0).getfield("name").string_value(); - int line = stack(0).getfield("line").int_value(); - int column = stack(0).getfield("column").int_value(); + octave_map stack = last_error_stack (); - exceptionmsg << file << ":" << line << ":" << column << ": "; - if (!name.empty()) - exceptionmsg << "in '" << name << "': "; + if (! stack.is_empty ()) + { + std::string file = stack(0).getfield ("file").string_value (); + std::string name = stack(0).getfield ("name").string_value (); + int line = stack(0).getfield ("line").int_value (); + int column = stack(0).getfield ("column").int_value (); + + exceptionmsg << file << ":" << line << ":" << column << ": "; + if (! name.empty ()) + exceptionmsg << "in '" << name << "': "; } - if (!identifier.empty()) { - exceptionmsg << "(identifier: " << identifier << ") "; - } - exceptionmsg << message; + if (! identifier.empty ()) + exceptionmsg << "(identifier: " << identifier << ") "; - return exceptionmsg.str (); - } + exceptionmsg << message; + + return exceptionmsg.str (); + } - boost::python::tuple func_eval(const int nargout, - const std::string &funcname, - const boost::python::tuple &arguments) { - - octave_value_list octave_args, retval; + boost::python::tuple + func_eval (int nargout, const std::string& funcname, const boost::python::tuple& arguments) + { + octave_value_list octave_args, retval; - pytuple_to_octlist(octave_args, arguments); + pytuple_to_octlist (octave_args, arguments); - reset_error_handler(); - buffer_error_messages++; + reset_error_handler (); + buffer_error_messages++; - // Updating the timestamp makes Octave reread changed files - Vlast_prompt_time.stamp(); + // Updating the timestamp makes Octave reread changed files + Vlast_prompt_time.stamp (); #ifdef HAVE_USELOCALE - // Set C locale - locale_t old_locale = uselocale(c_locale); + // Set C locale + locale_t old_locale = uselocale (c_locale); #endif - bool bad_alloc_state = false; - bool octave_error = false; + bool bad_alloc_state = false; + bool octave_error = false; - Py_BEGIN_ALLOW_THREADS - try { - retval = feval(funcname, octave_args, (nargout >= 0) ? nargout : 0); - } catch (std::bad_alloc) { - bad_alloc_state = true; - } catch (const octave_execution_exception&) { - octave_error = true; + Py_BEGIN_ALLOW_THREADS + try + { + retval = feval (funcname, octave_args, (nargout >= 0) ? nargout : 0); } - Py_END_ALLOW_THREADS + catch (std::bad_alloc) + { + bad_alloc_state = true; + } + catch (const octave_execution_exception&) + { + octave_error = true; + } + Py_END_ALLOW_THREADS #ifdef HAVE_USELOCALE - // Reset locale - uselocale(old_locale); + // Reset locale + uselocale (old_locale); #endif - if (bad_alloc_state) - throw std::bad_alloc (); // Translated to MemoryError by boost::python + if (bad_alloc_state) + throw std::bad_alloc (); // Translated to MemoryError by boost::python - if (octave_error) { - std::string exceptionmsg = make_error_message (); - if (! exceptionmsg.empty ()) - throw octave_error_exception(exceptionmsg); - else - throw octave_error_exception("No Octave error available"); + if (octave_error) + { + std::string exceptionmsg = make_error_message (); + if (! exceptionmsg.empty ()) + throw octave_error_exception (exceptionmsg); + else + throw octave_error_exception ("No Octave error available"); } - if (nargout >= 0) { - boost::python::tuple pytuple; - octlist_to_pytuple(pytuple, retval); - return pytuple; - } else { - // Return () if nargout < 0. - return make_tuple(); + if (nargout >= 0) + { + boost::python::tuple pytuple; + octlist_to_pytuple (pytuple, retval); + return pytuple; } - } + else + return make_tuple (); + } - boost::python::tuple str_eval(int nargout, - const std::string &code, - bool silent) { + boost::python::tuple + str_eval (int nargout, const std::string& code, bool silent) + { + octave_value_list retval; + int parse_status; - octave_value_list retval; - int parse_status; + reset_error_handler (); + buffer_error_messages++; - reset_error_handler(); - buffer_error_messages++; - - // Updating the timestamp makes Octave reread changed files - Vlast_prompt_time.stamp(); + // Updating the timestamp makes Octave reread changed files + Vlast_prompt_time.stamp (); #ifdef HAVE_USELOCALE - // Set C locale - locale_t old_locale = uselocale(c_locale); + // Set C locale + locale_t old_locale = uselocale (c_locale); #endif - bool bad_alloc_state = false; - bool octave_error = false; + bool bad_alloc_state = false; + bool octave_error = false; - Py_BEGIN_ALLOW_THREADS - try { - retval = eval_string(code, silent, parse_status, - (nargout >= 0) ? nargout : 0); - } catch (std::bad_alloc) { - bad_alloc_state = true; - } catch (const octave_execution_exception&) { - octave_error = true; + Py_BEGIN_ALLOW_THREADS + try + { + retval = eval_string (code, silent, parse_status, (nargout >= 0) ? nargout : 0); } - Py_END_ALLOW_THREADS + catch (std::bad_alloc) + { + bad_alloc_state = true; + } + catch (const octave_execution_exception&) + { + octave_error = true; + } + Py_END_ALLOW_THREADS #ifdef HAVE_USELOCALE - // Reset locale - uselocale(old_locale); + // Reset locale + uselocale (old_locale); #endif - if (bad_alloc_state) - throw std::bad_alloc (); // Translated to MemoryError by boost::python + if (bad_alloc_state) + throw std::bad_alloc (); // Translated to MemoryError by boost::python - if (octave_error || parse_status) { - std::string exceptionmsg = make_error_message (); - if (! exceptionmsg.empty ()) { + if (octave_error || parse_status) + { + std::string exceptionmsg = make_error_message (); + if (! exceptionmsg.empty ()) + { if (parse_status != 0) - throw octave_parse_exception(exceptionmsg); + throw octave_parse_exception (exceptionmsg); else - throw octave_error_exception(exceptionmsg); - } else - throw octave_error_exception("No Octave error available"); + throw octave_error_exception (exceptionmsg); + } + else + throw octave_error_exception ("No Octave error available"); } - if (nargout >= 0) { - boost::python::tuple pytuple; - octlist_to_pytuple(pytuple, retval); - return pytuple; - } else { - // Return () if nargout < 0. - return make_tuple(); + if (nargout >= 0) + { + boost::python::tuple pytuple; + octlist_to_pytuple (pytuple, retval); + return pytuple; } - } + else + return make_tuple (); + } - boost::python::object getvar(const std::string& name, - bool global) { - octave_value val; + boost::python::object + getvar (const std::string& name, bool global) + { + octave_value val; - if (global) - val = symbol_table::global_varval(name); - else - val = symbol_table::varval(name); + if (global) + val = symbol_table::global_varval (name); + else + val = symbol_table::varval (name); - if (val.is_undefined()) { - throw variable_name_exception (name + " not defined in current scope"); - } + if (val.is_undefined ()) + throw variable_name_exception (name + " not defined in current scope"); - boost::python::object pyobject; - octvalue_to_pyobj(pyobject, val); + boost::python::object pyobject; + octvalue_to_pyobj (pyobject, val); - return pyobject; - } + return pyobject; + } - void setvar(const std::string& name, - const boost::python::object& pyobject, - bool global) { - octave_value val; + void + setvar (const std::string& name, const boost::python::object& pyobject, bool global) + { + octave_value val; + + if (! valid_identifier (name)) + throw variable_name_exception (name + " is not a valid identifier"); - if (!valid_identifier(name)) { - throw variable_name_exception (name + " is not a valid identifier"); - } + pyobj_to_octvalue (val, pyobject); - pyobj_to_octvalue(val, pyobject); + if (global) + symbol_table::global_assign (name, val); + else + symbol_table::assign (name, val); + } - if (global) - symbol_table::global_assign (name, val); - else - symbol_table::assign (name, val); - } + bool + isvar (const std::string& name, bool global) + { + bool retval; - bool isvar(const std::string& name, bool global) { - bool retval; + if (global) + retval = symbol_table::global_varval (name).is_defined (); + else + retval = symbol_table::is_variable (name); - if (global) - retval = symbol_table::global_varval (name).is_defined (); - else - retval = symbol_table::is_variable (name); + return retval; + } - return retval; - } - - void delvar(const std::string& name, bool global) { - - if (global) { + void + delvar (const std::string& name, bool global) + { + if (global) + { + // FIXME: workaround a bug in Octave 3.2.0. + if (! symbol_table::is_global (name)) + symbol_table::insert (name).mark_global (); - // FIXME: workaround a bug in Octave 3.2.0. - if (! symbol_table::is_global (name)) - symbol_table::insert (name).mark_global (); - - symbol_table::clear_global (name); - } else - symbol_table::clear_variable (name); - } + symbol_table::clear_global (name); + } + else + symbol_table::clear_variable (name); + } - int push_scope() { - symbol_table::scope_id local_scope = symbol_table::alloc_scope(); - symbol_table::set_scope(local_scope); - octave_call_stack::push(local_scope); - return local_scope; - } + int + push_scope () + { + symbol_table::scope_id local_scope = symbol_table::alloc_scope (); + symbol_table::set_scope (local_scope); + octave_call_stack::push (local_scope); + return local_scope; + } - void pop_scope () { - symbol_table::scope_id curr_scope = symbol_table::current_scope(); - if (curr_scope != symbol_table::top_scope()) - { - symbol_table::erase_scope(curr_scope); - octave_call_stack::pop(); - } - } + void + pop_scope () + { + symbol_table::scope_id curr_scope = symbol_table::current_scope (); + if (curr_scope != symbol_table::top_scope ()) + { + symbol_table::erase_scope (curr_scope); + octave_call_stack::pop (); + } + } // Make sure Octave is correctly unloaded. We cannot depend on Octave running // at the (true) process atexit point, because at that time the Octave library @@ -363,55 +393,56 @@ // At least that is the hypothesis, since Octave (in certain circumstances) // cause a segmentation fault in do_octave_atexit called from the exit // function. (One Octave call that causes this is "sleep(0)".) - void atexit () { + void + atexit () + { #ifdef HAVE_USELOCALE - // Set C locale - locale_t old_locale = uselocale(c_locale); + // Set C locale + locale_t old_locale = uselocale (c_locale); #endif - Py_BEGIN_ALLOW_THREADS - clean_up_and_exit (0); - Py_END_ALLOW_THREADS + Py_BEGIN_ALLOW_THREADS + clean_up_and_exit (0); + Py_END_ALLOW_THREADS #ifdef HAVE_USELOCALE - // Reset locale - uselocale(old_locale); + // Reset locale + uselocale (old_locale); #endif - } + } +} -} /* namespace pytave }}} */ - -BOOST_PYTHON_MODULE(_pytave) { /* {{{ */ - using namespace boost::python; +BOOST_PYTHON_MODULE (_pytave) +{ + using namespace boost::python; - def("init", pytave::init); - def("feval", pytave::func_eval); - def("eval", pytave::str_eval); - def("getvar", pytave::getvar); - def("setvar", pytave::setvar); - def("isvar", pytave::isvar); - def("delvar", pytave::delvar); - def("push_scope", pytave::push_scope); - def("pop_scope", pytave::pop_scope); - def("atexit", pytave::atexit); - def("get_exceptions", pytave::get_exceptions); + def ("init", pytave::init); + def ("feval", pytave::func_eval); + def ("eval", pytave::str_eval); + def ("getvar", pytave::getvar); + def ("setvar", pytave::setvar); + def ("isvar", pytave::isvar); + def ("delvar", pytave::delvar); + def ("push_scope", pytave::push_scope); + def ("pop_scope", pytave::pop_scope); + def ("atexit", pytave::atexit); + def ("get_exceptions", pytave::get_exceptions); - register_exception_translator( - pytave::pytave_exception::translate_exception); + register_exception_translator ( + pytave::pytave_exception::translate_exception); - register_exception_translator( - pytave::octave_error_exception::translate_exception); + register_exception_translator ( + pytave::octave_error_exception::translate_exception); - register_exception_translator( - pytave::octave_parse_exception::translate_exception); + register_exception_translator ( + pytave::octave_parse_exception::translate_exception); - register_exception_translator( - pytave::object_convert_exception::translate_exception); + register_exception_translator ( + pytave::object_convert_exception::translate_exception); - register_exception_translator( - pytave::value_convert_exception::translate_exception); + register_exception_translator ( + pytave::value_convert_exception::translate_exception); - register_exception_translator( - pytave::variable_name_exception::translate_exception); - -} /* }}} */ + register_exception_translator ( + pytave::variable_name_exception::translate_exception); +} diff -r a5ec9bbd94cc -r 8e3d06f2f5cf python_to_octave.cc --- a/python_to_octave.cc Tue Apr 05 00:16:53 2016 -0700 +++ b/python_to_octave.cc Tue Apr 05 08:08:45 2016 -0700 @@ -42,427 +42,450 @@ using namespace boost::python; -namespace pytave { - - void pyobj_to_octvalue(octave_value &oct_value, - const boost::python::object &py_object); - - template - static void copy_pyarrobj_to_octarray(OctaveBase &matrix, - PyArrayObject* pyarr, - const int unsigned matindex, - const unsigned int matstride, - const int dimension, - const unsigned int offset) { - unsigned char *ptr = (unsigned char*) PyArray_DATA (pyarr); - if (dimension == PyArray_NDIM (pyarr) - 1) { - // Last dimension, base case - for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) { - matrix.elem(matindex + i*matstride) +namespace pytave +{ + template + static void + copy_pyarrobj_to_octarray (OctaveBase& matrix, PyArrayObject *pyarr, + const int unsigned matindex, + const unsigned int matstride, + const int dimension, const unsigned int offset) + { + unsigned char *ptr = (unsigned char*) PyArray_DATA (pyarr); + if (dimension == PyArray_NDIM (pyarr) - 1) + { + // Last dimension, base case + for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) + { + matrix.elem (matindex + i*matstride) = *(PythonPrimitive*) &ptr[offset + i*PyArray_STRIDE (pyarr, dimension)]; - } - } else if (PyArray_NDIM (pyarr) == 0) { - matrix.elem(0) = *(PythonPrimitive*) ptr; - } else { - for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) { - copy_pyarrobj_to_octarray( - matrix, - pyarr, - matindex + i*matstride, - matstride * PyArray_DIM (pyarr, dimension), - dimension + 1, - offset + i*PyArray_STRIDE (pyarr, dimension)); - } + } + } + else if (PyArray_NDIM (pyarr) == 0) + { + matrix.elem (0) = *(PythonPrimitive*) ptr; } - } + else + { + for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) + { + copy_pyarrobj_to_octarray ( + matrix, + pyarr, + matindex + i*matstride, + matstride * PyArray_DIM (pyarr, dimension), + dimension + 1, + offset + i*PyArray_STRIDE (pyarr, dimension)); + } + } + } - template <> - void copy_pyarrobj_to_octarray(Cell &matrix, - PyArrayObject* pyarr, - const int unsigned matindex, - const unsigned int matstride, - const int dimension, - const unsigned int offset) { - unsigned char *ptr = (unsigned char*) PyArray_DATA (pyarr); - if (dimension == PyArray_NDIM (pyarr) - 1) { - // Last dimension, base case - for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) { + template <> + void + copy_pyarrobj_to_octarray (Cell& matrix, + PyArrayObject *pyarr, + const int unsigned matindex, + const unsigned int matstride, + const int dimension, + const unsigned int offset) + { + unsigned char *ptr = (unsigned char*) PyArray_DATA (pyarr); + if (dimension == PyArray_NDIM (pyarr) - 1) + { + // Last dimension, base case + for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) + { PyObject *pobj = *(PyObject **) &ptr[offset + i*PyArray_STRIDE (pyarr, dimension)]; - pyobj_to_octvalue (matrix.elem(matindex + i*matstride), - object(handle (borrowed (pobj)))); - } - } else if (PyArray_NDIM (pyarr) == 0) { - PyObject *pobj = *(PyObject **) ptr; - pyobj_to_octvalue (matrix.elem(0), - object(handle (borrowed (pobj)))); - } else { - for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) { - copy_pyarrobj_to_octarray( - matrix, - pyarr, - matindex + i*matstride, - matstride * PyArray_DIM (pyarr, dimension), - dimension + 1, - offset + i*PyArray_STRIDE (pyarr, dimension)); - } + pyobj_to_octvalue (matrix.elem (matindex + i*matstride), + object (handle (borrowed (pobj)))); + } + } + else if (PyArray_NDIM (pyarr) == 0) + { + PyObject *pobj = *(PyObject **) ptr; + pyobj_to_octvalue (matrix.elem (0), + object (handle (borrowed (pobj)))); } - } + else + { + for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) + { + copy_pyarrobj_to_octarray ( + matrix, + pyarr, + matindex + i*matstride, + matstride * PyArray_DIM (pyarr, dimension), + dimension + 1, + offset + i*PyArray_STRIDE (pyarr, dimension)); + } + } + } - template - static void copy_pyarrobj_to_octarray_dispatch(OctaveBase &matrix, - PyArrayObject* pyarr, - const boost::true_type&) { - copy_pyarrobj_to_octarray - (matrix, pyarr, 0, 1, 0, 0); - } + template + static void + copy_pyarrobj_to_octarray_dispatch (OctaveBase& matrix, + PyArrayObject *pyarr, + const boost::true_type&) + { + copy_pyarrobj_to_octarray (matrix, pyarr, 0, 1, 0, 0); + } - template - static void copy_pyarrobj_to_octarray_dispatch(OctaveBase &matrix, - PyArrayObject* pyarr, - const boost::false_type&) { - assert(0); - } + template + static void + copy_pyarrobj_to_octarray_dispatch (OctaveBase& matrix, + PyArrayObject *pyarr, + const boost::false_type&) + { + assert (0); + } - template class matching_type : public boost::false_type { }; - template class matching_type : public boost::true_type { }; - template class matching_type > : public boost::true_type { }; - template <> class matching_type : public boost::true_type { }; - template <> class matching_type : public boost::true_type { }; - template <> class matching_type : public boost::true_type { }; + template class matching_type : public boost::false_type { }; + template class matching_type : public boost::true_type { }; + template class matching_type > : public boost::true_type { }; + template <> class matching_type : public boost::true_type { }; + template <> class matching_type : public boost::true_type { }; + template <> class matching_type : public boost::true_type { }; - template - static void copy_pyarrobj_to_octarray_dispatch(OctaveBase &matrix, - PyArrayObject* pyarr) { - matching_type inst; - copy_pyarrobj_to_octarray_dispatch (matrix, pyarr, inst); - } + template + static void + copy_pyarrobj_to_octarray_dispatch (OctaveBase& matrix, + PyArrayObject *pyarr) + { + matching_type inst; + copy_pyarrobj_to_octarray_dispatch (matrix, pyarr, inst); + } - template - static void copy_pyarrobj_to_octarray_boot(OctaveBase &matrix, - PyArrayObject* pyarr) { + template + static void + copy_pyarrobj_to_octarray_boot (OctaveBase& matrix, PyArrayObject *pyarr) + { #define ARRAYCASE(AC_pyarrtype, AC_primitive) case AC_pyarrtype: \ - copy_pyarrobj_to_octarray_dispatch\ + copy_pyarrobj_to_octarray_dispatch \ (matrix, pyarr); \ break; \ - // Coerce NumPy's long type into one of two possible sized integer types - int type_num = PyArray_TYPE (pyarr); - switch (type_num) { - case NPY_LONG: - if (sizeof(npy_long) == sizeof(int64_t)) { - type_num = NPY_INT64; - } - else if (sizeof(npy_long) == sizeof(int32_t)) { - type_num = NPY_INT32; - } - break; - case NPY_LONGLONG: - if (sizeof(npy_longlong) == sizeof(int64_t)) { - type_num = NPY_INT64; - } - else if (sizeof(npy_longlong) == sizeof(int32_t)) { - type_num = NPY_INT32; - } - break; - case NPY_ULONG: - if (sizeof(npy_ulong) == sizeof(uint64_t)) { - type_num = NPY_UINT64; - } - else if (sizeof(npy_ulong) == sizeof(uint32_t)) { - type_num = NPY_UINT32; - } - break; - case NPY_ULONGLONG: - if (sizeof(npy_ulonglong) == sizeof(uint64_t)) { - type_num = NPY_UINT64; - } - else if (sizeof(npy_ulonglong) == sizeof(uint32_t)) { - type_num = NPY_UINT32; - } - break; + // Coerce NumPy's long type into one of two possible sized integer types + int type_num = PyArray_TYPE (pyarr); + switch (type_num) + { + case NPY_LONG: + if (sizeof (npy_long) == sizeof (int64_t)) + type_num = NPY_INT64; + else if (sizeof (npy_long) == sizeof (int32_t)) + type_num = NPY_INT32; + break; + case NPY_LONGLONG: + if (sizeof (npy_longlong) == sizeof (int64_t)) + type_num = NPY_INT64; + else if (sizeof (npy_longlong) == sizeof (int32_t)) + type_num = NPY_INT32; + break; + case NPY_ULONG: + if (sizeof (npy_ulong) == sizeof (uint64_t)) + type_num = NPY_UINT64; + else if (sizeof (npy_ulong) == sizeof (uint32_t)) + type_num = NPY_UINT32; + break; + case NPY_ULONGLONG: + if (sizeof (npy_ulonglong) == sizeof (uint64_t)) + type_num = NPY_UINT64; + else if (sizeof (npy_ulonglong) == sizeof (uint32_t)) + type_num = NPY_UINT32; + break; } - switch (type_num) { - ARRAYCASE(NPY_INT8, int8_t) - ARRAYCASE(NPY_INT16, int16_t) - ARRAYCASE(NPY_INT32, int32_t) - ARRAYCASE(NPY_INT64, int64_t) - ARRAYCASE(NPY_UINT8, uint8_t) - ARRAYCASE(NPY_UINT16, uint16_t) - ARRAYCASE(NPY_UINT32, uint32_t) - ARRAYCASE(NPY_UINT64, uint64_t) - ARRAYCASE(NPY_FLOAT, float) - ARRAYCASE(NPY_DOUBLE, double) - ARRAYCASE(NPY_CFLOAT, FloatComplex) - ARRAYCASE(NPY_CDOUBLE, Complex) - ARRAYCASE(NPY_BOOL, bool) - ARRAYCASE(NPY_CHAR, char) - ARRAYCASE(NPY_STRING, char) - ARRAYCASE(NPY_OBJECT, PyObject *) + switch (type_num) + { + ARRAYCASE (NPY_INT8, int8_t) + ARRAYCASE (NPY_INT16, int16_t) + ARRAYCASE (NPY_INT32, int32_t) + ARRAYCASE (NPY_INT64, int64_t) + ARRAYCASE (NPY_UINT8, uint8_t) + ARRAYCASE (NPY_UINT16, uint16_t) + ARRAYCASE (NPY_UINT32, uint32_t) + ARRAYCASE (NPY_UINT64, uint64_t) + ARRAYCASE (NPY_FLOAT, float) + ARRAYCASE (NPY_DOUBLE, double) + ARRAYCASE (NPY_CFLOAT, FloatComplex) + ARRAYCASE (NPY_CDOUBLE, Complex) + ARRAYCASE (NPY_BOOL, bool) + ARRAYCASE (NPY_CHAR, char) + ARRAYCASE (NPY_STRING, char) + ARRAYCASE (NPY_OBJECT, PyObject *) - default: - throw object_convert_exception( - PyEval_GetFuncName((PyObject*)pyarr) - + (PyEval_GetFuncDesc((PyObject*)pyarr) - + std::string(": Unsupported Python array type"))); + default: + throw object_convert_exception ( + PyEval_GetFuncName ((PyObject*)pyarr) + + (PyEval_GetFuncDesc ((PyObject*)pyarr) + + std::string (": Unsupported Python array type"))); } - } + } - template - static void pyarrobj_to_octvalueNd(octave_value &octvalue, - PyArrayObject* pyarr, - dim_vector dims) { - OctaveBase array(dims); - copy_pyarrobj_to_octarray_boot(array, pyarr); - octvalue = array; - } + template + static void + pyarrobj_to_octvalueNd (octave_value& octvalue, PyArrayObject *pyarr, + const dim_vector& dims) + { + OctaveBase array (dims); + copy_pyarrobj_to_octarray_boot (array, pyarr); + octvalue = array; + } - static void pyarr_to_octvalue(octave_value &octvalue, - PyArrayObject *pyarr) { - dim_vector dims; - switch (PyArray_NDIM (pyarr)) { - case 0: - dims = dim_vector (1, 1); - break; - case 1: - // Always make PyArray vectors row vectors. - dims = dim_vector(1, PyArray_DIM (pyarr, 0)); - break; - default: - dims.resize(PyArray_NDIM (pyarr)); - for (int d = 0; d < PyArray_NDIM (pyarr); d++) { - dims(d) = PyArray_DIM (pyarr, d); - } - break; + static void + pyarr_to_octvalue (octave_value& octvalue, PyArrayObject *pyarr) + { + dim_vector dims; + switch (PyArray_NDIM (pyarr)) + { + case 0: + dims = dim_vector (1, 1); + break; + case 1: + // Always make PyArray vectors row vectors. + dims = dim_vector (1, PyArray_DIM (pyarr, 0)); + break; + default: + dims.resize (PyArray_NDIM (pyarr)); + for (int d = 0; d < PyArray_NDIM (pyarr); d++) + dims(d) = PyArray_DIM (pyarr, d); + break; } - switch (PyArray_TYPE (pyarr)) { - case NPY_BYTE: - case NPY_SHORT: - case NPY_INT: - case NPY_LONG: - case NPY_LONGLONG: - switch (PyArray_ITEMSIZE (pyarr)) { - case 1: - pyarrobj_to_octvalueNd(octvalue, pyarr, dims); - break; - case 2: - pyarrobj_to_octvalueNd(octvalue, pyarr, dims); - break; - case 4: - pyarrobj_to_octvalueNd(octvalue, pyarr, dims); - break; - case 8: - pyarrobj_to_octvalueNd(octvalue, pyarr, dims); - break; - default: - throw object_convert_exception("Unknown integer."); - } + switch (PyArray_TYPE (pyarr)) + { + case NPY_BYTE: + case NPY_SHORT: + case NPY_INT: + case NPY_LONG: + case NPY_LONGLONG: + switch (PyArray_ITEMSIZE (pyarr)) + { + case 1: + pyarrobj_to_octvalueNd (octvalue, pyarr, dims); + break; + case 2: + pyarrobj_to_octvalueNd (octvalue, pyarr, dims); + break; + case 4: + pyarrobj_to_octvalueNd (octvalue, pyarr, dims); + break; + case 8: + pyarrobj_to_octvalueNd (octvalue, pyarr, dims); break; - case NPY_UBYTE: - case NPY_USHORT: - case NPY_UINT: - case NPY_ULONG: - case NPY_ULONGLONG: - switch (PyArray_ITEMSIZE (pyarr)) { - case 1: - pyarrobj_to_octvalueNd(octvalue, pyarr, dims); - break; - case 2: - pyarrobj_to_octvalueNd(octvalue, pyarr, dims); - break; - case 4: - pyarrobj_to_octvalueNd(octvalue, pyarr, dims); - break; - case 8: - pyarrobj_to_octvalueNd(octvalue, pyarr, dims); - break; - default: - throw object_convert_exception("Unknown unsigned integer."); - } + default: + throw object_convert_exception ("Unknown integer."); + } + break; + case NPY_UBYTE: + case NPY_USHORT: + case NPY_UINT: + case NPY_ULONG: + case NPY_ULONGLONG: + switch (PyArray_ITEMSIZE (pyarr)) + { + case 1: + pyarrobj_to_octvalueNd (octvalue, pyarr, dims); break; - case NPY_FLOAT: - pyarrobj_to_octvalueNd(octvalue, pyarr, dims); + case 2: + pyarrobj_to_octvalueNd (octvalue, pyarr, dims); break; - case NPY_DOUBLE: - pyarrobj_to_octvalueNd(octvalue, pyarr, dims); + case 4: + pyarrobj_to_octvalueNd (octvalue, pyarr, dims); + break; + case 8: + pyarrobj_to_octvalueNd (octvalue, pyarr, dims); break; - case NPY_CFLOAT: - pyarrobj_to_octvalueNd(octvalue, pyarr, dims); - break; - case NPY_CDOUBLE: - pyarrobj_to_octvalueNd(octvalue, pyarr, dims); - break; - case NPY_BOOL: - pyarrobj_to_octvalueNd(octvalue, pyarr, dims); - break; - case NPY_CHAR: - case_NPY_CHAR: - pyarrobj_to_octvalueNd(octvalue, pyarr, dims); - // FIXME: is the following needed? - octvalue = octvalue.convert_to_str(true, true, '"'); - break; - case NPY_STRING: + default: + throw object_convert_exception ("Unknown unsigned integer."); + } + break; + case NPY_FLOAT: + pyarrobj_to_octvalueNd (octvalue, pyarr, dims); + break; + case NPY_DOUBLE: + pyarrobj_to_octvalueNd (octvalue, pyarr, dims); + break; + case NPY_CFLOAT: + pyarrobj_to_octvalueNd (octvalue, pyarr, dims); + break; + case NPY_CDOUBLE: + pyarrobj_to_octvalueNd (octvalue, pyarr, dims); + break; + case NPY_BOOL: + pyarrobj_to_octvalueNd (octvalue, pyarr, dims); + break; + case NPY_CHAR: + case_NPY_CHAR: + pyarrobj_to_octvalueNd (octvalue, pyarr, dims); + // FIXME: is the following needed? + octvalue = octvalue.convert_to_str (true, true, '"'); + break; + case NPY_STRING: + { + if (PyArray_ITEMSIZE (pyarr) == 1) + goto case_NPY_CHAR; + else { - if (PyArray_ITEMSIZE (pyarr) == 1) - goto case_NPY_CHAR; - else { - // Create a new descriptor of the data. - PyArray_Descr *view_descr = PyArray_DescrFromType(NPY_CHAR); - // Create a new view of the NumPy array. - PyArrayObject *view = (PyArrayObject *)PyArray_View (pyarr, view_descr, NULL); - // Store in a handle to ensure proper destruction. - handle view_handle (allow_null ((PyObject *)view)); - // Call recursively. - pyarr_to_octvalue (octvalue, view); - } + // Create a new descriptor of the data. + PyArray_Descr *view_descr = PyArray_DescrFromType (NPY_CHAR); + // Create a new view of the NumPy array. + PyArrayObject *view = (PyArrayObject *)PyArray_View (pyarr, view_descr, 0); + // Store in a handle to ensure proper destruction. + handle view_handle (allow_null ((PyObject *)view)); + // Call recursively. + pyarr_to_octvalue (octvalue, view); } - break; - case NPY_OBJECT: - pyarrobj_to_octvalueNd(octvalue, pyarr, dims); - break; - default: - throw object_convert_exception( - PyEval_GetFuncDesc((PyObject*)(pyarr)) + std::string(" ") - + PyEval_GetFuncName((PyObject*)(pyarr)) - + ": Encountered unsupported Python array"); - break; + } + break; + case NPY_OBJECT: + pyarrobj_to_octvalueNd (octvalue, pyarr, dims); + break; + default: + throw object_convert_exception ( + PyEval_GetFuncDesc ((PyObject*)(pyarr)) + std::string (" ") + + PyEval_GetFuncName ((PyObject*)(pyarr)) + + ": Encountered unsupported Python array"); + break; } - } - - static void pylist_to_cellarray(octave_value &oct_value, - const boost::python::list &list) { + } - octave_idx_type length = boost::python::extract( - list.attr("__len__")()); - octave_value_list values; + static void + pylist_to_cellarray (octave_value& oct_value, const boost::python::list& list) + { + octave_idx_type length = boost::python::extract (list.attr ("__len__") ()); + octave_value_list values; - for(octave_idx_type i = 0; i < length; i++) { + for (octave_idx_type i = 0; i < length; i++) + { octave_value val; - pyobj_to_octvalue(val, list[i]); - values.append(val); + pyobj_to_octvalue (val, list[i]); + values.append (val); } - oct_value = Cell(values); - } - - static void pydict_to_octmap(octave_value &oct_value, - const boost::python::dict &dict) { + oct_value = Cell (values); + } - boost::python::list list = dict.items(); - octave_idx_type length = boost::python::extract( - list.attr("__len__")()); + static void + pydict_to_octmap (octave_value& oct_value, const boost::python::dict& dict) + { + boost::python::list list = dict.items (); + octave_idx_type length = boost::python::extract (list.attr ("__len__") ()); - dim_vector dims = dim_vector(1, 1); + dim_vector dims = dim_vector (1, 1); - octave_value_list vals (length); - string_vector keys (length); + octave_value_list vals (length); + string_vector keys (length); - // Extract all keys and convert values. Remember whether dimensions - // match. + // Extract all keys and convert values. Remember whether dimensions + // match. - for(octave_idx_type i = 0; i < length; i++) { + for (octave_idx_type i = 0; i < length; i++) + { + std::string& key = keys[i]; - std::string& key = keys[i]; - - boost::python::tuple tuple = - boost::python::extract(list[i])(); + boost::python::tuple tuple = + boost::python::extract (list[i]) (); - boost::python::extract str(tuple[0]); - if(!str.check()) { - throw object_convert_exception( - std::string("Can not convert key of type ") - + PyEval_GetFuncName(boost::python::object(tuple[0]).ptr()) - + PyEval_GetFuncDesc(boost::python::object(tuple[0]).ptr()) - + " to a structure field name. Field names must be strings."); - } + boost::python::extract str (tuple[0]); + if (! str.check ()) + throw object_convert_exception ( + std::string ("Can not convert key of type ") + + PyEval_GetFuncName (boost::python::object (tuple[0]).ptr ()) + + PyEval_GetFuncDesc (boost::python::object (tuple[0]).ptr ()) + + " to a structure field name. Field names must be strings."); - key = str(); + key = str (); - if (!valid_identifier(key)) { - throw object_convert_exception( - std::string("Can not convert key `") + key + "' to a structure " - "field name. Field names must be valid Octave identifiers."); - } + if (! valid_identifier (key)) + throw object_convert_exception ( + std::string ("Can not convert key `") + key + "' to a structure " + "field name. Field names must be valid Octave identifiers."); - octave_value& val = vals(i); + octave_value& val = vals(i); + + pyobj_to_octvalue (val, tuple[1]); - pyobj_to_octvalue(val, tuple[1]); - - if(val.is_cell()) { - if(i == 0) { - dims = val.dims(); - } else if (val.numel() != 1 && val.dims() != dims){ - throw object_convert_exception( - "Dimensions of the struct fields do not match"); - } - } + if (val.is_cell ()) + { + if (i == 0) + dims = val.dims (); + else if (val.numel () != 1 && val.dims () != dims) + throw object_convert_exception ( + "Dimensions of the struct fields do not match"); + } } - octave_map map = octave_map(dims); + octave_map map = octave_map (dims); - for(octave_idx_type i = 0; i < length; i++) { - - std::string& key = keys[i]; - octave_value val = vals(i); + for (octave_idx_type i = 0; i < length; i++) + { + std::string& key = keys[i]; + octave_value val = vals(i); - if(val.is_cell()) { - const Cell c = val.cell_value(); - if (c.numel () == 1) { - map.assign(key, Cell(dims, c(0))); - } else { - map.assign(key, c); + if (val.is_cell ()) + { + const Cell c = val.cell_value (); + if (c.numel () == 1) + { + map.assign (key, Cell (dims, c(0))); } - } else { - map.assign(key, Cell(dims, val)); + else + { + map.assign (key, c); + } } + else + map.assign (key, Cell (dims, val)); } - oct_value = map; - } + oct_value = map; + } - void pyobj_to_octvalue(octave_value &oct_value, - const boost::python::object &py_object) { - extract intx(py_object); - extract doublex(py_object); - extract complexx(py_object); - extract stringx(py_object); - extract arrayx(py_object); - extract listx(py_object); - extract dictx(py_object); - if (intx.check()) { - oct_value = intx(); - } else if (doublex.check()) { - oct_value = doublex(); - } else if (complexx.check()) { - oct_value = complexx(); - } else if (arrayx.check()) { - pyarr_to_octvalue(oct_value, (PyArrayObject*)py_object.ptr()); - } else if (stringx.check()) { - oct_value = stringx(); - } else if (listx.check()) { - pylist_to_cellarray(oct_value, (boost::python::list&)py_object); - } else if (dictx.check()) { - pydict_to_octmap(oct_value, (boost::python::dict&)py_object); - } else { - throw object_convert_exception( - PyEval_GetFuncName(py_object.ptr()) - + (PyEval_GetFuncDesc(py_object.ptr()) - + std::string(": Unsupported Python object type, " - "cannot convert to Octave value"))); + void pyobj_to_octvalue (octave_value& oct_value, + const boost::python::object& py_object) + { + extract intx (py_object); + extract doublex (py_object); + extract complexx (py_object); + extract stringx (py_object); + extract arrayx (py_object); + extract listx (py_object); + extract dictx (py_object); + + if (intx.check ()) + oct_value = intx (); + else if (doublex.check ()) + oct_value = doublex (); + else if (complexx.check ()) + oct_value = complexx (); + else if (arrayx.check ()) + pyarr_to_octvalue (oct_value, (PyArrayObject*)py_object.ptr ()); + else if (stringx.check ()) + oct_value = stringx (); + else if (listx.check ()) + pylist_to_cellarray (oct_value, (boost::python::list&)py_object); + else if (dictx.check ()) + pydict_to_octmap (oct_value, (boost::python::dict&)py_object); + else + throw object_convert_exception ( + PyEval_GetFuncName (py_object.ptr ()) + + (PyEval_GetFuncDesc (py_object.ptr ()) + + std::string (": Unsupported Python object type, " + "cannot convert to Octave value"))); + } + + void pytuple_to_octlist (octave_value_list& octave_list, + const boost::python::tuple& python_tuple) + { + int length = extract (python_tuple.attr ("__len__") ()); + + for (int i = 0; i < length; i++) + { + pyobj_to_octvalue (octave_list(i), python_tuple[i]); } - } - - void pytuple_to_octlist(octave_value_list &octave_list, - const boost::python::tuple &python_tuple) { - int length = extract(python_tuple.attr("__len__")()); - - for (int i = 0; i < length; i++) { - pyobj_to_octvalue(octave_list(i), python_tuple[i]); - } - } + } } diff -r a5ec9bbd94cc -r 8e3d06f2f5cf python_to_octave.h --- a/python_to_octave.h Tue Apr 05 00:16:53 2016 -0700 +++ b/python_to_octave.h Tue Apr 05 08:08:45 2016 -0700 @@ -27,11 +27,12 @@ #include #include -namespace pytave { - void pyobj_to_octvalue(octave_value &oct_value, - const boost::python::object &py_object); - void pytuple_to_octlist(octave_value_list &octave_list, - const boost::python::tuple &python_tuple); +namespace pytave +{ + void pyobj_to_octvalue (octave_value& oct_value, + const boost::python::object& py_object); + void pytuple_to_octlist (octave_value_list& octave_list, + const boost::python::tuple& python_tuple); } #endif diff -r a5ec9bbd94cc -r 8e3d06f2f5cf test/exceptions.py --- a/test/exceptions.py Tue Apr 05 00:16:53 2016 -0700 +++ b/test/exceptions.py Tue Apr 05 08:08:45 2016 -0700 @@ -1,23 +1,24 @@ #!/usr/bin/python + import pytave try: - pytave.feval(1,"",) + pytave.feval(1, "") except pytave.OctaveError, e: - print "test ok" + print "test ok" except: - print "test fail" + print "test fail" try: - pytave.feval(1,"cell",) + pytave.feval(1, "cell") except pytave.ValueConvertError, e: - print "test ok" + print "test ok" except: - print "test fail" + print "test fail" try: - pytave.feval(1,"sin",{"asdf":"asdf"}) + pytave.feval(1, "sin", {"asdf": "asdf"}) except pytave.ObjectConvertError, e: - print "test ok" + print "test ok" except: - print "test fail" + print "test fail" diff -r a5ec9bbd94cc -r 8e3d06f2f5cf test/test.py --- a/test/test.py Tue Apr 05 00:16:53 2016 -0700 +++ b/test/test.py Tue Apr 05 08:08:45 2016 -0700 @@ -7,9 +7,9 @@ print "No messages indicates test pass." -arr0_0 = numpy.zeros((0,0)); -arr0_1 = numpy.zeros((0,1)); -arr1_0 = numpy.zeros((1,0)); +arr0_0 = numpy.zeros((0, 0)) +arr0_1 = numpy.zeros((0, 1)) +arr1_0 = numpy.zeros((1, 0)) number = numpy.array([[1.32]], numpy.float32) arr1fT = numpy.array([[1.32], [2], [3], [4]], numpy.float32) arr1fT2 = numpy.array([[1.32, 2, 3, 4]], numpy.float32) @@ -17,166 +17,183 @@ arr1b = numpy.array([[8, 2, 3, 256]], numpy.int8) arr1i = numpy.array([[17, 2, 3, 4]], numpy.int) arr1i32 = numpy.array([[32, 2, 3, 4]], numpy.int32) -arr1i64 = numpy.array([[32, 2, 3, 4]], dtype=numpy.int64) +arr1i64 = numpy.array([[32, 2, 3, 4]], numpy.int64) arr1a = numpy.array([[1, 2, 3, 4]]) -arr2f = numpy.array([[1.32, 2, 3, 4],[5,6,7,8]], numpy.float32) -arr2d = numpy.array([[1.17, 2, 3, 4],[5,6,7,8]], numpy.float) -arr3f = numpy.array([[[1.32, 2, 3, 4],[5,6,7,8]],[[9, 10, 11, 12],[13,14,15,16]]], numpy.float32) -arr1c = numpy.array([[1+2j, 3+4j, 5+6j, 7+0.5j]], numpy.complex) -arr1fc = numpy.array([[1+2j, 3+4j, 5+6j, 7+0.5j]], numpy.complex64) -arr1ch = numpy.array([["abc"]],numpy.character) -arr2ch = numpy.array([["abc"],["def"]],numpy.character) -arr1o = numpy.array([[1.0,"abc",2+3j]],numpy.object) -arr2o = numpy.array([[1.0,"abc",2+3j],[4.0,arr1i,"def"]],numpy.object) +arr2f = numpy.array([[1.32, 2, 3, 4], [5, 6, 7, 8]], numpy.float32) +arr2d = numpy.array([[1.17, 2, 3, 4], [5, 6, 7, 8]], numpy.float) +arr3f = numpy.array([[[1.32, 2, 3, 4], [5, 6, 7, 8]], + [[9, 10, 11, 12], [13, 14, 15, 16]]], numpy.float32) +arr1c = numpy.array([[1 + 2j, 3 + 4j, 5 + 6j, 7 + 0.5j]], numpy.complex) +arr1fc = numpy.array([[1 + 2j, 3 + 4j, 5 + 6j, 7 + 0.5j]], numpy.complex64) +arr1ch = numpy.array([["abc"]], numpy.character) +arr2ch = numpy.array([["abc"], ["def"]], numpy.character) +arr1o = numpy.array([[1.0, "abc", 2 + 3j]], numpy.object) +arr2o = numpy.array([[1.0, "abc", 2 + 3j], [4.0, arr1i, "def"]], numpy.object) -alimit_int64 = numpy.array([[-9223372036854775808L, 9223372036854775807L]], dtype=numpy.int64); -alimit_int32 = numpy.array([[-2147483648, 2147483647]], numpy.int32); -alimit_int16 = numpy.array([[-32768, 32767, -32769, 32768]], numpy.int16); -alimit_int8 = numpy.array([[-128, 127, -129, 128]], numpy.int8); -alimit_uint8 = numpy.array([[0, 255, -1, 256]], numpy.uint8); +alimit_int64 = numpy.array([[-9223372036854775808L, 9223372036854775807L]], + numpy.int64) +alimit_int32 = numpy.array([[-2147483648, 2147483647]], numpy.int32) +alimit_int16 = numpy.array([[-32768, 32767, -32769, 32768]], numpy.int16) +alimit_int8 = numpy.array([[-128, 127, -129, 128]], numpy.int8) +alimit_uint8 = numpy.array([[0, 255, -1, 256]], numpy.uint8) -# 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.eval(0, "function [result] = test_return(arg); result = arg; endfunction") +# Define a function in the Octave test session that simply returns the +# single value given to it. +pytave.eval(0, "function y = test_return (x); y = x; endfunction") pytave.feval(1, "test_return", 1) -def equals(a,b): + +def equals(a, b): return numpy.alltrue(numpy.ravel(a == b)) + def fail(msg, exc=None): - print "FAIL:", msg - traceback.print_stack() - if exc is not None: - traceback.print_exc(exc) - print "" + 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 not equals(value, nvalue): - fail("as %s != %s" % (value, nvalue)) - except TypeError, e: - fail(value, e) + try: + nvalue, = pytave.feval(1, "test_return", value) + if not equals(value, nvalue): + fail("as %s != %s" % (value, nvalue)) + except TypeError, e: + fail(value, e) + def testexpect(value, expected): - try: - nvalue, = pytave.feval(1, "test_return", value) - if not equals(value, nvalue): - fail("sent in %s, expecting %s, got %s", (value, expected, nvalue)) - except TypeError, e: - fail(value, e) + try: + nvalue, = pytave.feval(1, "test_return", value) + if not equals(value, nvalue): + fail("sent in %s, expecting %s, got %s", (value, expected, nvalue)) + except TypeError, e: + fail(value, e) + def testmatrix(value): - try: - nvalue, = pytave.feval(1, "test_return", value) - class1, = pytave.feval(1, "class", value) - class1 = class1.tostring() - class2, = pytave.feval(1, "class", nvalue) - class2 = class2.tostring() - if not equals(value, nvalue): - fail("as %s != %s" % (value, nvalue)) - if value.shape != nvalue.shape: - fail("Size check failed for: %s. Expected shape %s, got %s with shape %s" \ - %(value, value.shape, nvalue, nvalue.shape)) - if class1 != class2: - fail( "Type check failed for: %s. Expected %s. Got %s." - %(value, class1, class2)) - except TypeError, e: - fail("Execute failed: %s" % value, e) + try: + nvalue, = pytave.feval(1, "test_return", value) + class1, = pytave.feval(1, "class", value) + class1 = class1.tostring() + class2, = pytave.feval(1, "class", nvalue) + class2 = class2.tostring() + if not equals(value, nvalue): + fail("as %s != %s" % (value, nvalue)) + if value.shape != nvalue.shape: + fail("Size check failed for: %s. Expected shape %s, got %s with shape %s" + % (value, value.shape, nvalue, nvalue.shape)) + if class1 != class2: + fail("Type check failed for: %s. Expected %s. Got %s." + % (value, class1, class2)) + except TypeError, e: + fail("Execute failed: %s" % value, e) + def testobjecterror(value): - try: - pytave.feval(1, "test_return", value); - print "FAIL:", (value,) - except pytave.ObjectConvertError: - pass - except Exception, e: - print "FAIL", (value,), e + try: + pytave.feval(1, "test_return", value) + print "FAIL:", (value,) + except pytave.ObjectConvertError: + pass + except Exception, e: + print "FAIL", (value,), e + def testvalueerror(*value): - try: - pytave.feval(1, *value); - fail(value) - except pytave.ValueConvertError: - pass - except Exception, e: - fail(value, e) + try: + pytave.feval(1, *value) + fail(value) + except pytave.ValueConvertError: + pass + except Exception, e: + fail(value, e) + def testparseerror(*value): - try: - pytave.eval(*value); - print "FAIL:", (value,) - except pytave.ParseError: - pass - except Exception, e: - print "FAIL", (value,), e + try: + pytave.eval(*value) + print "FAIL:", (value,) + except pytave.ParseError: + pass + except Exception, e: + print "FAIL", (value,), e + def testvalueok(*value): - try: - pytave.feval(1, *value); - except Exception, e: - print "FAIL", (value,), e + try: + pytave.feval(1, *value) + except Exception, e: + print "FAIL", (value,), e + def testevalexpect(numargout, code, expectations): - try: - results = pytave.eval(numargout, code); - if not equals(results, expectations): - fail("eval: %s : because %s != %s" % (code, results, expectations)) - except Exception, e: - fail("eval: %s" % code, e) + try: + results = pytave.eval(numargout, code) + if not equals(results, expectations): + fail("eval: %s : because %s != %s" % (code, results, expectations)) + except Exception, e: + fail("eval: %s" % code, e) + def testsetget(variables, name, value): - try: - variables[name] = value - if name not in variables: - fail("set/get: %s: Should exist, not there." % name) - result, = pytave.feval(1, "isequal", value, variables[name]) - if not result: - fail("set/get: %s -> %s: results diverged" % (name, value)) - except Exception, e: - fail("set/get: %s" % name, e) + try: + variables[name] = value + if name not in variables: + fail("set/get: %s: Should exist, not there." % name) + result, = pytave.feval(1, "isequal", value, variables[name]) + if not result: + fail("set/get: %s -> %s: results diverged" % (name, value)) + except Exception, e: + fail("set/get: %s" % name, e) + def testexception(exception, func): - try: - func() - fail("Expecting %s but nothing was raised." % repr(exception)) - except Exception, e: - if not isinstance(e, exception): - fail("Expecting %s but got %s instead" % (repr(exception), repr(e)), e) + try: + func() + fail("Expecting %s but nothing was raised." % repr(exception)) + except Exception, e: + if not isinstance(e, exception): + fail("Expecting %s but got %s instead" % (repr(exception), repr(e)), e) + def testlocalscope(x): @pytave.local_scope def sloppy_factorial(x): - pytave.locals["x"] = x - xm1, = pytave.eval(1,"x-1") - xm1 = xm1[0][0] - if xm1 > 0: - fxm1 = sloppy_factorial(xm1) - else: - fxm1 = 1 - pytave.locals["fxm1"] = fxm1 - fx, = pytave.eval(1,"x * fxm1") - fx = fx[0][0] - return fx + pytave.locals["x"] = x + xm1, = pytave.eval(1, "x - 1") + xm1 = xm1[0][0] + if xm1 > 0: + fxm1 = sloppy_factorial(xm1) + else: + fxm1 = 1 + pytave.locals["fxm1"] = fxm1 + fx, = pytave.eval(1, "x * fxm1") + fx = fx[0][0] + return fx try: - fx = sloppy_factorial(x) - fx1 = 1.0 - for k in range(1,x+1): - fx1 = k * fx1 - if fx != fx1: - fail('testlocalscope: result incorrect') + fx = sloppy_factorial(x) + fx1 = 1.0 + for k in range(1, x + 1): + fx1 = k * fx1 + if fx != fx1: + fail("testlocalscope: result incorrect") except Exception, e: - fail("testlocalscope: %s" % (x,), e) + fail("testlocalscope: %s" % (x,), e) + def objarray(obj): - return numpy.array(obj,numpy.object) + return numpy.array(obj, numpy.object) + def charray(obj): - return numpy.array(obj,numpy.character) + return numpy.array(obj, numpy.character) testmatrix(alimit_int64) @@ -186,12 +203,12 @@ # Strings -#FIXME: These tests are not working. -#testequal(["mystring"]) -#testequal(["mystringåäöÅÄÖ"]) +# FIXME: These tests are not working. +# testequal(["mystring"]) +# testequal(["mystringåäöÅÄÖ"]) -testexpect(1,numpy.array([[1]],numpy.int)) -testexpect(1.0,numpy.array([[1]],numpy.float)) +testexpect(1, numpy.array([[1]], numpy.int)) +testexpect(1.0, numpy.array([[1]], numpy.float)) # Vector arrays testmatrix(arr1a) @@ -212,18 +229,18 @@ # Note, both arr0_0 == arr0_0 and arr0_0 != arr0_0 are false! if (arr0_0 != arr0_0) or (arr0_0 == arr0_0): - print "FAIL: Zero test", + print "FAIL: Zero test" testmatrix(arr0_0) testmatrix(arr0_1) testmatrix(arr1_0) # Lists -testexpect([1, 2],objarray([[1,2]])) -testexpect([],objarray([[]])) +testexpect([1, 2], objarray([[1, 2]])) +testexpect([], objarray([[]])) # Return cells with OK dimensions -testvalueok("cell", 1, 3); +testvalueok("cell", 1, 3) testvalueok("cell", 1, 0) testvalueok("cell", 0, 0) testvalueok("cell", 3, 1) @@ -234,17 +251,17 @@ # Simple dictionary tests testexpect({"foo": 1, "bar": 2}, - {"foo": objarray([[1]]), "bar": objarray([[2]])}) -#testexpect({"x": [1, 3], "y": [2, 4]}, -# {"x": objarray([[1,3]]), "y": objarray([[2,4]])}) + {"foo": objarray([[1]]), "bar": objarray([[2]])}) +# testexpect({"x": [1, 3], "y": [2, 4]}, +# {"x": objarray([[1, 3]]), "y": objarray([[2, 4]])}) # just constructing the second value with Numeric 24.2! -#testexpect({"x": [1, "baz"], "y": [2, "foobar"]}, -# {"x": objarray([[1, charray(["baz"])]]), -# "y": objarray([[2, charray(["foobar"])]])}) +# testexpect({"x": [1, "baz"], "y": [2, "foobar"]}, +# {"x": objarray([[1, charray(["baz"])]]), +# "y": objarray([[2, charray(["foobar"])]])}) testequal({"x": objarray([[arr1f]]), "y": objarray([[arr1i]])}) testequal({}) -testequal({"foo": arr2o, "bar": arr2o}) +testequal({"foo": arr2o, "bar": arr2o}) # Try some invalid keys testobjecterror({"this is not an Octave identifier": 1}) @@ -252,41 +269,45 @@ # These should fail: No object conversion defined. testobjecterror(None) -testobjecterror((1, )) +testobjecterror((1,)) testobjecterror(()) result, = pytave.feval(1, "eval", "[1, 1, 1]") -if result.shape != (1,3): - print "FAIL: expected length-3 vector" +if result.shape != (1, 3): + print "FAIL: expected length-3 vector" -result, = pytave.feval(1, "eval", "[1; 2; 3]"); +result, = pytave.feval(1, "eval", "[1; 2; 3]") if result.shape != (3, 1): - print "FAIL: expected 3x1 matrix" + print "FAIL: expected 3x1 matrix" testparseerror(1, "endfunction") testevalexpect(1, "2 + 2", (4,)) testevalexpect(1, "{2}", (objarray([[2]]),)) -testevalexpect(1, "struct('foo', 2)", ({'foo': objarray([[2]])},)) +testevalexpect(1, "struct('foo', 2)", ({"foo": objarray([[2]])},)) testsetget(pytave.locals, "xxx", arr1f) testsetget(pytave.globals, "xxx", arr2o) + def func(): - pytave.locals["this is not a valid Octave identifier"] = 1 + pytave.locals["this is not a valid Octave identifier"] = 1 testexception(pytave.VarNameError, func) + def func(): - pytave.locals["nonexistentvariable"] + pytave.locals["nonexistentvariable"] testexception(KeyError, func) + def func(key): - pytave.locals[key] = 1 + pytave.locals[key] = 1 testexception(TypeError, lambda: func(0.1)) testexception(TypeError, lambda: func(1)) testexception(TypeError, lambda: func([])) + def func(key): - pytave.locals[key] + pytave.locals[key] testexception(TypeError, lambda: func(0.1)) testexception(TypeError, lambda: func(1)) testexception(TypeError, lambda: func([])) @@ -296,23 +317,27 @@ testexception(KeyError, lambda: pytave.locals["localvariable"]) pytave.locals["localvariable"] = 1 if "localvariable" in pytave.globals: - fail("Local variable in globals") + fail("Local variable in globals") del pytave.locals["localvariable"] if "localvariable" in pytave.locals: - fail("Could not clear local variable") + fail("Could not clear local variable") testexception(KeyError, lambda: pytave.locals["localvariable"]) + + def func(): - del pytave.locals["localvariable"] + del pytave.locals["localvariable"] testexception(KeyError, lambda: func()) testexception(KeyError, lambda: pytave.globals["globalvariable"]) pytave.globals["globalvariable"] = 1 if "globalvariable" in pytave.locals: - fail("Global variable in locals") + fail("Global variable in locals") del pytave.globals["globalvariable"] if "globalvariable" in pytave.globals: - fail("Could not clear global variable") + fail("Could not clear global variable") testexception(KeyError, lambda: pytave.globals["globalvariable"]) + + def func(): - del pytave.globals["globalvariable"] + del pytave.globals["globalvariable"] testexception(KeyError, lambda: func())