Skip to content

Commit

Permalink
Seperate APIs for simple expression and multiple lines. Make them ext…
Browse files Browse the repository at this point in the history
…ension methods.
  • Loading branch information
tonybaloney committed Jan 15, 2025
1 parent e863786 commit 93aa143
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 38 deletions.
27 changes: 23 additions & 4 deletions src/CSnakes.Runtime.Tests/Python/RunTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ public class RunTests : RuntimeTestBase
[Fact]
public void TestSimpleString()
{
using var result = env.Execute("1+1");
using var result = env.ExecuteExpression("1+1");
Assert.Equal("2", result.ToString());
}

[Fact]
public void TestBadString()
{
Assert.Throws<PythonInvocationException>(() => env.Execute("1+"));
Assert.Throws<PythonInvocationException>(() => env.ExecuteExpression("1+"));
}

[Fact]
Expand All @@ -23,7 +23,7 @@ public void TestSimpleStringWithLocals()
{
["a"] = PyObject.From(101)
};
using var result = env.Execute("a+1", locals);
using var result = env.ExecuteExpression("a+1", locals);
Assert.Equal("102", result.ToString());
}

Expand All @@ -38,7 +38,26 @@ public void TestSimpleStringWithLocalsAndGlobals()
{
["b"] = PyObject.From(100)
};
using var result = env.Execute("a+b+1", locals, globals);
using var result = env.ExecuteExpression("a+b+1", locals, globals);
Assert.Equal("202", result.ToString());
}

[Fact]
public void TestMultilineInput()
{
var c = """
a = 101
b = c + a
""";
var locals = new Dictionary<string, PyObject>
{
["c"] = PyObject.From(101)
};
var globals = new Dictionary<string, PyObject>
{
["d"] = PyObject.From(100)
};
using var result = env.Execute(c, locals, globals);
Assert.Equal("None", result.ToString());
}
}
4 changes: 0 additions & 4 deletions src/CSnakes.Runtime/IPythonEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,4 @@ public string Version
public bool IsDisposed();

public ILogger<IPythonEnvironment> Logger { get; }

public PyObject Execute(string code);
public PyObject Execute(string code, IDictionary<string, PyObject> locals);
public PyObject Execute(string code, IDictionary<string, PyObject> globals, IDictionary<string, PyObject> locals);
}
30 changes: 0 additions & 30 deletions src/CSnakes.Runtime/PythonEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,34 +145,4 @@ public bool IsDisposed()
{
return disposedValue;
}

public PyObject Execute(string code)
{
using (GIL.Acquire())
{
using var globals = PyObject.Create(CPythonAPI.PyDict_New());
using var locals = PyObject.Create(CPythonAPI.PyDict_New());
return CPythonAPI.PyRun_String(code, CPythonAPI.InputType.Py_eval_input, globals, locals);
}
}

public PyObject Execute(string code, IDictionary<string, PyObject> locals)
{
using (GIL.Acquire())
{
using var localsPyDict = PyObject.From<IDictionary<string, PyObject>>(locals);
using var globalsPyDict = PyObject.Create(CPythonAPI.PyDict_New());
return CPythonAPI.PyRun_String(code, CPythonAPI.InputType.Py_eval_input, globalsPyDict, localsPyDict);
}
}

public PyObject Execute(string code, IDictionary<string, PyObject> globals, IDictionary<string, PyObject> locals)
{
using (GIL.Acquire())
{
using var localsPyDict = PyObject.From<IDictionary<string, PyObject>>(locals);
using var globalsPyDict = PyObject.From<IDictionary<string, PyObject>>(globals);
return CPythonAPI.PyRun_String(code, CPythonAPI.InputType.Py_eval_input, globalsPyDict, localsPyDict);
}
}
}
75 changes: 75 additions & 0 deletions src/CSnakes.Runtime/PythonRunString.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@

using CSnakes.Runtime.CPython;
using CSnakes.Runtime.Python;

namespace CSnakes.Runtime;
public static class PythonRunString
{
/// <summary>
/// Execute a single expression in Python and return the result,
/// e.g. `1 + 1` or `len([1, 2, 3])`
/// </summary>
/// <param name="code">The Python code</param>
/// <returns>The resulting Python object</returns>
public static PyObject ExecuteExpression(this IPythonEnvironment env, string code)
{
using (GIL.Acquire())
{
using var globals = PyObject.Create(CPythonAPI.PyDict_New());
using var locals = PyObject.Create(CPythonAPI.PyDict_New());
return CPythonAPI.PyRun_String(code, CPythonAPI.InputType.Py_eval_input, globals, locals);
}
}

/// <summary>
/// Execute a single expression in Python and return the result, with locals
/// e.g. `1 + b`
/// </summary>
/// <param name="code">The Python code</param>
/// <param name="locals">A dictionary of local variables</param>
/// <returns>The resulting Python object</returns>
public static PyObject ExecuteExpression(this IPythonEnvironment env, string code, IDictionary<string, PyObject> locals)
{
using (GIL.Acquire())
{
using var localsPyDict = PyObject.From(locals);
using var globalsPyDict = PyObject.Create(CPythonAPI.PyDict_New());
return CPythonAPI.PyRun_String(code, CPythonAPI.InputType.Py_eval_input, globalsPyDict, localsPyDict);
}
}

/// <summary>
/// Execute a single expression in Python and return the result, with locals
/// e.g. `1 + b`
/// </summary>
/// <param name="code">The Python code</param>
/// <param name="locals">A dictionary of local variables</param>
/// <param name="globals">A dictionary of global variables</param>
/// <returns>The resulting Python object</returns>
public static PyObject ExecuteExpression(this IPythonEnvironment env, string code, IDictionary<string, PyObject> locals, IDictionary<string, PyObject> globals)
{
using (GIL.Acquire())
{
using var localsPyDict = PyObject.From(locals);
using var globalsPyDict = PyObject.From(globals);
return CPythonAPI.PyRun_String(code, CPythonAPI.InputType.Py_eval_input, globalsPyDict, localsPyDict);
}
}

/// <summary>
/// Execute Python program from a string, typically multiple lines of code
/// </summary>
/// <param name="code">The Python code</param>
/// <param name="locals">A dictionary of local variables</param>
/// <param name="globals">A dictionary of global variables</param>
/// <returns>Normally nothing</returns>
public static PyObject Execute(this IPythonEnvironment env, string code, IDictionary<string, PyObject> locals, IDictionary<string, PyObject> globals)
{
using (GIL.Acquire())
{
using var localsPyDict = PyObject.From(locals);
using var globalsPyDict = PyObject.From(globals);
return CPythonAPI.PyRun_String(code, CPythonAPI.InputType.Py_file_input, globalsPyDict, localsPyDict);
}
}
}

0 comments on commit 93aa143

Please sign in to comment.