# HG changeset patch # User Colin Macdonald # Date 1469728544 25200 # Node ID 4c4747646e12515b501e6c50b81400f1a0c383f8 # Parent 3bf799e80ca5110df2871bf955c8b6eda09a862f Make pyobject callable by users (to convert input) This makes "pyobject(...)" behave more a cast or typical constructor call. This should supercede the "fromPythonVarName" hack in some cases. * @pyobject/dummy.m: Use new pyobject call. * @pyobject/pyobject.m (@pyobject/pyobject): Redo ctor. * python_to_octave.cc: Use new pyobject ctor. diff -r 3bf799e80ca5 -r 4c4747646e12 @pyobject/dummy.m --- a/@pyobject/dummy.m Fri Jul 29 20:15:39 2016 -0700 +++ b/@pyobject/dummy.m Thu Jul 28 10:55:44 2016 -0700 @@ -25,8 +25,10 @@ ## Simple example: ## @example ## @group -## pyexec ("g = 6") -## g = pyobject.fromPythonVarName ("g"); +## g = pyobject (int32 (6)) +## @result{} g = [pyobject ...] +## +## 6 ## ## sort (methods (g)) ## @result{} ans = diff -r 3bf799e80ca5 -r 4c4747646e12 @pyobject/pyobject.m --- a/@pyobject/pyobject.m Fri Jul 29 20:15:39 2016 -0700 +++ b/@pyobject/pyobject.m Thu Jul 28 10:55:44 2016 -0700 @@ -52,16 +52,52 @@ pyvarname, pyvarname); pyexec (cmd); id = pyeval (["hex(id(" pyvarname "))"]); - x = pyobject (id); + x = pyobject (0, id); endfunction endmethods methods - function x = pyobject (id) - % warning: not intended for casual use: you must also insert - % the object into the Python `__InOct__` dict with key `id`. - x.id = id; + function obj = pyobject (x, id) + if (nargin == 0) + obj = pyeval ("None"); + return + endif + + if (nargin == 1) + ## Convert the input to a pyobject + if (isa (x, "pyobject")) + obj = x; + else + ## XXX: perhaps not the ideal implementation! + vars = pyeval ("__import__('__main__').__dict__"); + ## this is vars{"_temp"} = x + idx = struct ("type", "{}", "subs", {{"_temp"}}); + vars = subsasgn (vars, idx, x); + cmd = [ ... + "if not ('__InOct__' in vars() or '__InOct__' in globals()):\n" ... + " __InOct__ = dict()\n" ... + " # FIXME: make it accessible elsewhere?\n" ... + " import __main__\n" ... + " __main__.__InOct__ = __InOct__\n" ... + "__InOct__[hex(id(_temp))] = _temp" ]; + pyexec (cmd); + id = pyeval (["hex(id(_temp))"]); + obj = pyobject (0, id); + endif + return + endif + + if (nargin == 2) + ## The actual constructor. Nicer to split this off to static method + ## like `pyobject.new` but I don't know how to call from pycall.cc. + ## Warning: not intended for casual use: you must also insert the + ## object into the Python `__InOct__` dict with key `id`. + obj.id = id; + return + endif + + error ("pyobject: unexpected input to the constructor") endfunction function delete (x) @@ -154,3 +190,9 @@ %!assert (char (pyeval ("[1, 2, 3, 4, 5]")), "[1, 2, 3, 4, 5]") %!assert (char (pyeval ("(1, 2, 3, 4, 5)")), "(1, 2, 3, 4, 5)") %!assert (char (pyeval ("__import__('sys')")), "") + +%!assert (isa (pyobject (), "pyobject")) +%!assert (isa (pyobject ("a string"), "pyobject")) +%!assert (isa (pyobject (42.2), "pyobject")) +%!assert (isa (pyobject (int32 (42)), "pyobject")) +%!assert (isa (pyobject (pyobject ()), "pyobject")) diff -r 3bf799e80ca5 -r 4c4747646e12 python_to_octave.cc --- a/python_to_octave.cc Fri Jul 29 20:15:39 2016 -0700 +++ b/python_to_octave.cc Thu Jul 28 10:55:44 2016 -0700 @@ -500,7 +500,7 @@ main_namespace, main_namespace); main_namespace["__InOct__"][id] = py_object; // Create @pyobject - oct_value = feval ("pyobject", ovl (id), 1); + oct_value = feval ("pyobject", ovl (0, id), 2); } void pyobj_to_octvalue (octave_value& oct_value,