Skip to content

Commit b95acc3

Browse files
committed
add eval and exec
1 parent 1d583c7 commit b95acc3

File tree

3 files changed

+121
-25
lines changed

3 files changed

+121
-25
lines changed

src/embed_tests/Python.EmbeddingTest.csproj

+11-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
33
<PropertyGroup>
44
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -30,7 +30,8 @@
3030
<DebugType>full</DebugType>
3131
</PropertyGroup>
3232
<PropertyGroup Condition=" '$(Configuration)' == 'ReleaseMono'">
33-
<DefineConstants Condition="'$(DefineConstants)' == ''"></DefineConstants>
33+
<DefineConstants Condition="'$(DefineConstants)' == ''">
34+
</DefineConstants>
3435
<Optimize>true</Optimize>
3536
<DebugType>pdbonly</DebugType>
3637
</PropertyGroup>
@@ -40,7 +41,8 @@
4041
<DebugType>full</DebugType>
4142
</PropertyGroup>
4243
<PropertyGroup Condition=" '$(Configuration)' == 'ReleaseWin'">
43-
<DefineConstants Condition="'$(DefineConstants)' == ''"></DefineConstants>
44+
<DefineConstants Condition="'$(DefineConstants)' == ''">
45+
</DefineConstants>
4446
<Optimize>true</Optimize>
4547
<DebugType>pdbonly</DebugType>
4648
</PropertyGroup>
@@ -50,7 +52,8 @@
5052
<DebugType>full</DebugType>
5153
</PropertyGroup>
5254
<PropertyGroup Condition=" '$(Configuration)' == 'ReleaseMonoPY3'">
53-
<DefineConstants Condition="'$(DefineConstants)' == ''"></DefineConstants>
55+
<DefineConstants Condition="'$(DefineConstants)' == ''">
56+
</DefineConstants>
5457
<Optimize>true</Optimize>
5558
<DebugType>pdbonly</DebugType>
5659
</PropertyGroup>
@@ -60,7 +63,8 @@
6063
<DebugType>full</DebugType>
6164
</PropertyGroup>
6265
<PropertyGroup Condition=" '$(Configuration)' == 'ReleaseWinPY3'">
63-
<DefineConstants Condition="'$(DefineConstants)' == ''"></DefineConstants>
66+
<DefineConstants Condition="'$(DefineConstants)' == ''">
67+
</DefineConstants>
6468
<Optimize>true</Optimize>
6569
<DebugType>pdbonly</DebugType>
6670
</PropertyGroup>
@@ -82,6 +86,7 @@
8286
<Compile Include="pyiter.cs" />
8387
<Compile Include="pylong.cs" />
8488
<Compile Include="pyobject.cs" />
89+
<Compile Include="pyrunstring.cs" />
8590
<Compile Include="pythonexception.cs" />
8691
<Compile Include="pytuple.cs" />
8792
</ItemGroup>
@@ -103,4 +108,4 @@
103108
<Copy SourceFiles="$(TargetAssembly)" DestinationFolder="$(PythonBuildDir)" />
104109
<Copy SourceFiles="$(TargetAssemblyPdb)" Condition="Exists('$(TargetAssemblyPdb)')" DestinationFolder="$(PythonBuildDir)" />
105110
</Target>
106-
</Project>
111+
</Project>

src/embed_tests/pyrunstring.cs

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
using NUnit.Framework;
2+
using Python.Runtime;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Text;
7+
8+
namespace Python.EmbeddingTest
9+
{
10+
[TestFixture]
11+
public class RunStringTest
12+
{
13+
private Py.GILState gil;
14+
15+
[SetUp]
16+
public void SetUp()
17+
{
18+
gil = Py.GIL();
19+
}
20+
21+
[TearDown]
22+
public void TearDown()
23+
{
24+
gil.Dispose();
25+
}
26+
27+
[Test]
28+
public void TestRunSimpleString()
29+
{
30+
int aa = PythonEngine.RunSimpleString("import sys");
31+
Assert.AreEqual(aa, 0);
32+
33+
int bb = PythonEngine.RunSimpleString("import 1234");
34+
Assert.AreEqual(bb, -1);
35+
}
36+
37+
[Test]
38+
public void TestEval()
39+
{
40+
dynamic sys = Py.Import("sys");
41+
sys.attr1 = 100;
42+
PyDict locals = new PyDict();
43+
locals.SetItem("sys", sys);
44+
locals.SetItem("a", new PyInt(10));
45+
46+
var b = PythonEngine.Eval("sys.attr1 + a + 1", null, locals.Handle)
47+
.AsManagedObject(typeof(Int32));
48+
Assert.AreEqual(b, 111);
49+
}
50+
51+
[Test]
52+
public void TestExec()
53+
{
54+
dynamic sys = Py.Import("sys");
55+
sys.attr1 = 100;
56+
PyDict locals = new PyDict();
57+
locals.SetItem("sys", sys);
58+
locals.SetItem("a", new PyInt(10));
59+
60+
PythonEngine.Exec("c = sys.attr1 + a + 1", null, locals.Handle);
61+
var c = locals.GetItem("c").AsManagedObject(typeof(Int32));
62+
Assert.AreEqual(c, 111);
63+
}
64+
}
65+
}

src/runtime/pythonengine.cs

+45-19
Original file line numberDiff line numberDiff line change
@@ -156,11 +156,7 @@ public static void Initialize(IEnumerable<string> args)
156156
string code =
157157
"import atexit, clr\n" +
158158
"atexit.register(clr._AtExit)\n";
159-
PyObject r = PythonEngine.RunString(code);
160-
if (r != null)
161-
{
162-
r.Dispose();
163-
}
159+
PythonEngine.Exec(code);
164160

165161
// Load the clr.py resource into the clr module
166162
IntPtr clr = Python.Runtime.ImportHook.GetCLRModule();
@@ -180,12 +176,7 @@ public static void Initialize(IEnumerable<string> args)
180176
{
181177
// add the contents of clr.py to the module
182178
string clr_py = reader.ReadToEnd();
183-
PyObject result = RunString(clr_py, module_globals, locals.Handle);
184-
if (null == result)
185-
{
186-
throw new PythonException();
187-
}
188-
result.Dispose();
179+
Exec(clr_py, module_globals, locals.Handle);
189180
}
190181

191182
// add the imported module to the clr module, and copy the API functions
@@ -253,11 +244,7 @@ public static void InitExt()
253244
" exec(line)\n" +
254245
" break\n";
255246

256-
PyObject r = PythonEngine.RunString(code);
257-
if (r != null)
258-
{
259-
r.Dispose();
260-
}
247+
PythonEngine.Exec(code);
261248
}
262249
catch (PythonException e)
263250
{
@@ -405,6 +392,38 @@ public static PyObject ModuleFromString(string name, string code)
405392
}
406393

407394

395+
/// <summary>
396+
/// Eval Method
397+
/// </summary>
398+
/// <remarks>
399+
/// Evaluate a Python expression and returns the result.
400+
/// It's a subset of Python eval function.
401+
/// </remarks>
402+
public static PyObject Eval(string code, IntPtr? globals = null, IntPtr? locals = null)
403+
{
404+
PyObject result = RunString(code, globals, locals, RunFlagType.Eval);
405+
return result;
406+
}
407+
408+
409+
/// <summary>
410+
/// Exec Method
411+
/// </summary>
412+
/// <remarks>
413+
/// Run a string containing Python code.
414+
/// It's a subset of Python exec function.
415+
/// </remarks>
416+
public static void Exec(string code, IntPtr? globals = null, IntPtr? locals = null)
417+
{
418+
PyObject result = RunString(code, globals, locals, RunFlagType.File);
419+
if (result.obj != Runtime.PyNone)
420+
{
421+
throw new PythonException();
422+
}
423+
result.Dispose();
424+
}
425+
426+
408427
/// <summary>
409428
/// RunString Method
410429
/// </summary>
@@ -413,8 +432,8 @@ public static PyObject ModuleFromString(string name, string code)
413432
/// executing the code string as a PyObject instance, or null if
414433
/// an exception was raised.
415434
/// </remarks>
416-
public static PyObject RunString(
417-
string code, IntPtr? globals = null, IntPtr? locals = null
435+
internal static PyObject RunString(
436+
string code, IntPtr? globals = null, IntPtr? locals = null, RunFlagType _flag = RunFlagType.File
418437
)
419438
{
420439
var borrowedGlobals = true;
@@ -439,7 +458,7 @@ public static PyObject RunString(
439458
borrowedLocals = false;
440459
}
441460

442-
var flag = (IntPtr)257; /* Py_file_input */
461+
var flag = (IntPtr)_flag;
443462

444463
try
445464
{
@@ -465,6 +484,13 @@ public static PyObject RunString(
465484
}
466485
}
467486

487+
public enum RunFlagType
488+
{
489+
Single = 256,
490+
File = 257, /* Py_file_input */
491+
Eval = 258
492+
}
493+
468494
public static class Py
469495
{
470496
public static GILState GIL()

0 commit comments

Comments
 (0)