Mercurial > pytave
changeset 202:3fa99babc7b5
pyeval: preliminary support for returning pyobj
Introduces static method `pyobj.fromPythonVarName(s)`, whereas the
constructor itself now no longer deals with `__InOct__` itself.
* pyeval.cc: return the id() instead for now
* @pyobj/pyobj.m: change constructor, add method
* @pyobj/dummy.m: add doctests
author | Colin Macdonald <cbm@m.fsf.org> |
---|---|
date | Fri, 20 May 2016 00:20:03 -0700 |
parents | b3c23054a9c2 |
children | 7d03df51d6e8 |
files | @pyobj/dummy.m @pyobj/pyobj.m pyeval.cc |
diffstat | 3 files changed, 70 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/@pyobj/dummy.m Thu May 19 17:08:03 2016 -0700 +++ b/@pyobj/dummy.m Fri May 20 00:20:03 2016 -0700 @@ -26,7 +26,7 @@ %% @example %% @group %% pyexec('d = dict(one=1, two=2)') -%% x = pyobj('d') +%% x = pyobj.fromPythonVarName('d') %% @result{} x = %% [PyObject id ...] %% @{'two': 2, 'one': 1@} @@ -42,6 +42,39 @@ %% @end group %% @end example %% +%% @code{pyeval} should return a @@pyobj for things it cannot convert to +%% Octave-native objects: +%% @example +%% @group +%% pyexec('import sys') % doctest: +XFAIL +%% sysmodule = pyeval('sys') +%% @result{} sysmodule = +%% [PyObject id ...] +%% <module 'sys' (built-in)> +%% @end group +%% @end example +%% +%% But it doesn't work yet, for now you have to do: +%% @example +%% @group +%% pyexec('import sys') +%% key = pyeval('sys') +%% @result{} key = ... +%% sysmodule = pyobj(key) +%% @result{} sysmodule = +%% [PyObject id ...] +%% <module 'sys' (built-in)> +%% @end group +%% @end example +%% +%% After you have the object, you can access its properties: +%% @example +%% @group +%% sysmodule.version +%% @result{} ans = ... +%% @end group +%% @end example +%% %% @seealso{pyobj} %% @end defmethod
--- a/@pyobj/pyobj.m Thu May 19 17:08:03 2016 -0700 +++ b/@pyobj/pyobj.m Fri May 20 00:20:03 2016 -0700 @@ -53,9 +53,9 @@ properties id end - methods - function x = pyobj(pyvarname) + methods(Static) + function x = fromPythonVarName(pyvarname) % if @var{pyvarname} is a string, its assumed to be a variable % name, e.g., previously created with pyexec. This must exist % at the time of construction but it can disappear later (we @@ -63,16 +63,23 @@ if (~ ischar(pyvarname)) error('pyobj: currently we only take variable names as input') end - % FIXME: check __InOct__ exists - % FIXME: ensure id is not in the dict cmd = sprintf ([ ... 'if not ("__InOct__" in vars() or "__InOct__" in globals()):\n' ... ' __InOct__ = dict()\n' ... '__InOct__[hex(id(%s))] = %s' ], ... pyvarname, pyvarname); pyexec (cmd); - x.id = pyeval (['hex(id(' pyvarname '))']); - %x.repr = pyeval (['repr(' x.varname ')']); + id = pyeval (['hex(id(' pyvarname '))']); + x = pyobj(id); + end + end + + + methods + function x = pyobj(id) + % warning: not intended for casual use: you must also insert + % the object into the Python `__InOct__` dict with key `id`. + x.id = id; end function delete(x) @@ -100,6 +107,8 @@ delete(x) end + dummy (x) + function r = getid (x) r = x.id; end
--- a/pyeval.cc Thu May 19 17:08:03 2016 -0700 +++ b/pyeval.cc Fri May 20 00:20:03 2016 -0700 @@ -63,13 +63,22 @@ std::string code = args(0).string_value (); + std::string id; + object res; + Py_Initialize (); + object main_module = import ("__main__"); + object main_namespace = main_module.attr ("__dict__"); + try { - object main_module = import ("__main__"); - object main_namespace = main_module.attr ("__dict__"); - object res = eval (code.c_str (), main_namespace, main_namespace); + res = eval (code.c_str (), main_namespace, main_namespace); + object builtins = main_module.attr ("__builtins__"); + // hex(id(res)) + object idtmp = builtins.attr("hex")(builtins.attr("id")(res)); + id = extract<std::string> (idtmp); + //std::cerr << "got it: " << id << std::endl; // FIXME: currently, we cannot return the raw object to octave... if (! res.is_none ()) @@ -81,7 +90,15 @@ } catch (pytave::object_convert_exception const &) { - error ("pyeval: error in return value type conversion"); + printf ("pyeval: could not convert return value to Octave-native object, making pyobj...\n"); + // Ensure we have a __InOct__ dict, and then put `res` into it + exec ("if not (\"__InOct__\" in vars() or \"__InOct__\" in globals()):\n" + " __InOct__ = dict()\n", + main_namespace, main_namespace); + main_namespace["__InOct__"][id] = res; + //retval(0) = pyobj(id); + // FIXME: how to do the above? For now, just return the string + retval(0) = id; } catch (error_already_set const &) {