Thanks to visit codestin.com
Credit goes to github.com

Skip to content

add a scope class to manage the context of interaction with Python an… #381

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Jun 9, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
add unit test for Variables() method
  • Loading branch information
yagweb committed Apr 7, 2017
commit dd492f46f27c3f00dbc8e05e5507a095b866dece
25 changes: 25 additions & 0 deletions src/embed_tests/TestPyScope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,31 @@ public void TestImportScopeByName()
}
}

/// <summary>
/// Use the locals() and globals() method just like in python module
/// </summary>
[Test]
public void TestVariables()
{
(ps.Variables() as dynamic)["ee"] = new PyInt(200);
var a0 = ps.GetVariable<int>("ee");
Assert.AreEqual(200, a0);

ps.Exec("locals()['ee'] = 210");
var a1 = ps.GetVariable<int>("ee");
Assert.AreEqual(210, a1);

ps.Exec("globals()['ee'] = 220");
var a2 = ps.GetVariable<int>("ee");
Assert.AreEqual(220, a2);

var item = (ps as dynamic).locals();
item["ee"] = new PyInt(230);
item.Dispose();
var a3 = ps.GetVariable<int>("ee");
Assert.AreEqual(230, a3);
}

/// <summary>
/// Share a pyscope by multiple threads.
/// </summary>
Expand Down
49 changes: 28 additions & 21 deletions src/runtime/pyscope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,16 @@ internal PyScope(string name)
InitVariables();
}

//To compitable with the python module
//To compitable with the python module.
//Enable locals() and glocals() usage in the python script.
private void InitVariables()
{
SetVariable("locals", (Func<PyDict>)Variables);
SetVariable("globals", (Func<PyDict>)Variables);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As said before, I'm strongly against this. I don't see any advantage in this over separating globals and locals as done in the Python API.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the responses below.

}

/// <summary>
/// the dict for local variables
/// the dict for scope variables
/// </summary>
internal IntPtr variables { get; private set; }

Expand Down Expand Up @@ -96,23 +97,23 @@ public void ImportScope(PyScope scope)
}

/// <summary>
/// Import Method
/// ImportModule Method
/// </summary>
/// <remarks>
/// The import .. as .. statement in Python.
/// Import a module ,add it to the local variable dict and return the resulting module object as a PyObject.
/// Import a module ,add it to the variables dict and return the resulting module object as a PyObject.
/// </remarks>
public PyObject ImportModule(string name)
{
return ImportModule(name, name);
}

/// <summary>
/// Import Method
/// ImportModule Method
/// </summary>
/// <remarks>
/// The import .. as .. statement in Python.
/// Import a module ,add it to the local variable dict and return the resulting module object as a PyObject.
/// Import a module ,add it to the variables dict and return the resulting module object as a PyObject.
/// </remarks>
public PyObject ImportModule(string name, string asname)
{
Expand All @@ -126,6 +127,13 @@ public PyObject ImportModule(string name, string asname)
return module;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also here, imported modules are global names.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the responses below.

}

/// <summary>
/// Execute method
/// </summary>
/// <remarks>
/// Execute a Python ast and return the result as a PyObject.
/// The ast can be either an expression or stmts.
/// </remarks>
public PyObject Execute(PyObject script)
{
Check();
Expand Down Expand Up @@ -156,9 +164,9 @@ public T ExecuteVariable<T>(string name)
PyObject script = GetVariable(name);
return Execute<T>(script);
}

/// <summary>
/// Evaluate a Python expression
/// Eval method
/// </summary>
/// <remarks>
/// Evaluate a Python expression and return the result as a PyObject
Expand Down Expand Up @@ -193,7 +201,7 @@ public T Eval<T>(string code)
/// Exec Method
/// </summary>
/// <remarks>
/// Evaluate a Python script and save its local variables in the current local variable dict.
/// Exec a Python script and save its local variables in the current local variable dict.
/// </remarks>
public void Exec(string code)
{
Expand All @@ -214,13 +222,13 @@ private void Exec(string code, IntPtr _globals, IntPtr _locals)
}
Runtime.XDecref(ptr);
}

/// <summary>
/// SetLocal Method
/// SetVariable Method
/// </summary>
/// <remarks>
/// Add a new variable to local variable dict if it not exists
/// or set the value of the local variable if it exists.
/// Add a new variable to the variables dict if it not exists
/// or update its value if the variable exists.
/// </remarks>
public void SetVariable(string name, object value)
{
Expand All @@ -238,10 +246,10 @@ public void SetVariable(string name, object value)
}

/// <summary>
/// DelLocal Method
/// RemoveVariable Method
/// </summary>
/// <remarks>
/// Remove a variable from the local variable dict.
/// Remove a variable from the variables dict.
/// </remarks>
public void RemoveVariable(string name)
{
Expand All @@ -257,10 +265,10 @@ public void RemoveVariable(string name)
}

/// <summary>
/// Exists Method
/// ContainsVariable Method
/// </summary>
/// <remarks>
/// Returns true if the variable appears in the local variable dict or the global variable dict.
/// Returns true if the variable exists in the variables dict.
/// </remarks>
public bool ContainsVariable(string name)
{
Expand All @@ -270,13 +278,13 @@ public bool ContainsVariable(string name)
return Runtime.PyMapping_HasKey(variables, pyKey.obj) != 0;
}
}

/// <summary>
/// GetVariable Method
/// </summary>
/// <remarks>
/// Returns the value of the variable, local variable first.
/// If the variable is not exists, return null.
/// If the variable is not exists, throw an Exception.
/// </remarks>
public PyObject GetVariable(string name)
{
Expand Down Expand Up @@ -304,7 +312,7 @@ public PyObject GetVariable(string name)
}

/// <summary>
/// GetVariable Method
/// TryGetVariable Method
/// </summary>
/// <remarks>
/// Returns the value of the variable, local variable first.
Expand Down Expand Up @@ -380,7 +388,6 @@ public override bool TrySetMember(SetMemberBinder binder, object value)
return true;
}

// Currently, AsManagedObject method cannot accept 'dynamic' for the T parameter
private object ToManagedObject<T>(PyObject pyObj)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should return T instead of object and should actually be part of PyObject instead of privately implemented here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cannot agree more.
I thought the name AsManagedObject is too verbose because this method is heavily used, what's more, it can not accept object/dynamic as it parameter (it can be fixed easily).

I had planed to replace it for a long time. Since you mentioned it now, a new As method was added to the PyObject.

{
if(typeof(T) == typeof(PyObject) || typeof(T) == typeof(object))
Expand Down