# HG changeset patch # User Mike Miller # Date 1471157577 25200 # Node ID 5782d793252961f23264e2cda75c2ced2efd8259 # Parent 15c20ab4b80ac3d3759b422d27a2ba1f653dd8e8 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. diff -r 15c20ab4b80a -r 5782d7932529 @py/py.m --- 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 diff -r 15c20ab4b80a -r 5782d7932529 oct-py-types.cc --- 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) { diff -r 15c20ab4b80a -r 5782d7932529 oct-py-types.h --- 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); diff -r 15c20ab4b80a -r 5782d7932529 pycall.cc --- 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]); diff -r 15c20ab4b80a -r 5782d7932529 python_to_octave.cc --- 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 ()))