From ea44eef9b4fbc4d0ab9ba4f7f31af16c7e9b44e4 Mon Sep 17 00:00:00 2001 From: yag Date: Fri, 17 Feb 2017 15:47:55 +0800 Subject: [PATCH 1/2] Add Eval(...) and Exec(...) --- src/embed_tests/Python.EmbeddingTest.csproj | 1 + src/embed_tests/pyrunstring.cs | 61 ++++++++++++++++++++ src/runtime/pythonengine.cs | 64 +++++++++++++++------ 3 files changed, 107 insertions(+), 19 deletions(-) create mode 100644 src/embed_tests/pyrunstring.cs diff --git a/src/embed_tests/Python.EmbeddingTest.csproj b/src/embed_tests/Python.EmbeddingTest.csproj index 1b015136d..f943ca787 100644 --- a/src/embed_tests/Python.EmbeddingTest.csproj +++ b/src/embed_tests/Python.EmbeddingTest.csproj @@ -86,6 +86,7 @@ + diff --git a/src/embed_tests/pyrunstring.cs b/src/embed_tests/pyrunstring.cs new file mode 100644 index 000000000..29fef522a --- /dev/null +++ b/src/embed_tests/pyrunstring.cs @@ -0,0 +1,61 @@ +using System; +using NUnit.Framework; +using Python.Runtime; + +namespace Python.EmbeddingTest +{ + public class RunStringTest + { + private Py.GILState gil; + + [SetUp] + public void SetUp() + { + gil = Py.GIL(); + } + + [TearDown] + public void Dispose() + { + gil.Dispose(); + } + + [Test] + public void TestRunSimpleString() + { + int aa = PythonEngine.RunSimpleString("import sys"); + Assert.AreEqual(aa, 0); + + int bb = PythonEngine.RunSimpleString("import 1234"); + Assert.AreEqual(bb, -1); + } + + [Test] + public void TestEval() + { + dynamic sys = Py.Import("sys"); + sys.attr1 = 100; + var locals = new PyDict(); + locals.SetItem("sys", sys); + locals.SetItem("a", new PyInt(10)); + + object b = PythonEngine.Eval("sys.attr1 + a + 1", null, locals.Handle) + .AsManagedObject(typeof(Int32)); + Assert.AreEqual(b, 111); + } + + [Test] + public void TestExec() + { + dynamic sys = Py.Import("sys"); + sys.attr1 = 100; + var locals = new PyDict(); + locals.SetItem("sys", sys); + locals.SetItem("a", new PyInt(10)); + + PythonEngine.Exec("c = sys.attr1 + a + 1", null, locals.Handle); + object c = locals.GetItem("c").AsManagedObject(typeof(Int32)); + Assert.AreEqual(c, 111); + } + } +} diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index e9fa888a9..1728422af 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -156,11 +156,7 @@ public static void Initialize(IEnumerable args) string code = "import atexit, clr\n" + "atexit.register(clr._AtExit)\n"; - PyObject r = PythonEngine.RunString(code); - if (r != null) - { - r.Dispose(); - } + PythonEngine.Exec(code); // Load the clr.py resource into the clr module IntPtr clr = Python.Runtime.ImportHook.GetCLRModule(); @@ -180,12 +176,7 @@ public static void Initialize(IEnumerable args) { // add the contents of clr.py to the module string clr_py = reader.ReadToEnd(); - PyObject result = RunString(clr_py, module_globals, locals.Handle); - if (null == result) - { - throw new PythonException(); - } - result.Dispose(); + Exec(clr_py, module_globals, locals.Handle); } // add the imported module to the clr module, and copy the API functions @@ -253,11 +244,7 @@ public static void InitExt() " exec(line)\n" + " break\n"; - PyObject r = PythonEngine.RunString(code); - if (r != null) - { - r.Dispose(); - } + PythonEngine.Exec(code); } catch (PythonException e) { @@ -405,6 +392,38 @@ public static PyObject ModuleFromString(string name, string code) } + /// + /// Eval Method + /// + /// + /// Evaluate a Python expression and returns the result. + /// It's a subset of Python eval function. + /// + public static PyObject Eval(string code, IntPtr? globals = null, IntPtr? locals = null) + { + PyObject result = RunString(code, globals, locals, RunFlagType.Eval); + return result; + } + + + /// + /// Exec Method + /// + /// + /// Run a string containing Python code. + /// It's a subset of Python exec function. + /// + public static void Exec(string code, IntPtr? globals = null, IntPtr? locals = null) + { + PyObject result = RunString(code, globals, locals, RunFlagType.File); + if (result.obj != Runtime.PyNone) + { + throw new PythonException(); + } + result.Dispose(); + } + + /// /// RunString Method /// @@ -413,8 +432,8 @@ public static PyObject ModuleFromString(string name, string code) /// executing the code string as a PyObject instance, or null if /// an exception was raised. /// - public static PyObject RunString( - string code, IntPtr? globals = null, IntPtr? locals = null + internal static PyObject RunString( + string code, IntPtr? globals = null, IntPtr? locals = null, RunFlagType _flag = RunFlagType.File ) { var borrowedGlobals = true; @@ -439,7 +458,7 @@ public static PyObject RunString( borrowedLocals = false; } - var flag = (IntPtr)257; /* Py_file_input */ + var flag = (IntPtr)_flag; try { @@ -465,6 +484,13 @@ public static PyObject RunString( } } + public enum RunFlagType + { + Single = 256, + File = 257, /* Py_file_input */ + Eval = 258 + } + public static class Py { public static GILState GIL() From 2dfff9f21601afe742477fda4c3df1040925c91a Mon Sep 17 00:00:00 2001 From: Victor Uriarte Date: Thu, 23 Feb 2017 14:25:56 -0700 Subject: [PATCH 2/2] Keep RunString Public. Fix Assert.AreEqual order - Deprecation/Removal should be a separate issue/pr - In NUnit/XUnit, expected is the first argument, actual is second. Opposite to how Python does it --- src/embed_tests/pyrunstring.cs | 12 ++++++------ src/runtime/pythonengine.cs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/embed_tests/pyrunstring.cs b/src/embed_tests/pyrunstring.cs index 29fef522a..b17bb87f8 100644 --- a/src/embed_tests/pyrunstring.cs +++ b/src/embed_tests/pyrunstring.cs @@ -24,10 +24,10 @@ public void Dispose() public void TestRunSimpleString() { int aa = PythonEngine.RunSimpleString("import sys"); - Assert.AreEqual(aa, 0); + Assert.AreEqual(0, aa); int bb = PythonEngine.RunSimpleString("import 1234"); - Assert.AreEqual(bb, -1); + Assert.AreEqual(-1, bb); } [Test] @@ -40,8 +40,8 @@ public void TestEval() locals.SetItem("a", new PyInt(10)); object b = PythonEngine.Eval("sys.attr1 + a + 1", null, locals.Handle) - .AsManagedObject(typeof(Int32)); - Assert.AreEqual(b, 111); + .AsManagedObject(typeof(int)); + Assert.AreEqual(111, b); } [Test] @@ -54,8 +54,8 @@ public void TestExec() locals.SetItem("a", new PyInt(10)); PythonEngine.Exec("c = sys.attr1 + a + 1", null, locals.Handle); - object c = locals.GetItem("c").AsManagedObject(typeof(Int32)); - Assert.AreEqual(c, 111); + object c = locals.GetItem("c").AsManagedObject(typeof(int)); + Assert.AreEqual(111, c); } } } diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index 1728422af..accd349c5 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -432,7 +432,7 @@ public static void Exec(string code, IntPtr? globals = null, IntPtr? locals = nu /// executing the code string as a PyObject instance, or null if /// an exception was raised. /// - internal static PyObject RunString( + public static PyObject RunString( string code, IntPtr? globals = null, IntPtr? locals = null, RunFlagType _flag = RunFlagType.File ) {