-
Notifications
You must be signed in to change notification settings - Fork 635
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
Incorporate DSCPython3 branch updated to .NET 4.8 #10682
Changes from 7 commits
c853363
a3da7cf
9d7b630
c811e14
734b16c
721bde3
9bcb101
2a36fa2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,244 @@ | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using Autodesk.DesignScript.Runtime; | ||
using Dynamo.Utilities; | ||
using Python.Runtime; | ||
|
||
namespace DSCPython | ||
{ | ||
[SupressImportIntoVM] | ||
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. is this class actually imported into the VM at all? 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'm not sure about this. Maybe @reddyashish ? 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. Yes, the class is imported in the VM but not these internal variables. Similar to what is done in IronPythonEvaluator class. |
||
public enum EvaluationState { Begin, Success, Failed } | ||
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. if this needs to be public can we add summary tags? |
||
|
||
[SupressImportIntoVM] | ||
public delegate void EvaluationEventHandler(EvaluationState state, | ||
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. same here(public/internal) |
||
PyScope scope, | ||
string code, | ||
IList bindingValues); | ||
|
||
/// <summary> | ||
/// Evaluates a Python script in the Dynamo context. | ||
/// </summary> | ||
[IsVisibleInDynamoLibrary(false)] | ||
public static class CPythonEvaluator | ||
{ | ||
/// <summary> stores a copy of the previously executed code</summary> | ||
private static string prev_code { get; set; } | ||
|
||
/// <summary> | ||
/// Executes a Python script with custom variable names. Script may be a string | ||
/// read from a file, for example. Pass a list of names (matching the variable | ||
/// names in the script) to bindingNames and pass a corresponding list of values | ||
/// to bindingValues. | ||
/// </summary> | ||
/// <param name="code">Python script as a string.</param> | ||
/// <param name="bindingNames">Names of values referenced in Python script.</param> | ||
/// <param name="bindingValues">Values referenced in Python script.</param> | ||
public static object EvaluatePythonScript( | ||
string code, | ||
IList bindingNames, | ||
[ArbitraryDimensionArrayImport] IList bindingValues) | ||
{ | ||
if (code != prev_code) | ||
{ | ||
Python.Included.Installer.SetupPython().Wait(); | ||
|
||
if (!PythonEngine.IsInitialized) | ||
{ | ||
PythonEngine.Initialize(); | ||
PythonEngine.BeginAllowThreads(); | ||
} | ||
|
||
IntPtr gs = PythonEngine.AcquireLock(); | ||
try | ||
{ | ||
using (Py.GIL()) | ||
{ | ||
using (PyScope scope = Py.CreateScope()) | ||
{ | ||
int amt = Math.Min(bindingNames.Count, bindingValues.Count); | ||
|
||
for (int i = 0; i < amt; i++) | ||
{ | ||
scope.Set((string)bindingNames[i], InputMarshaler.Marshal(bindingValues[i]).ToPython()); | ||
} | ||
|
||
try | ||
{ | ||
OnEvaluationBegin(scope, code, bindingValues); | ||
scope.Exec(code); | ||
OnEvaluationEnd(false, scope, code, bindingValues); | ||
|
||
var result = scope.Contains("OUT") ? scope.Get("OUT") : null; | ||
|
||
return OutputMarshaler.Marshal(result); | ||
} | ||
catch (Exception e) | ||
{ | ||
OnEvaluationEnd(false, scope, code, bindingValues); | ||
throw e; | ||
} | ||
} | ||
} | ||
} | ||
catch (PythonException pe) | ||
{ | ||
throw pe; | ||
} | ||
finally | ||
{ | ||
PythonEngine.ReleaseLock(gs); | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
#region Marshalling | ||
|
||
/// <summary> | ||
/// Data Marshaler for all data coming into a Python node. | ||
/// </summary> | ||
[SupressImportIntoVM] | ||
public static DataMarshaler InputMarshaler | ||
{ | ||
get | ||
{ | ||
if (inputMarshaler == null) | ||
{ | ||
inputMarshaler = new DataMarshaler(); | ||
inputMarshaler.RegisterMarshaler( | ||
delegate(IList lst) | ||
{ | ||
var pyList = new PyList(); | ||
foreach (var item in lst.Cast<object>().Select(inputMarshaler.Marshal)) | ||
{ | ||
pyList.Append(item.ToPython()); | ||
} | ||
return pyList; | ||
}); | ||
inputMarshaler.RegisterMarshaler( | ||
delegate (DesignScript.Builtin.Dictionary dict) | ||
{ | ||
var pyDict = new PyDict(); | ||
foreach (var key in dict.Keys) | ||
{ | ||
pyDict.SetItem(inputMarshaler.Marshal(key).ToPython(), inputMarshaler.Marshal(dict.ValueAtKey(key)).ToPython()); | ||
} | ||
return pyDict; | ||
}); | ||
} | ||
return inputMarshaler; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Data Marshaler for all data coming out of a Python node. | ||
/// </summary> | ||
[SupressImportIntoVM] | ||
public static DataMarshaler OutputMarshaler | ||
{ | ||
get | ||
{ | ||
if (outputMarshaler == null) | ||
{ | ||
outputMarshaler = new DataMarshaler(); | ||
outputMarshaler.RegisterMarshaler( | ||
delegate (PyObject pyObj) | ||
{ | ||
if (PyList.IsListType(pyObj)) | ||
{ | ||
var pyList = new PyList(pyObj); | ||
var list = new List<object>(); | ||
foreach (PyObject item in pyList) | ||
{ | ||
list.Add(outputMarshaler.Marshal(item)); | ||
} | ||
return list; | ||
} | ||
else if (PyDict.IsDictType(pyObj)) | ||
{ | ||
var pyDict = new PyDict(pyObj); | ||
var dict = new Dictionary<object, object>(); | ||
foreach (PyObject item in pyDict.Items()) | ||
{ | ||
dict.Add( | ||
outputMarshaler.Marshal(item.GetItem(0)), | ||
outputMarshaler.Marshal(item.GetItem(1)) | ||
); | ||
} | ||
return dict; | ||
} | ||
else if(PyLong.IsLongType(pyObj)) | ||
{ | ||
return PyLong.AsLong(pyObj).ToInt64(); | ||
} | ||
else | ||
{ | ||
return outputMarshaler.Marshal(pyObj.AsManagedObject(typeof(object))); | ||
} | ||
}); | ||
} | ||
return outputMarshaler; | ||
} | ||
|
||
} | ||
|
||
private static DataMarshaler inputMarshaler; | ||
private static DataMarshaler outputMarshaler; | ||
|
||
#endregion | ||
|
||
#region Evaluation events | ||
|
||
/// <summary> | ||
/// Emitted immediately before execution begins | ||
/// </summary> | ||
[SupressImportIntoVM] | ||
public static event EvaluationEventHandler EvaluationBegin; | ||
|
||
/// <summary> | ||
/// Emitted immediately after execution ends or fails | ||
/// </summary> | ||
[SupressImportIntoVM] | ||
public static event EvaluationEventHandler EvaluationEnd; | ||
|
||
/// <summary> | ||
/// Called immediately before evaluation starts | ||
/// </summary> | ||
/// <param name="scope">The scope in which the code is executed</param> | ||
/// <param name="code">The code to be evaluated</param> | ||
/// <param name="bindingValues">The binding values - these are already added to the scope when called</param> | ||
private static void OnEvaluationBegin( PyScope scope, | ||
string code, | ||
IList bindingValues ) | ||
{ | ||
if (EvaluationBegin != null) | ||
{ | ||
EvaluationBegin(EvaluationState.Begin, scope, code, bindingValues); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Called when the evaluation has completed successfully or failed | ||
/// </summary> | ||
/// <param name="isSuccessful">Whether the evaluation succeeded or not</param> | ||
/// <param name="scope">The scope in which the code is executed</param> | ||
/// <param name="code">The code to that was evaluated</param> | ||
/// <param name="bindingValues">The binding values - these are already added to the scope when called</param> | ||
private static void OnEvaluationEnd( bool isSuccessful, | ||
PyScope scope, | ||
string code, | ||
IList bindingValues) | ||
{ | ||
if (EvaluationEnd != null) | ||
{ | ||
EvaluationEnd( isSuccessful ? EvaluationState.Success : EvaluationState.Failed, | ||
scope, code, bindingValues); | ||
} | ||
} | ||
|
||
#endregion | ||
|
||
} | ||
} |
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.
I guess this should also be added to the CLI path resolver?
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.
Thanks @mjkkirschner , I will update that. Let me know if you find anything else.