10000 add a scope class to manage the context of interaction with Python an… by yagweb · Pull Request #381 · pythonnet/pythonnet · GitHub
[go: up one dir, main page]

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 a new class PyScopeManager
  • Loading branch information
yagweb committed Apr 24, 2017
commit f35d75ba8e4e68ef1ca289e7ed58c020e919c149
2 changes: 1 addition & 1 deletion src/embed_tests/TestPyScope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ public void TestVariables()
var a2 = ps.GetVariable<int>("ee");
Assert.AreEqual(220, a2);

var item = (ps as dynamic).locals();
var item = ps.Variables();
item["ee"] = new PyInt(230);
item.Dispose();
var a3 = ps.GetVariable<int>("ee");
Expand Down
77 changes: 70 additions & 7 deletions src/runtime/pyscope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@ public PyScopeException(string message)
}

/// <summary>
/// Classes implement this interface must be used with GIL obtained.
/// Classes/methods have this attribute must be used with GIL obtained.
/// </summary>
public interface IPyObject : IDisposable
public class PyGILAttribute : Attribute
{
}

public class PyScope : DynamicObject, IPyObject
[PyGIL]
public class PyScope : DynamicObject, IDisposable
{
public readonly string Name;

Expand All @@ -33,6 +34,10 @@ public class PyScope : DynamicObject, IPyObject
internal readonly IntPtr variables;

private bool isDisposed;
Copy link
Member

Choose a reason for hiding this comment

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

Private should be _isDisposed.


internal PyScopeManager Manager;

public event Action<PyScope> OnDispose;

internal static PyScope New(string name = null)
{
Expand Down Expand Up @@ -64,8 +69,6 @@ private PyScope(IntPtr ptr)
this.Name = this.GetVariable<string>("__name__");
}

public event Action<PyScope> OnDispose;

public PyDict Variables()
{
Runtime.XIncref(variables);
Expand All @@ -81,7 +84,7 @@ public PyScope NewScope()

public void ImportAllFromScope(string name)
{
var scope = Py.GetScope(name);
var scope = Manager.Get(name);
ImportAllFromScope(scope);
}

Expand All @@ -96,7 +99,7 @@ public void ImportAllFromScope(PyScope scope)

public void ImportScope(string name, string asname = null)
{
var scope = Py.GetScope(name);
var scope = Manager.Get(name);
if(asname == null)
{
asname = name;
Expand Down Expand Up @@ -436,4 +439,64 @@ public void Dispose()
Dispose();
}
}

public class PyScopeManager
{
private Dictionary<string, PyScope> NamedScopes = new Dictionary<string, PyScope>();

[PyGIL]
public PyScope Create()
{
var scope = PyScope.New();
scope.Manager = this;
return scope;
}

[PyGIL]
public PyScope Create(string name)
{
if (String.IsNullOrEmpty(name))
{
throw new PyScopeException("Name of ScopeStorage must not be empty");
}
if (name != null && NamedScopes.ContainsKey(name))
Copy link
Member

Choose a reason for hiding this comment

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

Contains(name)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, I'm not quite understand?

Copy link
Member

Choose a reason for hiding this comment

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

You already defined a member function Contains, use that one.

{
throw new PyScopeException(String.Format("ScopeStorage '{0}' has existed", name));
}
var scope = PyScope.New(name);
scope.Manager = this;
scope.OnDispose += Remove;
NamedScopes[name] = scope;
return scope;
}

public bool Contains(string name)
{
return NamedScopes.ContainsKey(name);
}

public PyScope Get(string name)
{
if (name != null && NamedScopes.ContainsKey(name))
{
return NamedScopes[name];
}
throw new PyScopeException(String.Format("ScopeStorage '{0}' not exist", name));
}

public void Remove(PyScope scope)
{
NamedScopes.Remove(scope.Name);
}

[PyGIL]
public void Clear()
{
var scopes = NamedScopes.Values.ToList();
foreach (var scope in scopes)
{
scope.Dispose();
}
}
}
}
49 changes: 4 additions & 45 deletions 6D4E src/runtime/pythonengine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ public static void Shutdown()
{
if (initialized)
{
Py.ClearScopes();
Py.PyScopeManager.Clear();
Marshal.FreeHGlobal(_pythonHome);
_pythonHome = IntPtr.Zero;
Marshal.FreeHGlobal(_programName);
Expand Down Expand Up @@ -547,61 +547,20 @@ public static GILState GIL()
return new GILState();
}

private static Dictionary<string, PyScope> NamedScopes = new Dictionary<string, PyScope>();
internal static PyScopeManager PyScopeManager = new PyScopeManager();

public static PyScope CreateScope()
{
var scope = PyScope.New();
var scope = PyScopeManager.Create();
return scope;
}

9E7A
public static PyScope CreateScope(string name)
Copy link
Member

Choose a reason for hiding this comment

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

Should have a default parameter of null.

Copy link
Contributor Author
@yagweb yagweb Apr 7, 2017

Choose a reason for hiding this comment

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

By contrast, I want to split the two methods CreateScope() and CreateScope(string name).
Pass null to the name will be forbidden in the future.

CreateScope() is unique, CreateScope(string name) will be put in the ScopeManager class.

{
if (String.IsNullOrEmpty(name))
{
throw new PyScopeException("Name of ScopeStorage must not be empty");
}
if (name != null && NamedScopes.ContainsKey(name))
{
throw new PyScopeException(String.Format("ScopeStorage '{0}' has existed", name));
}
var scope = PyScope.New(name);
if (name != null)
{
NamedScopes[name] = scope;
scope.OnDispose += RemoveScope;
}
var scope = PyScopeManager.Create(name);
return scope;
}

public static bool ContainsScope(string name)
{
return NamedScopes.ContainsKey(name);
}

public static PyScope GetScope(string name)
{
if (name != null && NamedScopes.ContainsKey(name))
{
return NamedScopes[name];
}
throw new PyScopeException(String.Format("ScopeStorage '{0}' not exist", name));
}

internal static void RemoveScope(PyScope scope)
{
NamedScopes.Remove(scope.Name);
}

internal static void ClearScopes()
{
var scopes = NamedScopes.Values.ToList();
foreach (var scope in scopes)
{
scope.Dispose();
}
}

public class GILState : IDisposable
{
private IntPtr state;
Expand Down
4 changes: 2 additions & 2 deletions src/runtime/runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -707,10 +707,10 @@ public static extern int Py_Main(
[DllImport(PythonDll, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr PyRun_String(string code, IntPtr st, IntPtr globals, IntPtr locals);

[DllImport(PythonDll)]
[DllImport(PythonDll, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr PyEval_EvalCode(IntPtr co, IntPtr globals, IntPtr locals);

[DllImport(PythonDll)]
[DllImport(PythonDll, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr Py_CompileString(string code, string file, IntPtr tok);

[DllImport(PythonDll, CallingConvention = CallingConvention.Cdecl)]
Expand Down
0