changeset 335:9b862844e6b7

Enable Python print function in evaluated expressions (fixes issue #48) * oct-py-eval.cc, oct-py-eval.h: New files. * Makefile.am (COMMON_SOURCE_FILES, PYTAVE_HEADER_FILES): Add oct-py-eval.cc and oct-py-eval.h to the build system. * pyeval.cc (Fpyeval): Use pytave::py_eval_string. * pyexec.cc (Fpyexec): Use pytave::py_exec_string.
author Mike Miller <mtmiller@octave.org>
date Mon, 15 Aug 2016 15:16:24 -0700
parents 252b458bd904
children c081e30c2f64
files Makefile.am oct-py-eval.cc oct-py-eval.h pyeval.cc pyexec.cc
diffstat 5 files changed, 130 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.am	Mon Aug 15 14:19:15 2016 -0700
+++ b/Makefile.am	Mon Aug 15 15:16:24 2016 -0700
@@ -30,6 +30,7 @@
 COMMON_SOURCE_FILES = \
   exceptions.cc \
   octave_to_python.cc \
+  oct-py-eval.cc \
   oct-py-types.cc \
   oct-py-util.cc \
   python_to_octave.cc
@@ -49,6 +50,7 @@
   arrayobjectdefs.h \
   config.h \
   exceptions.h \
+  oct-py-eval.h \
   oct-py-types.h \
   oct-py-util.h \
   octave_to_python.h \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/oct-py-eval.cc	Mon Aug 15 15:16:24 2016 -0700
@@ -0,0 +1,81 @@
+/*
+
+Copyright (C) 2016 Mike Miller
+
+This file is part of Pytave.
+
+Pytave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Pytave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Pytave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
+#include <string>
+#include <boost/python.hpp>
+
+#include "oct-py-eval.h"
+
+namespace pytave
+{
+
+PyObject *
+py_run_string_safe (const std::string& expr, int start, PyObject *globals,
+                    PyObject *locals)
+{
+  bool alloc = false;
+
+  if (! globals || (globals == Py_None))
+    {
+      globals = PyEval_GetGlobals ();
+      if (! globals)
+        {
+          globals = PyDict_New ();
+          alloc = true;
+        }
+    }
+
+  if (! locals || (locals == Py_None))
+    locals = globals;
+
+  // Evaluate all expressions under "from __future__ import print_function"
+  PyCompilerFlags flags { CO_FUTURE_PRINT_FUNCTION };
+
+  PyObject *retval = PyRun_StringFlags (expr.c_str (), start, globals, locals,
+                                        &flags);
+
+  if (alloc)
+    Py_DECREF (globals);
+
+  if (! retval)
+    throw boost::python::error_already_set ();
+
+  return retval;
+}
+
+PyObject *
+py_eval_string (const std::string& expr, PyObject *globals, PyObject *locals)
+{
+  return py_run_string_safe (expr, Py_eval_input, globals, locals);
+}
+
+PyObject *
+py_exec_string (const std::string& expr, PyObject *globals, PyObject *locals)
+{
+  return py_run_string_safe (expr, Py_file_input, globals, locals);
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/oct-py-eval.h	Mon Aug 15 15:16:24 2016 -0700
@@ -0,0 +1,40 @@
+/*
+
+Copyright (C) 2016 Mike Miller
+
+This file is part of Pytave.
+
+Pytave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Pytave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Pytave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (pytave_oct_py_eval_h)
+#define pytave_oct_py_eval_h 1
+
+#include <Python.h>
+#include <string>
+
+namespace pytave
+{
+
+PyObject *
+py_eval_string (const std::string& expr, PyObject *globals = 0, PyObject *locals = 0);
+
+PyObject *
+py_exec_string (const std::string& expr, PyObject *globals = 0, PyObject *locals = 0);
+
+}
+
+#endif
--- a/pyeval.cc	Mon Aug 15 14:19:15 2016 -0700
+++ b/pyeval.cc	Mon Aug 15 15:16:24 2016 -0700
@@ -34,6 +34,7 @@
 #define PYTAVE_DO_DECLARE_SYMBOL
 #include "arrayobjectdefs.h"
 #include "exceptions.h"
+#include "oct-py-eval.h"
 #include "oct-py-util.h"
 #include "python_to_octave.h"
 
@@ -77,7 +78,6 @@
   std::string code = args(0).string_value ();
 
   std::string id;
-  object res;
 
   Py_Initialize ();
 
@@ -95,7 +95,9 @@
 
   try
     {
-      res = eval (code.c_str (), main_namespace, local_namespace);
+      PyObject *obj = pytave::py_eval_string (code, main_namespace.ptr (),
+                                              local_namespace.ptr ());
+      boost::python::object res { boost::python::handle<> (obj) };
 
       if (nargout > 0 || ! res.is_none ())
         {
--- a/pyexec.cc	Mon Aug 15 14:19:15 2016 -0700
+++ b/pyexec.cc	Mon Aug 15 15:16:24 2016 -0700
@@ -33,6 +33,7 @@
 #define PYTAVE_DO_DECLARE_SYMBOL
 #include "arrayobjectdefs.h"
 #include "exceptions.h"
+#include "oct-py-eval.h"
 #include "oct-py-util.h"
 #include "python_to_octave.h"
 
@@ -88,7 +89,8 @@
     {
       // 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, local_namespace);
+      pytave::py_exec_string (code, main_namespace.ptr (),
+                              local_namespace.ptr ());
     }
   catch (pytave::object_convert_exception const &)
     {