Mercurial > pytave
changeset 328:5782d7932529
Automatically convert Python 2 'int' type to Octave int64 (fixes issue #56)
* oct-py-types.cc, oct-py-types.h (pytave::extract_py_int64): New function.
* python_to_octave.cc (pytave::pyobj_to_octvalue): Convert Python 2 'int' to
Octave int64 type.
* @py/py.m, pycall.cc: Add %!tests for Python 'int' and 'long' type handling,
conditional on Python version.
author | Mike Miller <mtmiller@octave.org> |
---|---|
date | Sat, 13 Aug 2016 23:52:57 -0700 |
parents | 15c20ab4b80a |
children | 5c63651b0ec4 |
files | @py/py.m oct-py-types.cc oct-py-types.h pycall.cc python_to_octave.cc |
diffstat | 5 files changed, 71 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/@py/py.m Sat Aug 13 21:24:29 2016 -0700 +++ b/@py/py.m Sat Aug 13 23:52:57 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/oct-py-types.cc Sat Aug 13 21:24:29 2016 -0700 +++ b/oct-py-types.cc Sat Aug 13 23:52:57 2016 -0700 @@ -68,6 +68,24 @@ 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) {
--- a/oct-py-types.h Sat Aug 13 21:24:29 2016 -0700 +++ b/oct-py-types.h Sat Aug 13 23:52:57 2016 -0700 @@ -34,6 +34,9 @@ PyObject * make_py_dict (const octave_scalar_map& map); +int64_t +extract_py_int64 (PyObject *obj); + std::string extract_py_str (PyObject *obj);
--- a/pycall.cc Sat Aug 13 21:24:29 2016 -0700 +++ b/pycall.cc Sat Aug 13 23:52:57 2016 -0700 @@ -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]);
--- a/python_to_octave.cc Sat Aug 13 21:24:29 2016 -0700 +++ b/python_to_octave.cc Sat Aug 13 23:52:57 2016 -0700 @@ -345,6 +345,10 @@ if (PyBool_Check (py_object.ptr ())) oct_value = boolx (); +#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 (PyComplex_Check (py_object.ptr ()))