-
Notifications
You must be signed in to change notification settings - Fork 762
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
Changes from 1 commit
8e0b1a2
72003aa
efd3798
9f50e25
add5ba8
c15555c
b0d57e9
ceaaef0
dec39c7
e117d60
904d9ed
5484451
2e063c2
dd492f4
df6a49a
f35d75b
497d7aa
60ce28b
ebf5a2b
2c3db3d
30543eb
b9dcdac
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,26 +35,21 @@ public class PyScope : DynamicObject, IDisposable | |
|
||
private bool isDisposed; | ||
|
||
internal PyScopeManager Manager; | ||
internal readonly PyScopeManager Manager; | ||
|
||
public event Action<PyScope> OnDispose; | ||
|
||
internal static PyScope New(string name = null) | ||
public PyScope(IntPtr ptr, PyScopeManager manager) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Things using |
||
{ | ||
if (name == null) | ||
if (Runtime.PyObject_Type(ptr) != Runtime.PyModuleType) | ||
{ | ||
name = ""; | ||
throw new PyScopeException("object is not a module"); | ||
} | ||
var module = Runtime.PyModule_New(name); | ||
if (module == IntPtr.Zero) | ||
if(manager == null) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Formatting, just run a |
||
{ | ||
throw new PythonException(); | ||
manager = PyScopeManager.Global; | ||
} | ||
return new PyScope(module); | ||
} | ||
|
||
private PyScope(IntPtr ptr) | ||
{ | ||
Manager = manager; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
obj = ptr; | ||
//Refcount of the variables not increase | ||
variables = Runtime.PyModule_GetDict(obj); | ||
|
@@ -77,70 +72,92 @@ public PyDict Variables() | |
|
||
public PyScope NewScope() | ||
{ | ||
var scope = PyScope.New(); | ||
scope.ImportAllFromScope(this); | ||
var scope = Manager.Create(); | ||
scope.ImportAll(this); | ||
return scope; | ||
} | ||
|
||
public void ImportAllFromScope(string name) | ||
{ | ||
var scope = Manager.Get(name); | ||
ImportAllFromScope(scope); | ||
} | ||
|
||
public void ImportAllFromScope(PyScope scope) | ||
public dynamic Import(string name, string asname = null) | ||
{ | ||
int result = Runtime.PyDict_Update(variables, scope.variables); | ||
if (result < 0) | ||
Check(); | ||
if (asname == null) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
{ | ||
throw new PythonException(); | ||
asname = name; | ||
} | ||
} | ||
|
||
public void ImportScope(string name, string asname = null) | ||
{ | ||
var scope = Manager.Get(name); | ||
if(asname == null) | ||
var scope = Manager.TryGet(name); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For
|
||
if(scope != null) | ||
{ | ||
asname = name; | ||
Import(scope, asname); | ||
return scope; | ||
} | ||
ImportScope(scope, asname); | ||
PyObject module = PythonEngine.ImportModule(name); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wrap in |
||
Import(module, asname); | ||
return module; | ||
} | ||
|
||
public void ImportScope(PyScope scope, string asname) | ||
public void Import(PyScope scope, string asname) | ||
{ | ||
this.SetVariable(asname, scope.obj); | ||
} | ||
|
||
/// <summary> | ||
/// ImportModule Method | ||
/// Import Method | ||
/// </summary> | ||
/// <remarks> | ||
/// The import .. as .. statement in Python. | ||
/// Import a module ,add it to the variables 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) | ||
public void Import(PyObject module, string asname = null) | ||
{ | ||
return ImportModule(name, name); | ||
if (asname == null) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
{ | ||
asname = module.GetAttr("__name__").ToString(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use |
||
} | ||
SetVariable(asname, module); | ||
} | ||
|
||
/// <summary> | ||
/// ImportModule Method | ||
/// </summary> | ||
/// <remarks> | ||
/// The import .. as .. statement in Python. | ||
/// 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) | ||
public void ImportAll(string name) | ||
{ | ||
Check(); | ||
var scope = Manager.TryGet(name); | ||
if(scope != null) | ||
{ | ||
ImportAll(scope); | ||
return; | ||
} | ||
PyObject module = PythonEngine.ImportModule(name); | ||
if (asname == null) | ||
ImportAll(module); | ||
} | ||
|
||
public void ImportAll(PyScope scope) | ||
{ | ||
int result = Runtime.PyDict_Update(variables, scope.variables); | ||
if (result < 0) | ||
{ | ||
asname = name; | ||
throw new PythonException(); | ||
} | ||
} | ||
|
||
public void ImportAll(PyObject module) | ||
{ | ||
if (Runtime.PyObject_Type(module.obj) != Runtime.PyModuleType) | ||
{ | ||
throw new PyScopeException("object is not a module"); | ||
} | ||
var module_dict = Runtime.PyModule_GetDict(module.obj); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This leaks a reference. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just checked, the Runtime.PyModule_GetDict method does not increase the refcount of the module dict. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, misread the docs :) |
||
int result = Runtime.PyDict_Update(variables, module_dict); | ||
if (result < 0) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This usage comes from the Update method of PyDict. |
||
{ | ||
throw new PythonException(); | ||
} | ||
} | ||
|
||
public void ImportAll(PyDict dict) | ||
{ | ||
int result = Runtime.PyDict_Update(variables, dict.obj); | ||
if (result < 0) | ||
{ | ||
throw new PythonException(); | ||
} | ||
SetVariable(asname, module); | ||
return module; | ||
} | ||
|
||
/// <summary> | ||
|
@@ -263,15 +280,6 @@ private void SetVariable(string name, IntPtr value) | |
} | ||
} | ||
|
||
public void AddVariables(PyDict dict) | ||
{ | ||
int result = Runtime.PyDict_Update(variables, dict.obj); | ||
if (result < 0) | ||
{ | ||
throw new PythonException(); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// RemoveVariable Method | ||
/// </summary> | ||
|
@@ -442,13 +450,28 @@ public void Dispose() | |
|
||
public class PyScopeManager | ||
{ | ||
public readonly static PyScopeManager Global = new PyScopeManager(); | ||
|
||
private Dictionary<string, PyScope> NamedScopes = new Dictionary<string, PyScope>(); | ||
|
||
internal PyScope NewScope(string name) | ||
{ | ||
if (name == null) | ||
{ | ||
name = ""; | ||
} | ||
var module = Runtime.PyModule_New(name); | ||
if (module == IntPtr.Zero) | ||
{ | ||
throw new PythonException(); | ||
} | ||
return new PyScope(module, this); | ||
} | ||
|
||
[PyGIL] | ||
public PyScope Create() | ||
{ | ||
var scope = PyScope.New(); | ||
scope.Manager = this; | ||
var scope = this.NewScope(null); | ||
return scope; | ||
} | ||
|
||
|
@@ -457,14 +480,13 @@ public PyScope Create(string name) | |
{ | ||
if (String.IsNullOrEmpty(name)) | ||
{ | ||
throw new PyScopeException("Name of ScopeStorage must not be empty"); | ||
throw new ArgumentNullException(nameof(name)); | ||
} | ||
if (name != null && NamedScopes.ContainsKey(name)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, I'm not quite understand? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You already defined a member function |
||
{ | ||
throw new PyScopeException(String.Format("ScopeStorage '{0}' has existed", name)); | ||
throw new PyScopeException($"PyScope '{name}' has existed"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
var scope = PyScope.New(name); | ||
scope.Manager = this; | ||
var scope = this.NewScope(name); | ||
scope.OnDispose += Remove; | ||
NamedScopes[name] = scope; | ||
return scope; | ||
|
@@ -477,11 +499,22 @@ public bool Contains(string name) | |
|
||
public PyScope Get(string name) | ||
{ | ||
if (name != null && NamedScopes.ContainsKey(name)) | ||
if (name == null) | ||
{ | ||
throw new ArgumentNullException(nameof(name)); | ||
} | ||
if (NamedScopes.ContainsKey(name)) | ||
{ | ||
return NamedScopes[name]; | ||
} | ||
throw new PyScopeException(String.Format("ScopeStorage '{0}' not exist", name)); | ||
throw new PyScopeException($"PyScope '{name}' not exist"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe |
||
} | ||
|
||
public PyScope TryGet(string name) | ||
{ | ||
PyScope value; | ||
NamedScopes.TryGetValue(name, out value); | ||
return value; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As said above, just forward the semantics of |
||
} | ||
|
||
public void Remove(PyScope scope) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -294,7 +294,7 @@ public static void Shutdown() | |
{ | ||
if (initialized) | ||
{ | ||
Py.PyScopeManager.Clear(); | ||
PyScopeManager.Global.Clear(); | ||
Marshal.FreeHGlobal(_pythonHome); | ||
_pythonHome = IntPtr.Zero; | ||
Marshal.FreeHGlobal(_programName); | ||
|
@@ -546,18 +546,16 @@ public static GILState GIL() | |
|
||
return new GILState(); | ||
} | ||
|
||
internal static PyScopeManager PyScopeManager = new PyScopeManager(); | ||
|
||
public static PyScope CreateScope() | ||
{ | ||
var scope = PyScopeManager.Create(); | ||
var scope = PyScopeManager.Global.Create(); | ||
return scope; | ||
} | ||
|
||
public static PyScope CreateScope(string name) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should have a default parameter of There was a problem hiding this comment. Choose a reason for hiding this commentThe 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). CreateScope() is unique, CreateScope(string name) will be put in the ScopeManager class. |
||
{ | ||
var scope = PyScopeManager.Create(name); | ||
var scope = PyScopeManager.Global.Create(name); | ||
return scope; | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Private should be
_isDisposed
.