Skip to content
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

[DYN-2322] Add PythonNet 3.7 CPython as a selectable engine. #10548

Merged
merged 18 commits into from
Apr 21, 2020
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
27 changes: 12 additions & 15 deletions src/Dynamo.All.sln
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
# Visual Studio Version 15
VisualStudioVersion = 15.0.28010.2050
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DynamoCore", "DynamoCore\DynamoCore.csproj", "{7858FA8C-475F-4B8E-B468-1F8200778CF8}"
Expand Down Expand Up @@ -99,8 +99,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "System", "System", "{88A445
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IntegrationTests", "..\test\System\IntegrationTests\IntegrationTests.csproj", "{1254D922-643B-4F0B-82BD-E9E02399B040}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Python", "Libraries\DynamoPython\Python.csproj", "{2B0F2800-6F62-4869-9074-088C5F6DCCA2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProtoTestConsoleRunner", "..\test\Engine\ProtoTestConsoleRunner\ProtoTestConsoleRunner.csproj", "{672BF8EC-1116-49F6-B253-DFCE5CF7D4C9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Units", "Libraries\DynamoUnits\Units.csproj", "{6E0A079E-85F1-45A1-AD5B-9855E4344809}"
Expand Down Expand Up @@ -149,8 +147,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DynamoCrypto", "DynamoCrypt
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InstallUpdate", "Tools\InstallUpdate\InstallUpdate.csproj", "{0ED387BC-17B5-49B7-9C1D-BF58A4A5CC4D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Legacy", "Legacy", "{398542E6-659A-48C8-86EB-33164D227C90}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataBridgeTests", "..\test\Libraries\DataBridgeTests\DataBridgeTests.csproj", "{F0AF3C6E-0E59-4511-A057-79970EA9DC34}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NUnitUtility", "Tools\NUnitUtility\NUnitUtility.csproj", "{D0DC5724-DE00-4201-A659-A9A6CF81290D}"
Expand Down Expand Up @@ -229,6 +225,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkspaceDependencyViewExte
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DocumentationBrowserViewExtension", "DocumentationBrowserViewExtension\DocumentationBrowserViewExtension.csproj", "{BE6D0644-05AF-4580-8597-B95920CE923F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DSCPython", "Libraries\DSCPython\DSCPython.csproj", "{F1541C2D-80A9-4FE7-8D9E-75A8B9FF3479}"
EndProject
reddyashish marked this conversation as resolved.
Show resolved Hide resolved
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibraryViewExtensionMSWebBrowser", "LibraryViewExtensionMSWebBrowser\LibraryViewExtensionMSWebBrowser.csproj", "{1A5DC90A-477E-4D4A-87BD-0BFB01F056CE}"
EndProject
Global
Expand Down Expand Up @@ -423,14 +421,6 @@ Global
{1254D922-643B-4F0B-82BD-E9E02399B040}.Release|Any CPU.Build.0 = Release|Any CPU
{1254D922-643B-4F0B-82BD-E9E02399B040}.Release|x64.ActiveCfg = Release|x64
{1254D922-643B-4F0B-82BD-E9E02399B040}.Release|x64.Build.0 = Release|x64
{2B0F2800-6F62-4869-9074-088C5F6DCCA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2B0F2800-6F62-4869-9074-088C5F6DCCA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2B0F2800-6F62-4869-9074-088C5F6DCCA2}.Debug|x64.ActiveCfg = Debug|x64
{2B0F2800-6F62-4869-9074-088C5F6DCCA2}.Debug|x64.Build.0 = Debug|x64
{2B0F2800-6F62-4869-9074-088C5F6DCCA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2B0F2800-6F62-4869-9074-088C5F6DCCA2}.Release|Any CPU.Build.0 = Release|Any CPU
{2B0F2800-6F62-4869-9074-088C5F6DCCA2}.Release|x64.ActiveCfg = Release|x64
{2B0F2800-6F62-4869-9074-088C5F6DCCA2}.Release|x64.Build.0 = Release|x64
{672BF8EC-1116-49F6-B253-DFCE5CF7D4C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{672BF8EC-1116-49F6-B253-DFCE5CF7D4C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{672BF8EC-1116-49F6-B253-DFCE5CF7D4C9}.Debug|x64.ActiveCfg = Debug|x64
Expand Down Expand Up @@ -823,6 +813,14 @@ Global
{BE6D0644-05AF-4580-8597-B95920CE923F}.Release|Any CPU.Build.0 = Release|Any CPU
{BE6D0644-05AF-4580-8597-B95920CE923F}.Release|x64.ActiveCfg = Release|x64
{BE6D0644-05AF-4580-8597-B95920CE923F}.Release|x64.Build.0 = Release|x64
{F1541C2D-80A9-4FE7-8D9E-75A8B9FF3479}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F1541C2D-80A9-4FE7-8D9E-75A8B9FF3479}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F1541C2D-80A9-4FE7-8D9E-75A8B9FF3479}.Debug|x64.ActiveCfg = Debug|x64
{F1541C2D-80A9-4FE7-8D9E-75A8B9FF3479}.Debug|x64.Build.0 = Debug|x64
{F1541C2D-80A9-4FE7-8D9E-75A8B9FF3479}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F1541C2D-80A9-4FE7-8D9E-75A8B9FF3479}.Release|Any CPU.Build.0 = Release|Any CPU
{F1541C2D-80A9-4FE7-8D9E-75A8B9FF3479}.Release|x64.ActiveCfg = Release|x64
{F1541C2D-80A9-4FE7-8D9E-75A8B9FF3479}.Release|x64.Build.0 = Release|x64
{1A5DC90A-477E-4D4A-87BD-0BFB01F056CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1A5DC90A-477E-4D4A-87BD-0BFB01F056CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1A5DC90A-477E-4D4A-87BD-0BFB01F056CE}.Debug|x64.ActiveCfg = Debug|Any CPU
Expand Down Expand Up @@ -859,7 +857,6 @@ Global
{C70FE632-5500-4C57-B3D6-9B5574137551} = {0355EB79-6961-4B8A-8F66-035D4EC0C9FE}
{88A44558-9148-4F1C-876B-46472793F3D6} = {F4D44BC0-32CF-4E58-AD2A-F19CE1450B00}
{1254D922-643B-4F0B-82BD-E9E02399B040} = {88A44558-9148-4F1C-876B-46472793F3D6}
{2B0F2800-6F62-4869-9074-088C5F6DCCA2} = {398542E6-659A-48C8-86EB-33164D227C90}
{672BF8EC-1116-49F6-B253-DFCE5CF7D4C9} = {0355EB79-6961-4B8A-8F66-035D4EC0C9FE}
{6E0A079E-85F1-45A1-AD5B-9855E4344809} = {FA7BE306-A3B0-45FA-9D87-0C69E6932C13}
{9B4FDC96-E2F9-4B8F-894A-4294405D50E7} = {FA7BE306-A3B0-45FA-9D87-0C69E6932C13}
Expand All @@ -873,7 +870,6 @@ Global
{CCB6E56B-2DA1-4EBA-A1F9-E8510E129D12} = {FA7BE306-A3B0-45FA-9D87-0C69E6932C13}
{A84E15A2-6735-4575-A1DA-7C64AF7582B1} = {D114C59C-CF66-4CC2-980F-9301FB4EA4E1}
{0ED387BC-17B5-49B7-9C1D-BF58A4A5CC4D} = {D114C59C-CF66-4CC2-980F-9301FB4EA4E1}
{398542E6-659A-48C8-86EB-33164D227C90} = {FA7BE306-A3B0-45FA-9D87-0C69E6932C13}
{F0AF3C6E-0E59-4511-A057-79970EA9DC34} = {0E492D35-2310-4849-9694-A2A53C09F21B}
{D0DC5724-DE00-4201-A659-A9A6CF81290D} = {D114C59C-CF66-4CC2-980F-9301FB4EA4E1}
{76686ED6-E759-4772-81C2-768740BE13FA} = {FA7BE306-A3B0-45FA-9D87-0C69E6932C13}
Expand Down Expand Up @@ -904,6 +900,7 @@ Global
{47D2166C-5261-4093-9660-E72B7035E666} = {88D45B00-E564-41DB-B57C-9509646CAA49}
{5E76AAB3-6302-473E-9655-081B53FB1419} = {88D45B00-E564-41DB-B57C-9509646CAA49}
{BE6D0644-05AF-4580-8597-B95920CE923F} = {88D45B00-E564-41DB-B57C-9509646CAA49}
{F1541C2D-80A9-4FE7-8D9E-75A8B9FF3479} = {FA7BE306-A3B0-45FA-9D87-0C69E6932C13}
{1A5DC90A-477E-4D4A-87BD-0BFB01F056CE} = {88D45B00-E564-41DB-B57C-9509646CAA49}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
Expand Down
1 change: 1 addition & 0 deletions src/DynamoApplications/PathResolvers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public SandboxPathResolver(string preloaderLocation)
"DSCoreNodes.dll",
"DSOffice.dll",
"DSIronPython.dll",
"DSCPython.dll",
"FunctionObject.ds",
"BuiltIn.ds",
"DynamoConversions.dll",
Expand Down
237 changes: 237 additions & 0 deletions src/Libraries/DSCPython/CPythonEvaluator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Autodesk.DesignScript.Runtime;
using Dynamo.Utilities;
using Python.Runtime;

namespace DSCPython
{
[SupressImportIntoVM]
public enum EvaluationState { Begin, Success, Failed }

[SupressImportIntoVM]
public delegate void EvaluationEventHandler(EvaluationState state,
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)
{
// TODO - it would be nice if users could modify a preference
// setting enabling the ability to load additional paths

// Container for paths that will be imported in the PythonEngine
//List<string> paths = new List<string>();

// Attempt to get the Standard Python Library
//string stdLib = pythonStandardLibPath();
reddyashish marked this conversation as resolved.
Show resolved Hide resolved

if (code != prev_code)
{
Python.Included.Installer.SetupPython().Wait();
PythonEngine.Initialize();
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;
}
}
}
}

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
{
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="engine">The engine used to do the evaluation</param>
QilongTang marked this conversation as resolved.
Show resolved Hide resolved
/// <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="engine">The engine used to do the evaluation</param>
QilongTang marked this conversation as resolved.
Show resolved Hide resolved
/// <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

}
}
Loading