Mercurial > pytave
changeset 307:b4e56f7255f7
Add option to specify namespace when calling pyexec and pyeval (fixes issue #25)
* pyeval.cc, pyexec.cc: Use the second parameter (if supplied) as namespace to
eval/exec the python code.
author | Abhinav Tripathi <genuinelucifer@gmail.com> |
---|---|
date | Tue, 09 Aug 2016 11:28:15 -0700 |
parents | 2ecae5c6eeb6 |
children | 3e0decdf59b0 |
files | pyeval.cc pyexec.cc |
diffstat | 2 files changed, 80 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/pyeval.cc Tue Aug 09 11:27:38 2016 -0700 +++ b/pyeval.cc Tue Aug 09 11:28:15 2016 -0700 @@ -35,6 +35,7 @@ #include "arrayobjectdefs.h" #include "exceptions.h" #include "python_to_octave.h" +#include "pytave_utils.h" using namespace boost::python; @@ -42,7 +43,10 @@ "-*- texinfo -*-\n\ @deftypefn {} {} pyeval (@var{expr})\n\ @deftypefnx {} {@var{x} =} pyeval (@var{expr})\n\ +@deftypefn {} {} pyeval (@var{expr}, @var{localNS})\n\ +@deftypefnx {} {@var{x} =} pyeval (@var{expr}, @var{localNS})\n\ Evaluate a Python expression and return the result.\n\ +You can supply a 'localNS' to enforce all changes in that namespace.\n\ \n\ Examples:\n\ @example\n\ @@ -63,6 +67,12 @@ int nargin = args.length (); + if (nargin < 1 || nargin > 2) + { + print_usage (); + return retval; + } + std::string code = args(0).string_value (); std::string id; @@ -72,10 +82,19 @@ object main_module = import ("__main__"); object main_namespace = main_module.attr ("__dict__"); + object local_namespace; + if (nargin > 1) + { + pytave::get_object_from_python (args(1), local_namespace); + if (local_namespace.is_none ()) + error ("pyeval: NAMESPACE must be a string or a Python reference"); + } + else + local_namespace = main_namespace; try { - res = eval (code.c_str (), main_namespace, main_namespace); + res = eval (code.c_str (), main_namespace, local_namespace); if (nargout > 0 || ! res.is_none ()) { @@ -154,4 +173,50 @@ %!error <NameError> %! pyexec ("def raiseException(): raise NameError ('oops')") %! pyeval ("raiseException()") + +%!test +%! % Variable defined in global namespace is available locally +%! myNS = pyeval ("{}"); +%! 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) +%! assert (pyeval ("myvar"), 1) +%! assert (pyeval ("myvar", myNS1), 2) +%! assert (pyeval ("myvar", myNS2), 3) + +%!test +%! pyexec ("if 'myvar' in globals(): del myvar") +%! % Namespaces can also be passed as strings +%! pyexec ("myNS = {}"); +%! pyexec ("myvar = 1", "myNS"); +%! assert (pyeval ("myvar", "myNS"), 1); + +%!error <NameError> +%! pyexec ("if 'myvar' in globals(): del myvar") +%! % Variable defined in local namespace MUST not be available globally +%! myNS = pyeval ("{}"); +%! pyexec ("myvar = 1", myNS) +%! pyeval ("myvar"); + +%!error <NameError> +%! pyexec ("if 'myvar' in globals(): del myvar") +%! % Variable defined in one local namespace MUST not be available in another +%! myNS1 = pyeval ("{}"); +%! myNS2 = pyeval ("{}"); +%! pyexec ("myvar = 1", myNS1) +%! pyeval ("myvar", myNS2); + +%!error <NameError> +%! pyexec ("if 'sys' in globals(): del sys") +%! % Modules imported in local namespace MUST not be accessible globally +%! myNS = pyeval ("{}"); +%! pyexec ("import sys", myNS); +%! pyeval ("sys"); */
--- a/pyexec.cc Tue Aug 09 11:27:38 2016 -0700 +++ b/pyexec.cc Tue Aug 09 11:28:15 2016 -0700 @@ -34,13 +34,16 @@ #include "arrayobjectdefs.h" #include "exceptions.h" #include "python_to_octave.h" +#include "pytave_utils.h" using namespace boost::python; DEFUN_DLD (pyexec, args, nargout, "-*- texinfo -*-\n\ @deftypefn {} {} pyexec (@var{expr})\n\ +@deftypefn {} {} pyexec (@var{expr}, @var{localNS})\n\ Execute a Python expression or block of code.\n\ +You can supply a 'localNS' to enforce all changes in that namespace.\n\ \n\ Examples:\n\ @example\n\ @@ -56,7 +59,7 @@ int nargin = args.length (); - if (nargin != 1) + if (nargin < 1 || nargin > 2) { print_usage (); return retval; @@ -68,12 +71,21 @@ object main_module = import ("__main__"); object main_namespace = main_module.attr ("__dict__"); + object local_namespace; + if (nargin > 1) + { + pytave::get_object_from_python (args(1), local_namespace); + if (local_namespace.is_none ()) + error ("pyexec: NAMESPACE must be a string or a Python reference"); + } + else + local_namespace = main_namespace; try { // FIXME: figure out exec return code: // http://www.boost.org/doc/libs/1_38_0/libs/python/doc/v2/exec.html - exec (code.c_str (), main_namespace, main_namespace); + exec (code.c_str (), main_namespace, local_namespace); } catch (pytave::object_convert_exception const &) {