# HG changeset patch # User Mike Miller # Date 1471148669 25200 # Node ID 15c20ab4b80ac3d3759b422d27a2ba1f653dd8e8 # Parent 37df9bd607edd4f3e7e0face9153f7a860b19259 Do not automatically convert Python integer types to Octave (see issue #56) * python_to_octave.cc (pytave::pyobj_to_octvalue): Drop automatic conversion of Python int and long types to Octave. * @pyobject/pyobject.m (pyobject.length, pyobject.size): Cast values to double. Adapt %!tests to changes. * @pyobject/cell.m, @pyobject/dummy.m, @pyobject/subsasgn.m, @pyobject/subsref.m, pycall.cc, pyeval.cc: Adapt usage examples and %!tests to changes. diff -r 37df9bd607ed -r 15c20ab4b80a @pyobject/cell.m --- a/@pyobject/cell.m Sat Aug 13 19:57:49 2016 -0700 +++ b/@pyobject/cell.m Sat Aug 13 21:24:29 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")) diff -r 37df9bd607ed -r 15c20ab4b80a @pyobject/dummy.m --- a/@pyobject/dummy.m Sat Aug 13 19:57:49 2016 -0700 +++ b/@pyobject/dummy.m Sat Aug 13 21:24:29 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', ] +## [42.0, 'hello', ] ## @end group ## @end example ## diff -r 37df9bd607ed -r 15c20ab4b80a @pyobject/pyobject.m --- a/@pyobject/pyobject.m Sat Aug 13 19:57:49 2016 -0700 +++ b/@pyobject/pyobject.m Sat Aug 13 21:24:29 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)]; @@ -254,15 +254,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)") diff -r 37df9bd607ed -r 15c20ab4b80a @pyobject/subsasgn.m --- a/@pyobject/subsasgn.m Sat Aug 13 19:57:49 2016 -0700 +++ b/@pyobject/subsasgn.m Sat Aug 13 21:24:29 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) diff -r 37df9bd607ed -r 15c20ab4b80a @pyobject/subsref.m --- a/@pyobject/subsref.m Sat Aug 13 19:57:49 2016 -0700 +++ b/@pyobject/subsref.m Sat Aug 13 21:24:29 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) diff -r 37df9bd607ed -r 15c20ab4b80a pycall.cc --- a/pycall.cc Sat Aug 13 19:57:49 2016 -0700 +++ b/pycall.cc Sat Aug 13 21:24:29 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")) @@ -225,9 +225,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 %! pyexec ("def raiseException(): raise NameError('oops')") diff -r 37df9bd607ed -r 15c20ab4b80a pyeval.cc --- a/pyeval.cc Sat Aug 13 19:57:49 2016 -0700 +++ b/pyeval.cc Sat Aug 13 21:24:29 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 %! 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 @@ -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 diff -r 37df9bd607ed -r 15c20ab4b80a python_to_octave.cc --- a/python_to_octave.cc Sat Aug 13 19:57:49 2016 -0700 +++ b/python_to_octave.cc Sat Aug 13 21:24:29 2016 -0700 @@ -338,19 +338,16 @@ void pyobj_to_octvalue (octave_value& oct_value, const boost::python::object& py_object) { - extract longx (py_object); extract boolx (py_object); extract doublex (py_object); extract complexx (py_object); extract arrayx (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 ()) + 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 ());