Mercurial > pytave
annotate pyeval.cc @ 247:c3addc52dfcd
pyeval: allow evaluated value of None (fixes issue #31)
* pyeval.cc (Fpyeval): Allow return value to be None when being assigned to
an lvalue.
author | Mike Miller <mtmiller@octave.org> |
---|---|
date | Wed, 27 Jul 2016 17:20:01 -0700 |
parents | bbf0b7a4e117 |
children | 0fc1a58d7e89 0a4f620da178 9278a272b1c8 |
rev | line source |
---|---|
161 | 1 /* |
2 | |
3 Copyright (C) 2016 Colin B. Macdonald | |
4 | |
5 This file is part of Pytave. | |
6 | |
7 Pytave is free software; you can redistribute it and/or modify it | |
8 under the terms of the GNU General Public License as published by the | |
9 Free Software Foundation; either version 3 of the License, or (at your | |
10 option) any later version. | |
11 | |
12 Pytave is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with Pytave; see the file COPYING. If not, see | |
19 <http://www.gnu.org/licenses/>. | |
20 | |
21 */ | |
22 | |
162
df7b4a5ab542
Apply recent project changes to pyeval/pyexec, clean up
Mike Miller <mtmiller@octave.org>
parents:
161
diff
changeset
|
23 #if defined (HAVE_CONFIG_H) |
df7b4a5ab542
Apply recent project changes to pyeval/pyexec, clean up
Mike Miller <mtmiller@octave.org>
parents:
161
diff
changeset
|
24 # include <config.h> |
161 | 25 #endif |
26 | |
27 #include <dlfcn.h> | |
28 #include <boost/python.hpp> | |
29 #include <boost/python/numeric.hpp> | |
30 | |
31 #include <oct.h> | |
204
61df785bd8b0
pyeval creates pyobj direction
Colin Macdonald <cbm@m.fsf.org>
parents:
202
diff
changeset
|
32 #include <octave/parse.h> |
161 | 33 |
34 #define PYTAVE_DO_DECLARE_SYMBOL | |
35 #include "arrayobjectdefs.h" | |
36 #include "exceptions.h" | |
37 #include "python_to_octave.h" | |
38 | |
39 using namespace boost::python; | |
40 | |
41 DEFUN_DLD (pyeval, args, nargout, | |
42 "-*- texinfo -*-\n\ | |
173
28dc607532c2
doc: Clarify and clean up docstrings for all oct files
Mike Miller <mtmiller@octave.org>
parents:
162
diff
changeset
|
43 @deftypefn {} {} pyeval (@var{expr})\n\ |
28dc607532c2
doc: Clarify and clean up docstrings for all oct files
Mike Miller <mtmiller@octave.org>
parents:
162
diff
changeset
|
44 @deftypefnx {} {@var{x} =} pyeval (@var{expr})\n\ |
28dc607532c2
doc: Clarify and clean up docstrings for all oct files
Mike Miller <mtmiller@octave.org>
parents:
162
diff
changeset
|
45 Evaluate a Python expression and return the result.\n\ |
28dc607532c2
doc: Clarify and clean up docstrings for all oct files
Mike Miller <mtmiller@octave.org>
parents:
162
diff
changeset
|
46 \n\ |
28dc607532c2
doc: Clarify and clean up docstrings for all oct files
Mike Miller <mtmiller@octave.org>
parents:
162
diff
changeset
|
47 Examples:\n\ |
28dc607532c2
doc: Clarify and clean up docstrings for all oct files
Mike Miller <mtmiller@octave.org>
parents:
162
diff
changeset
|
48 @example\n\ |
28dc607532c2
doc: Clarify and clean up docstrings for all oct files
Mike Miller <mtmiller@octave.org>
parents:
162
diff
changeset
|
49 @group\n\ |
176 | 50 pyexec (\"import sys\")\n\ |
173
28dc607532c2
doc: Clarify and clean up docstrings for all oct files
Mike Miller <mtmiller@octave.org>
parents:
162
diff
changeset
|
51 pyeval (\"sys.version\")\n\ |
28dc607532c2
doc: Clarify and clean up docstrings for all oct files
Mike Miller <mtmiller@octave.org>
parents:
162
diff
changeset
|
52 @result{} ...\n\ |
28dc607532c2
doc: Clarify and clean up docstrings for all oct files
Mike Miller <mtmiller@octave.org>
parents:
162
diff
changeset
|
53 pyeval (\"dict(one=1, two=2)\")\n\ |
28dc607532c2
doc: Clarify and clean up docstrings for all oct files
Mike Miller <mtmiller@octave.org>
parents:
162
diff
changeset
|
54 @result{} scalar structure containing the fields:\n\ |
28dc607532c2
doc: Clarify and clean up docstrings for all oct files
Mike Miller <mtmiller@octave.org>
parents:
162
diff
changeset
|
55 two = 2\n\ |
28dc607532c2
doc: Clarify and clean up docstrings for all oct files
Mike Miller <mtmiller@octave.org>
parents:
162
diff
changeset
|
56 one = 1\n\ |
28dc607532c2
doc: Clarify and clean up docstrings for all oct files
Mike Miller <mtmiller@octave.org>
parents:
162
diff
changeset
|
57 @end group\n\ |
28dc607532c2
doc: Clarify and clean up docstrings for all oct files
Mike Miller <mtmiller@octave.org>
parents:
162
diff
changeset
|
58 @end example\n\ |
28dc607532c2
doc: Clarify and clean up docstrings for all oct files
Mike Miller <mtmiller@octave.org>
parents:
162
diff
changeset
|
59 @seealso{pycall, pyexec}\n\ |
161 | 60 @end deftypefn") |
61 { | |
62 octave_value_list retval; | |
63 | |
64 int nargin = args.length (); | |
65 | |
66 std::string code = args(0).string_value (); | |
67 | |
202
3fa99babc7b5
pyeval: preliminary support for returning pyobj
Colin Macdonald <cbm@m.fsf.org>
parents:
173
diff
changeset
|
68 std::string id; |
3fa99babc7b5
pyeval: preliminary support for returning pyobj
Colin Macdonald <cbm@m.fsf.org>
parents:
173
diff
changeset
|
69 object res; |
3fa99babc7b5
pyeval: preliminary support for returning pyobj
Colin Macdonald <cbm@m.fsf.org>
parents:
173
diff
changeset
|
70 |
161 | 71 Py_Initialize (); |
72 | |
202
3fa99babc7b5
pyeval: preliminary support for returning pyobj
Colin Macdonald <cbm@m.fsf.org>
parents:
173
diff
changeset
|
73 object main_module = import ("__main__"); |
3fa99babc7b5
pyeval: preliminary support for returning pyobj
Colin Macdonald <cbm@m.fsf.org>
parents:
173
diff
changeset
|
74 object main_namespace = main_module.attr ("__dict__"); |
226
382bb1d91239
maint: import standard Python names consistently
Mike Miller <mtmiller@octave.org>
parents:
225
diff
changeset
|
75 #if PY_VERSION_HEX >= 0x03000000 |
382bb1d91239
maint: import standard Python names consistently
Mike Miller <mtmiller@octave.org>
parents:
225
diff
changeset
|
76 object builtins_module = import ("builtins"); |
382bb1d91239
maint: import standard Python names consistently
Mike Miller <mtmiller@octave.org>
parents:
225
diff
changeset
|
77 #else |
382bb1d91239
maint: import standard Python names consistently
Mike Miller <mtmiller@octave.org>
parents:
225
diff
changeset
|
78 object builtins_module = import ("__builtin__"); |
382bb1d91239
maint: import standard Python names consistently
Mike Miller <mtmiller@octave.org>
parents:
225
diff
changeset
|
79 #endif |
202
3fa99babc7b5
pyeval: preliminary support for returning pyobj
Colin Macdonald <cbm@m.fsf.org>
parents:
173
diff
changeset
|
80 |
161 | 81 try |
82 { | |
202
3fa99babc7b5
pyeval: preliminary support for returning pyobj
Colin Macdonald <cbm@m.fsf.org>
parents:
173
diff
changeset
|
83 res = eval (code.c_str (), main_namespace, main_namespace); |
3fa99babc7b5
pyeval: preliminary support for returning pyobj
Colin Macdonald <cbm@m.fsf.org>
parents:
173
diff
changeset
|
84 // hex(id(res)) |
227
c56b85f405ba
maint: apply Octave whitespace rules
Mike Miller <mtmiller@octave.org>
parents:
226
diff
changeset
|
85 object hex_function = builtins_module.attr ("hex"); |
c56b85f405ba
maint: apply Octave whitespace rules
Mike Miller <mtmiller@octave.org>
parents:
226
diff
changeset
|
86 object id_function = builtins_module.attr ("id"); |
c56b85f405ba
maint: apply Octave whitespace rules
Mike Miller <mtmiller@octave.org>
parents:
226
diff
changeset
|
87 object idtmp = hex_function (id_function (res)); |
212 | 88 id = extract<std::string> (idtmp); |
162
df7b4a5ab542
Apply recent project changes to pyeval/pyexec, clean up
Mike Miller <mtmiller@octave.org>
parents:
161
diff
changeset
|
89 |
247
c3addc52dfcd
pyeval: allow evaluated value of None (fixes issue #31)
Mike Miller <mtmiller@octave.org>
parents:
235
diff
changeset
|
90 if (nargout > 0 || ! res.is_none ()) |
161 | 91 { |
92 octave_value val; | |
93 pytave::pyobj_to_octvalue (val, res); | |
94 retval(0) = val; | |
95 } | |
96 } | |
97 catch (pytave::object_convert_exception const &) | |
98 { | |
202
3fa99babc7b5
pyeval: preliminary support for returning pyobj
Colin Macdonald <cbm@m.fsf.org>
parents:
173
diff
changeset
|
99 // Ensure we have a __InOct__ dict, and then put `res` into it |
3fa99babc7b5
pyeval: preliminary support for returning pyobj
Colin Macdonald <cbm@m.fsf.org>
parents:
173
diff
changeset
|
100 exec ("if not (\"__InOct__\" in vars() or \"__InOct__\" in globals()):\n" |
217
69abda471c67
Attempt at moving pyobject from octave to python
Colin Macdonald <cbm@m.fsf.org>
parents:
215
diff
changeset
|
101 " __InOct__ = dict()\n" |
69abda471c67
Attempt at moving pyobject from octave to python
Colin Macdonald <cbm@m.fsf.org>
parents:
215
diff
changeset
|
102 " # FIXME: make it accessible elsewhere?\n" |
69abda471c67
Attempt at moving pyobject from octave to python
Colin Macdonald <cbm@m.fsf.org>
parents:
215
diff
changeset
|
103 " import __main__\n" |
69abda471c67
Attempt at moving pyobject from octave to python
Colin Macdonald <cbm@m.fsf.org>
parents:
215
diff
changeset
|
104 " __main__.__InOct__ = __InOct__\n", |
202
3fa99babc7b5
pyeval: preliminary support for returning pyobj
Colin Macdonald <cbm@m.fsf.org>
parents:
173
diff
changeset
|
105 main_namespace, main_namespace); |
3fa99babc7b5
pyeval: preliminary support for returning pyobj
Colin Macdonald <cbm@m.fsf.org>
parents:
173
diff
changeset
|
106 main_namespace["__InOct__"][id] = res; |
211 | 107 // Create @pyobject |
108 retval = feval ("pyobject", ovl (id), 1); | |
161 | 109 } |
110 catch (error_already_set const &) | |
111 { | |
231
6fffa6219b2c
Properly extract exception text from Python (fixes issue #24)
Abhinav Tripathi <genuinelucifer@gmail.com>
parents:
190
diff
changeset
|
112 std::string message = pytave::fetch_exception_message (); |
6fffa6219b2c
Properly extract exception text from Python (fixes issue #24)
Abhinav Tripathi <genuinelucifer@gmail.com>
parents:
190
diff
changeset
|
113 error ("pyeval: %s", message.c_str ()); |
161 | 114 } |
115 | |
116 return retval; | |
117 } | |
180
5f0d94afebe2
Added some basic tests
Abhinav Tripathi <genuinelucifer@gmail.com>
parents:
176
diff
changeset
|
118 |
5f0d94afebe2
Added some basic tests
Abhinav Tripathi <genuinelucifer@gmail.com>
parents:
176
diff
changeset
|
119 /* |
190
ac377ace2ee4
More unit tests of pycall and pyeval
Mike Miller <mtmiller@octave.org>
parents:
183
diff
changeset
|
120 %!assert (isnumeric (pyeval ("0"))) |
ac377ace2ee4
More unit tests of pycall and pyeval
Mike Miller <mtmiller@octave.org>
parents:
183
diff
changeset
|
121 %!assert (isreal (pyeval ("0"))) |
ac377ace2ee4
More unit tests of pycall and pyeval
Mike Miller <mtmiller@octave.org>
parents:
183
diff
changeset
|
122 %!assert (pyeval ("0"), 0) |
180
5f0d94afebe2
Added some basic tests
Abhinav Tripathi <genuinelucifer@gmail.com>
parents:
176
diff
changeset
|
123 |
190
ac377ace2ee4
More unit tests of pycall and pyeval
Mike Miller <mtmiller@octave.org>
parents:
183
diff
changeset
|
124 %!assert (isnumeric (pyeval ("10.1"))) |
ac377ace2ee4
More unit tests of pycall and pyeval
Mike Miller <mtmiller@octave.org>
parents:
183
diff
changeset
|
125 %!assert (isreal (pyeval ("10.1"))) |
ac377ace2ee4
More unit tests of pycall and pyeval
Mike Miller <mtmiller@octave.org>
parents:
183
diff
changeset
|
126 %!assert (pyeval ("10.1"), 10.1) |
ac377ace2ee4
More unit tests of pycall and pyeval
Mike Miller <mtmiller@octave.org>
parents:
183
diff
changeset
|
127 |
ac377ace2ee4
More unit tests of pycall and pyeval
Mike Miller <mtmiller@octave.org>
parents:
183
diff
changeset
|
128 %!assert (isnumeric (pyeval ("2j"))) |
ac377ace2ee4
More unit tests of pycall and pyeval
Mike Miller <mtmiller@octave.org>
parents:
183
diff
changeset
|
129 %!assert (iscomplex (pyeval ("2j"))) |
ac377ace2ee4
More unit tests of pycall and pyeval
Mike Miller <mtmiller@octave.org>
parents:
183
diff
changeset
|
130 %!assert (pyeval ("2j"), 2j) |
ac377ace2ee4
More unit tests of pycall and pyeval
Mike Miller <mtmiller@octave.org>
parents:
183
diff
changeset
|
131 |
ac377ace2ee4
More unit tests of pycall and pyeval
Mike Miller <mtmiller@octave.org>
parents:
183
diff
changeset
|
132 %!assert (ischar (pyeval ("\"I <3 Octave\""))) |
ac377ace2ee4
More unit tests of pycall and pyeval
Mike Miller <mtmiller@octave.org>
parents:
183
diff
changeset
|
133 %!assert (pyeval ("\"I <3 Octave\""), "I <3 Octave") |
180
5f0d94afebe2
Added some basic tests
Abhinav Tripathi <genuinelucifer@gmail.com>
parents:
176
diff
changeset
|
134 |
183
2b03585d4ddd
Add proper conversion of booleans between octave and python. (fixes issue #6)
Abhinav Tripathi <genuinelucifer@gmail.com>
parents:
182
diff
changeset
|
135 %!assert (islogical (pyeval ("True"))) |
2b03585d4ddd
Add proper conversion of booleans between octave and python. (fixes issue #6)
Abhinav Tripathi <genuinelucifer@gmail.com>
parents:
182
diff
changeset
|
136 %!assert (islogical (pyeval ("False"))) |
190
ac377ace2ee4
More unit tests of pycall and pyeval
Mike Miller <mtmiller@octave.org>
parents:
183
diff
changeset
|
137 %!assert (pyeval ("True"), true) |
ac377ace2ee4
More unit tests of pycall and pyeval
Mike Miller <mtmiller@octave.org>
parents:
183
diff
changeset
|
138 %!assert (pyeval ("False"), false) |
183
2b03585d4ddd
Add proper conversion of booleans between octave and python. (fixes issue #6)
Abhinav Tripathi <genuinelucifer@gmail.com>
parents:
182
diff
changeset
|
139 %!assert (class (pyeval ("True")), "logical") |
2b03585d4ddd
Add proper conversion of booleans between octave and python. (fixes issue #6)
Abhinav Tripathi <genuinelucifer@gmail.com>
parents:
182
diff
changeset
|
140 %!assert (class (pyeval ("False")), "logical") |
2b03585d4ddd
Add proper conversion of booleans between octave and python. (fixes issue #6)
Abhinav Tripathi <genuinelucifer@gmail.com>
parents:
182
diff
changeset
|
141 |
235
bbf0b7a4e117
Return pyobject from pycall too, similar to pyeval (fixes issue #28)
Abhinav Tripathi <genuinelucifer@gmail.com>
parents:
232
diff
changeset
|
142 %!assert (isa (pyeval ("object()"), "pyobject")) |
bbf0b7a4e117
Return pyobject from pycall too, similar to pyeval (fixes issue #28)
Abhinav Tripathi <genuinelucifer@gmail.com>
parents:
232
diff
changeset
|
143 |
190
ac377ace2ee4
More unit tests of pycall and pyeval
Mike Miller <mtmiller@octave.org>
parents:
183
diff
changeset
|
144 ## FIXME: these will change when dict, list, and tuple are not converted |
ac377ace2ee4
More unit tests of pycall and pyeval
Mike Miller <mtmiller@octave.org>
parents:
183
diff
changeset
|
145 %!assert (pyeval ("{'x': 1, 'y': 2}"), struct ("x", 1, "y", 2)) |
ac377ace2ee4
More unit tests of pycall and pyeval
Mike Miller <mtmiller@octave.org>
parents:
183
diff
changeset
|
146 %!assert (pyeval ("[1, 2, 3]"), {1, 2, 3}) |
ac377ace2ee4
More unit tests of pycall and pyeval
Mike Miller <mtmiller@octave.org>
parents:
183
diff
changeset
|
147 %!assert (pyeval ("(4, 5, 6)"), {4, 5, 6}) |
ac377ace2ee4
More unit tests of pycall and pyeval
Mike Miller <mtmiller@octave.org>
parents:
183
diff
changeset
|
148 |
180
5f0d94afebe2
Added some basic tests
Abhinav Tripathi <genuinelucifer@gmail.com>
parents:
176
diff
changeset
|
149 %!test |
182
0bf4b7cf16ee
maint: Use Octave coding style conventions for unit tests
Mike Miller <mtmiller@octave.org>
parents:
180
diff
changeset
|
150 %! % FIXME: this will change when we stop converting lists |
0bf4b7cf16ee
maint: Use Octave coding style conventions for unit tests
Mike Miller <mtmiller@octave.org>
parents:
180
diff
changeset
|
151 %! z = pyeval ("[1, [21, 22], 3, [41, [421, 422], 43]]"); |
0bf4b7cf16ee
maint: Use Octave coding style conventions for unit tests
Mike Miller <mtmiller@octave.org>
parents:
180
diff
changeset
|
152 %! assert (z{2}{1}, 21) |
0bf4b7cf16ee
maint: Use Octave coding style conventions for unit tests
Mike Miller <mtmiller@octave.org>
parents:
180
diff
changeset
|
153 %! assert (z{2}{2}, 22) |
0bf4b7cf16ee
maint: Use Octave coding style conventions for unit tests
Mike Miller <mtmiller@octave.org>
parents:
180
diff
changeset
|
154 %! assert (z{4}{2}{1}, 421) |
0bf4b7cf16ee
maint: Use Octave coding style conventions for unit tests
Mike Miller <mtmiller@octave.org>
parents:
180
diff
changeset
|
155 %! assert (z{4}{2}{2}, 422) |
231
6fffa6219b2c
Properly extract exception text from Python (fixes issue #24)
Abhinav Tripathi <genuinelucifer@gmail.com>
parents:
190
diff
changeset
|
156 |
6fffa6219b2c
Properly extract exception text from Python (fixes issue #24)
Abhinav Tripathi <genuinelucifer@gmail.com>
parents:
190
diff
changeset
|
157 %!error <NameError> |
6fffa6219b2c
Properly extract exception text from Python (fixes issue #24)
Abhinav Tripathi <genuinelucifer@gmail.com>
parents:
190
diff
changeset
|
158 %! pyexec ("def raiseException ():\n raise NameError ('oops')") |
6fffa6219b2c
Properly extract exception text from Python (fixes issue #24)
Abhinav Tripathi <genuinelucifer@gmail.com>
parents:
190
diff
changeset
|
159 %! pyeval ("raiseException ()") |
180
5f0d94afebe2
Added some basic tests
Abhinav Tripathi <genuinelucifer@gmail.com>
parents:
176
diff
changeset
|
160 */ |