Mercurial > pytave
changeset 330:5c63651b0ec4
Merged in genuinelucifer/pytave_main (pull request #40)
Add isequal method to allow comparing pyobjects (fixes issue #53)
author | Mike Miller <mtmiller@octave.org> |
---|---|
date | Sat, 13 Aug 2016 23:59:49 -0700 |
parents | 5782d7932529 (diff) 778c91283a73 (current diff) |
children | cee203ea6245 |
files | @pyobject/pyobject.m |
diffstat | 12 files changed, 197 insertions(+), 307 deletions(-) [+] |
line wrap: on
line diff
--- a/@py/py.m Fri Aug 12 05:45:06 2016 -0700 +++ b/@py/py.m Sat Aug 13 23:59:49 2016 -0700 @@ -28,3 +28,27 @@ %!assert (py.math.sqrt (2), sqrt (2)) %!assert (ischar (py.sys.version)) + +%!test +%! if (double (py.sys.hexversion) >= 0x03000000) +%! assert (isobject (py.int (0))) +%! else +%! assert (py.int (0), int64 (0)) +%! endif + +%!test +%! if (double (py.sys.hexversion) < 0x03000000) +%! assert (py.int (2147483647), int64 (2147483647)) +%! endif + +%!test +%! if (double (py.sys.hexversion) < 0x03000000) +%! assert (isobject (py.long (0))) +%! endif + +%!test +%! if (double (py.sys.hexversion) >= 0x03000000) +%! assert (isobject (py.int (2^100))) +%! else +%! assert (isobject (py.long (2^100))) +%! endif
--- a/@pyobject/cell.m Fri Aug 12 05:45:06 2016 -0700 +++ b/@pyobject/cell.m Sat Aug 13 23:59:49 2016 -0700 @@ -27,10 +27,10 @@ ## converted into native Octave objects: ## @example ## @group -## L = pyeval ("[10, 20, 'hello']") +## L = pyeval ("[10.0, 20.0, 'hello']") ## @result{} L = [pyobject ...] ## -## [10, 20, 'hello'] +## [10.0, 20.0, 'hello'] ## @end group ## @end example ## @@ -50,7 +50,7 @@ ## The conversion is not recursive, in the following sense: ## @example ## @group -## L = pyeval ("[10, 20, [33, 44], 50]"); +## L = pyeval ("[10.0, 20.0, [33.0, 44.0], 50.0]"); ## C = cell (L) ## @result{} C = ## @{ @@ -58,7 +58,7 @@ ## [1,2] = 20 ## = [pyobject ...] ## -## [33, 44] +## [33.0, 44.0] ## ## [1,4] = 50 ## @} @@ -81,11 +81,15 @@ %!assert (cell (pyeval ("[]")), cell (1, 0)) -%!assert (cell (pyeval ("[1]")), {1}) -%!assert (cell (pyeval ("[1, 2, 3]")), {1, 2, 3}) -%!assert (cell (pyeval ("(1, 2, 3)")), {1, 2, 3}) +%!assert (cell (pyeval ("[1.]")), {1}) +%!assert (cell (pyeval ("[1., 2., 3.]")), {1, 2, 3}) +%!assert (cell (pyeval ("(1., 2., 3.)")), {1, 2, 3}) %!assert (cell (pyobject ("asdf")), {"a", "s", "d", "f"}) -%!assert (cell (pyeval ("range(10)")), num2cell (0:9)) + +%!test +%! c = cell (pyeval ("range(10)")); +%! c = cellfun (@(x) eval ("double (x)"), c, "uniformoutput", false); +%! assert (c, num2cell (0:9)) %!error cell (pyobject ()) %!error cell (pyeval ("None"))
--- a/@pyobject/dummy.m Fri Aug 12 05:45:06 2016 -0700 +++ b/@pyobject/dummy.m Sat Aug 13 23:59:49 2016 -0700 @@ -25,7 +25,7 @@ ## Some simple Python objects are converted to equivalent Octave values: ## @example ## @group -## pyeval ("6") +## pyeval ("6.0") ## @result{} ans = 6 ## @end group ## @end example @@ -54,9 +54,9 @@ ## [4,1] = real ## @} ## -## g.numerator +## double (g.numerator) ## @result{} ans = 6 -## g.denominator +## double (g.denominator) ## @result{} ans = 1 ## @end group ## @end example @@ -83,7 +83,7 @@ ## We can accesss ``callables'' (methods) of objects: ## @example ## @group -## x.pop ("two") +## double (x.pop ("two")) ## @result{} ans = 2 ## @end group ## @end example @@ -120,9 +120,9 @@ ## A Python list is returned as a @@pyobject: ## @example ## @group -## L = pyeval ("[42, 'hello', sys]") +## L = pyeval ("[42.0, 'hello', sys]") ## @result{} L = [pyobject ...] -## [42, 'hello', <module 'sys' (built-in)>] +## [42.0, 'hello', <module 'sys' (built-in)>] ## @end group ## @end example ##
--- a/@pyobject/pyobject.m Fri Aug 12 05:45:06 2016 -0700 +++ b/@pyobject/pyobject.m Sat Aug 13 23:59:49 2016 -0700 @@ -151,7 +151,7 @@ function len = length (x) try - len = pycall ("len", x); + len = double (pycall ("len", x)); catch len = 1; end_try_catch @@ -163,7 +163,7 @@ try idx = struct ("type", ".", "subs", "shape"); sz = subsref (x, idx); - sz = cell2mat (cell (sz)); + sz = cellfun (@(x) eval ("double (x)"), cell (sz)); catch ## if it had no shape, make it a row vector sz = [1 length(x)]; @@ -265,15 +265,15 @@ %!test %! L = pyeval ("[10, 20, 30]"); -%! assert (L{end}, 30) -%! assert (L{end-1}, 20) +%! assert (double (L{end}), 30) +%! assert (double (L{end-1}), 20) %!test %! % ensure "end" works for iterables that are not lists %! myrange = pyeval ( ... %! "range if __import__('sys').hexversion >= 0x03000000 else xrange"); %! R = pycall (myrange, int32 (5), int32 (10), int32 (2)); -%! assert (R{end}, 9) +%! assert (double (R{end}), 9) %!shared a %! pyexec ("class _myclass(): shape = (3, 4, 5)")
--- a/@pyobject/subsasgn.m Fri Aug 12 05:45:06 2016 -0700 +++ b/@pyobject/subsasgn.m Sat Aug 13 23:59:49 2016 -0700 @@ -88,7 +88,7 @@ %!test %! % list indexing -%! L = pyeval ("[10, 20]"); +%! L = pyeval ("[10., 20.]"); %! L{2} = "Octave"; %! assert (length (L) == 2) %! assert (L{1}, 10)
--- a/@pyobject/subsref.m Fri Aug 12 05:45:06 2016 -0700 +++ b/@pyobject/subsref.m Sat Aug 13 23:59:49 2016 -0700 @@ -114,13 +114,13 @@ %!test %! % list indexing -%! L = pyeval ("[10, 20]"); +%! L = pyeval ("[10., 20.]"); %! assert (L{1}, 10) %! assert (L{2}, 20) %!test %! % list indexing, slice -%! L = pyeval ("[10, 20, [30, 40]]"); +%! L = pyeval ("[10., 20., [30., 40.]]"); %! L2 = L{:}; %! assert (L2{1}, 10) %! assert (L2{2}, 20) @@ -129,14 +129,14 @@ %!test %! % list indexing, nested list -%! L = pyeval ("[1, 2, [10, 11, 12]]"); +%! L = pyeval ("[1., 2., [10., 11., 12.]]"); %! assert (L{2}, 2) %! assert (L{3}{1}, 10) %! assert (L{3}{3}, 12) %!test %! % list indexing, assign to vars -%! L = pyeval ("[1, 2, 'Octave']"); +%! L = pyeval ("[1., 2., 'Octave']"); %! [a, b, c] = L{:}; %! assert (a, 1) %! assert (b, 2) @@ -144,7 +144,7 @@ %!test %! % 2D array indexing -%! A = pyobject ([1 2; 3 4]); +%! A = pyobject ([1. 2.; 3. 4.]); %! assert (A{1, 1}, 1) %! assert (A{2, 1}, 3) %! assert (A{1, 2}, 2) @@ -158,17 +158,17 @@ %!test %! % dict: str key access -%! d = pyeval ("{'one':1, 5:5, 6:6}"); +%! d = pyeval ("{'one':1., 5:5, 6:6}"); %! assert (d{"one"}, 1) %!test %! % dict: integer key access -%! d = pyeval ("{5:42, 6:42}"); +%! d = pyeval ("{5:42., 6:42.}"); %! assert (d{6}, 42) %!test %! % dict: integer key should not subtract one -%! d = pyeval ("{5:40, 6:42}"); +%! d = pyeval ("{5:40., 6:42.}"); %! assert (d{6}, 42) %!test @@ -178,7 +178,7 @@ %!test %! % dict: make sure key ":" doesn't break anything -%! d = pyeval ("{'a':1, ':':2}"); +%! d = pyeval ("{'a':1., ':':2.}"); %! assert (d{'a'}, 1) %! assert (d{':'}, 2) @@ -199,7 +199,7 @@ %!test %! % callable can return something -%! s = pyeval ("set({1, 2})"); +%! s = pyeval ("set({1., 2.})"); %! v = s.pop (); %! assert (length (s) == 1) %! assert (v == 1 || v == 2) @@ -235,7 +235,7 @@ %!test %! % multiple return values: separate them -%! f = pyeval ("lambda: (1, 2, 3)"); +%! f = pyeval ("lambda: (1., 2., 3.)"); %! [a, b, c] = f (); %! assert (a, 1) %! assert (b, 2)
--- a/oct-py-types.cc Fri Aug 12 05:45:06 2016 -0700 +++ b/oct-py-types.cc Sat Aug 13 23:59:49 2016 -0700 @@ -27,6 +27,7 @@ #include <octave/oct-map.h> #include <octave/quit.h> +#include "exceptions.h" #include "oct-py-types.h" // FIXME: only here to bootstrap nested conversions needed in this file @@ -54,7 +55,10 @@ for (auto p = map.begin (); p != map.end (); ++p) { - PyObject *key = wrap_octvalue_to_pyobj (map.key (p)); + PyObject *key = make_py_str (map.key (p)); + if (! key) + octave_throw_bad_alloc (); + PyObject *item = wrap_octvalue_to_pyobj (map.contents (p)); if (PyDict_SetItem (dict, key, item) < 0) @@ -64,4 +68,65 @@ return dict; } +int64_t +extract_py_int64 (PyObject *obj) +{ + if (! obj) + throw object_convert_exception ("failed to extract integer: null object"); + + if (PyLong_Check (obj)) + return PyLong_AsLong (obj); +#if PY_VERSION_HEX < 0x03000000 + else if (PyInt_Check (obj)) + return PyInt_AsLong (obj); +#endif + else + throw object_convert_exception ("failed to extract integer: wrong type"); + + return 0; } + +std::string +extract_py_str (PyObject *obj) +{ + std::string retval; + + if (! obj) + throw object_convert_exception ("failed to extract string: null object"); + if (PyBytes_Check (obj)) + { + retval.assign (PyBytes_AsString (obj), PyBytes_Size (obj)); + } + else if (PyUnicode_Check (obj)) + { + bool ok = false; + PyObject *enc = PyUnicode_AsUTF8String (obj); + if (enc) + { + if (PyBytes_Check (enc)) + { + ok = true; + retval.assign (PyBytes_AsString (enc), PyBytes_Size (enc)); + } + Py_DECREF (enc); + } + if (! ok) + throw object_convert_exception ("failed to extract string: UTF-8 error"); + } + else + throw object_convert_exception ("failed to extract string: wrong type"); + + return retval; +} + +PyObject * +make_py_str (const std::string& str) +{ +#if PY_VERSION_HEX >= 0x03000000 + return PyUnicode_FromStringAndSize (str.data (), str.size ()); +#else + return PyString_FromStringAndSize (str.data (), str.size ()); +#endif +} + +}
--- a/oct-py-types.h Fri Aug 12 05:45:06 2016 -0700 +++ b/oct-py-types.h Sat Aug 13 23:59:49 2016 -0700 @@ -24,6 +24,7 @@ #define pytave_oct_py_types_h 1 #include <Python.h> +#include <string> class octave_scalar_map; @@ -33,6 +34,15 @@ PyObject * make_py_dict (const octave_scalar_map& map); +int64_t +extract_py_int64 (PyObject *obj); + +std::string +extract_py_str (PyObject *obj); + +PyObject * +make_py_str (const std::string& str); + } #endif
--- a/octave_to_python.cc Fri Aug 12 05:45:06 2016 -0700 +++ b/octave_to_python.cc Sat Aug 13 23:59:49 2016 -0700 @@ -76,43 +76,6 @@ } } - 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*) 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 ()); - *(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<PyObject *, Cell> ( - 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) { @@ -214,22 +177,6 @@ py_object = sequence; } - 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; - } - } - inline PyObject * python_integer_value (int32_t value) { @@ -305,19 +252,6 @@ throw value_convert_exception ("unhandled scalar type"); } - static void - octstring_to_pyobject (boost::python::object& py_object, - const std::string& str) - { - py_object = object (handle<PyObject> ( -#if PY_VERSION_HEX >= 0x03000000 - PyUnicode_FromStringAndSize (str.data (), str.size ()) -#else - PyString_FromStringAndSize (str.data (), str.size ()) -#endif - )); - } - void octvalue_to_pyobj (boost::python::object& py_object, const octave_value& octvalue) { @@ -325,7 +259,10 @@ throw value_convert_exception ( "Octave value `undefined'. Can not convert to a Python object"); else if (octvalue.is_string ()) - octstring_to_pyobject (py_object, octvalue.string_value ()); + { + PyObject *obj = make_py_str (octvalue.string_value ()); + py_object = object (handle<PyObject> (obj)); + } else if (octvalue.is_scalar_type ()) octscalar_to_pyobject (py_object, octvalue); else if (octvalue.is_cell ())
--- a/pycall.cc Fri Aug 12 05:45:06 2016 -0700 +++ b/pycall.cc Sat Aug 13 23:59:49 2016 -0700 @@ -49,7 +49,7 @@ Examples:\n\ @example\n\ @group\n\ -pycall (\"int\", 6)\n\ +pycall (\"float\", 6)\n\ @result{} 6\n\ pycall (\"os.getuid\")\n\ @result{} ...\n\ @@ -142,11 +142,11 @@ /* %!assert (ischar (pycall ("os.getcwd"))) %!assert (isreal (pycall ("random.random"))) -%!assert (pycall ("math.exp", 3), exp (3)) -%!assert (pycall ("math.trunc", pi), fix (pi)) -%!assert (pycall ("math.sqrt", 2), sqrt (2)) -%!assert (pycall ("cmath.sqrt", 2j), sqrt (2j)) -%!assert (pycall ("int", 10.2), 10) +%!assert (double (pycall ("math.exp", 3)), exp (3)) +%!assert (double (pycall ("math.trunc", pi)), fix (pi)) +%!assert (double (pycall ("math.sqrt", 2)), sqrt (2)) +%!assert (double (pycall ("cmath.sqrt", 2j)), sqrt (2j)) +%!assert (double (pycall ("int", 10.2)), 10) %!assert (isa (pycall ("object"), "pyobject")) %!assert (isa (pycall ("dict"), "pyobject")) %!assert (isa (pycall ("list"), "pyobject")) @@ -215,6 +215,28 @@ %! pyexec ("def intwrapper(x): return int(x)"); %! pycall ("intwrapper", ftp ()); +## Test conversion of integer types from Python +%!test +%! if (pyeval ("__import__('sys').hexversion >= 0x03000000")) +%! assert (isa (pycall ("int", 0), "pyobject")) +%! assert (isa (pycall ("int", 2^31-1), "pyobject")) +%! assert (isa (pycall ("int", -2^31), "pyobject")) +%! assert (double (pycall ("int", 0)), 0) +%! assert (double (pycall ("int", 2^31-1)), 2^31-1) +%! assert (double (pycall ("int", -2^31)), -2^31) +%! else +%! assert (pycall ("int", 0), int64 (0)) +%! assert (pycall ("int", 2^31-1), int64 (2^31-1)) +%! assert (pycall ("int", -2^31), int64 (-2^31)) +%! assert (isa (pycall ("long", 0), "pyobject")) +%! assert (isa (pycall ("long", 2^31-1), "pyobject")) +%! assert (isa (pycall ("long", -2^31), "pyobject")) +%! assert (double (pycall ("long", 0)), 0) +%! assert (double (pycall ("long", 2^31-1)), 2^31-1) +%! assert (double (pycall ("long", -2^31)), -2^31) +%! endif +%!assert (isa (pycall ("int", 2^100), "pyobject")) + %!test %! pyexec ("def pyfunc(x): return 2*x"); %! z = pycall ("pyfunc", [20 20]); @@ -225,9 +247,9 @@ %! " if x is True:\n return 30\n" ... %! " elif x is False:\n return 20\n" ... %! " else:\n return 10"]); -%! assert (pycall ("pyfunc", true), 30) -%! assert (pycall ("pyfunc", false), 20) -%! assert (pycall ("pyfunc", 10), 10) +%! assert (double (pycall ("pyfunc", true)), 30) +%! assert (double (pycall ("pyfunc", false)), 20) +%! assert (double (pycall ("pyfunc", 10)), 10) %!error <NameError> %! pyexec ("def raiseException(): raise NameError('oops')")
--- a/pyeval.cc Fri Aug 12 05:45:06 2016 -0700 +++ b/pyeval.cc Sat Aug 13 23:59:49 2016 -0700 @@ -118,9 +118,9 @@ } /* -%!assert (isnumeric (pyeval ("0"))) -%!assert (isreal (pyeval ("0"))) -%!assert (pyeval ("0"), 0) +%!assert (isnumeric (double (pyeval ("0")))) +%!assert (isreal (double (pyeval ("0")))) +%!assert (double (pyeval ("0")), 0) %!assert (isnumeric (pyeval ("10.1"))) %!assert (isreal (pyeval ("10.1"))) @@ -142,27 +142,27 @@ %!assert (isa (pyeval ("object()"), "pyobject")) -%!assert (isnumeric (pyeval ("__import__('sys').maxsize"))) -%!assert (pyeval ("99999999999999"), 99999999999999) -%!assert (pyeval ("-99999999999999"), -99999999999999) +%!assert (isnumeric (double (pyeval ("__import__('sys').maxsize")))) +%!assert (double (pyeval ("99999999999999")), 99999999999999) +%!assert (double (pyeval ("-99999999999999")), -99999999999999) %!test -%! z = pyeval ("{'x': 1, 'y': 2}"); +%! z = pyeval ("{'x': 1., 'y': 2.}"); %! assert (isa (z, "pyobject")) %! assert (z{"x"}, 1) %!test -%! z = pyeval ("[1, 2, 3]"); +%! z = pyeval ("[1., 2., 3.]"); %! assert (isa (z, "pyobject")) %! assert ({z{1}, z{2}, z{3}}, {1, 2, 3}) %!test -%! z = pyeval ("(4, 5, 6)"); +%! z = pyeval ("(4., 5., 6.)"); %! assert (isa (z, "pyobject")) %! assert ({z{1}, z{2}, z{3}}, {4, 5, 6}) %!test -%! z = pyeval ("[1, [21, 22], 3, [41, [421, 422], 43]]"); +%! z = pyeval ("[1., [21., 22.], 3., [41., [421., 422.], 43.]]"); %! assert (isa (z, "pyobject")) %! assert (isa (z{2}, "pyobject")) %! assert (z{2}{1}, 21) @@ -178,16 +178,16 @@ %!test %! % Variable defined in global namespace is available locally %! myNS = pyeval ("{}"); -%! pyexec ("myvar = 1") +%! pyexec ("myvar = 1.") %! assert (pyeval ("myvar", myNS), 1); %!test %! % Variables with same name can have different values in different namespaces %! myNS1 = pyeval ("{}"); %! myNS2 = pyeval ("{}"); -%! pyexec ("myvar = 1") -%! pyexec ("myvar = 2", myNS1) -%! pyexec ("myvar = 3", myNS2) +%! pyexec ("myvar = 1.") +%! pyexec ("myvar = 2.", myNS1) +%! pyexec ("myvar = 3.", myNS2) %! assert (pyeval ("myvar"), 1) %! assert (pyeval ("myvar", myNS1), 2) %! assert (pyeval ("myvar", myNS2), 3) @@ -196,14 +196,14 @@ %! pyexec ("if 'myvar' in globals(): del myvar") %! % Namespaces can also be passed as strings %! pyexec ("myNS = {}"); -%! pyexec ("myvar = 1", "myNS"); +%! pyexec ("myvar = 1.", "myNS"); %! assert (pyeval ("myvar", "myNS"), 1); %!error <NameError> %! pyexec ("if 'myvar' in globals(): del myvar") %! % Variable defined in local namespace MUST not be available globally %! myNS = pyeval ("{}"); -%! pyexec ("myvar = 1", myNS) +%! pyexec ("myvar = 1.", myNS) %! pyeval ("myvar"); %!error <NameError> @@ -211,7 +211,7 @@ %! % Variable defined in one local namespace MUST not be available in another %! myNS1 = pyeval ("{}"); %! myNS2 = pyeval ("{}"); -%! pyexec ("myvar = 1", myNS1) +%! pyexec ("myvar = 1.", myNS1) %! pyeval ("myvar", myNS2); %!error <NameError>
--- a/python_to_octave.cc Fri Aug 12 05:45:06 2016 -0700 +++ b/python_to_octave.cc Sat Aug 13 23:59:49 2016 -0700 @@ -40,6 +40,7 @@ #include "arrayobjectdefs.h" #include "exceptions.h" +#include "oct-py-types.h" #include "python_to_octave.h" #include "pytave_utils.h" @@ -84,48 +85,6 @@ } } - template <> - void - copy_pyarrobj_to_octarray<PyObject *, Cell> (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<PyObject> (borrowed (pobj)))); - } - } - else if (PyArray_NDIM (pyarr) == 0) - { - PyObject *pobj = *(PyObject **) ptr; - pyobj_to_octvalue (matrix.elem (0), - object (handle<PyObject> (borrowed (pobj)))); - } - else - { - for (int i = 0; i < PyArray_DIM (pyarr, dimension); i++) - { - copy_pyarrobj_to_octarray<PyObject *, Cell> ( - matrix, - pyarr, - matindex + i*matstride, - matstride * PyArray_DIM (pyarr, dimension), - dimension + 1, - offset + i*PyArray_STRIDE (pyarr, dimension)); - } - } - } - template <class PythonPrimitive, class OctaveBase> static void copy_pyarrobj_to_octarray_dispatch (OctaveBase& matrix, @@ -217,7 +176,6 @@ ARRAYCASE (NPY_BOOL, bool) ARRAYCASE (NPY_CHAR, char) ARRAYCASE (NPY_STRING, char) - ARRAYCASE (NPY_OBJECT, PyObject *) default: throw object_convert_exception ( @@ -343,9 +301,6 @@ } } break; - case NPY_OBJECT: - pyarrobj_to_octvalueNd<Cell> (octvalue, pyarr, dims); - break; default: throw object_convert_exception ( PyEval_GetFuncDesc ((PyObject*)(pyarr)) + std::string (" ") @@ -356,127 +311,6 @@ } static void - pylist_to_cellarray (octave_value& oct_value, const boost::python::list& list) - { - octave_idx_type length = boost::python::extract<octave_idx_type> (list.attr ("__len__") ()); - octave_value_list values; - - for (octave_idx_type i = 0; i < length; i++) - { - octave_value val; - - pyobj_to_octvalue (val, list[i]); - values.append (val); - - } - - oct_value = Cell (values); - } - - static void - pytuple_to_cellarray (octave_value& oct_value, const boost::python::tuple& tuple) - { - octave_idx_type length = boost::python::extract<octave_idx_type> (tuple.attr ("__len__") ()); - octave_value_list values; - - for (octave_idx_type i = 0; i < length; i++) - { - octave_value val; - - pyobj_to_octvalue (val, tuple[i]); - values.append (val); - - } - - oct_value = Cell (values); - } - - 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<octave_idx_type> (list.attr ("__len__") ()); - - dim_vector dims = dim_vector (1, 1); - - octave_value_list vals (length); - string_vector 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]; - - boost::python::tuple tuple = - boost::python::extract<boost::python::tuple> (list[i]) (); - - boost::python::extract<std::string> 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 (); - - 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); - - 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"); - } - } - - 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); - - 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); - } - } - else - map.assign (key, Cell (dims, val)); - } - oct_value = map; - } - - static std::string - pyunicode_to_utf8 (PyObject *unicode) - { - std::string str; - PyObject *utf8 = PyUnicode_AsUTF8String (unicode); - str.assign (PyBytes_AsString (utf8), PyBytes_Size (utf8)); - Py_DECREF (utf8); - return str; - } - - static void pyobj_to_oct_pyobject (octave_value& oct_value, const boost::python::object& py_object) { @@ -504,31 +338,25 @@ void pyobj_to_octvalue (octave_value& oct_value, const boost::python::object& py_object) { - extract<long> longx (py_object); extract<bool> boolx (py_object); extract<double> doublex (py_object); extract<Complex> complexx (py_object); - extract<std::string> stringx (py_object); - extract<std::wstring> wstringx (py_object); extract<numeric::array> arrayx (py_object); - extract<boost::python::list> listx (py_object); - extract<boost::python::dict> dictx (py_object); - extract<boost::python::tuple> tuplex (py_object); - if (boolx.check () && PyBool_Check ((PyArrayObject*)py_object.ptr ())) + if (PyBool_Check (py_object.ptr ())) oct_value = boolx (); - else if (longx.check ()) - oct_value = longx (); - else if (doublex.check ()) +#if PY_VERSION_HEX < 0x03000000 + else if (PyInt_Check (py_object.ptr ())) + oct_value = octave_int64 (extract_py_int64 (py_object.ptr ())); +#endif + else if (PyFloat_Check (py_object.ptr ())) oct_value = doublex (); - else if (complexx.check ()) + else if (PyComplex_Check (py_object.ptr ())) 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 (wstringx.check ()) - oct_value = pyunicode_to_utf8 (py_object.ptr ()); + else if (PyBytes_Check (py_object.ptr ()) || PyUnicode_Check (py_object.ptr ())) + oct_value = extract_py_str (py_object.ptr ()); else pyobj_to_oct_pyobject (oct_value, py_object); }