diff --git a/DSIronPython.sln b/DSIronPython.sln
index 787f0ef..678eb1f 100644
--- a/DSIronPython.sln
+++ b/DSIronPython.sln
@@ -9,6 +9,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IronPythonExtension", "Iron
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IronPythonTests", "IronPythonTests\IronPythonTests.csproj", "{E6DF2FBD-7D4D-4465-94DC-D576D737E985}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DSIronPythonEmpty", "DSironPythonEmpty\DSIronPythonEmpty.csproj", "{4B853519-34A0-494D-8A16-3E79D1C5829B}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -27,6 +29,10 @@ Global
{E6DF2FBD-7D4D-4465-94DC-D576D737E985}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E6DF2FBD-7D4D-4465-94DC-D576D737E985}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E6DF2FBD-7D4D-4465-94DC-D576D737E985}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4B853519-34A0-494D-8A16-3E79D1C5829B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4B853519-34A0-494D-8A16-3E79D1C5829B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4B853519-34A0-494D-8A16-3E79D1C5829B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4B853519-34A0-494D-8A16-3E79D1C5829B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/DSIronPython/DSIronPython.csproj b/DSIronPython/DSIronPython.csproj
index 05c7e7f..cf73c07 100644
--- a/DSIronPython/DSIronPython.csproj
+++ b/DSIronPython/DSIronPython.csproj
@@ -29,18 +29,6 @@
-
-
diff --git a/DSIronPython/pkg.json b/DSIronPython/pkg.json
index 8ade97b..a63abe8 100644
--- a/DSIronPython/pkg.json
+++ b/DSIronPython/pkg.json
@@ -15,5 +15,5 @@
"site_url": "https://dynamobim.org/",
"repository_url": "https://github.com/DynamoDS/Dynamo",
"contains_binaries": true,
- "node_libraries": []
+ "node_libraries": [ "DSIronPythonEmpty, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" ]
}
\ No newline at end of file
diff --git a/DSironPythonEmpty/Class1.cs b/DSironPythonEmpty/Class1.cs
new file mode 100644
index 0000000..cb88ec0
--- /dev/null
+++ b/DSironPythonEmpty/Class1.cs
@@ -0,0 +1,11 @@
+namespace DSironPythonEmpty
+{
+ ///
+ /// This class/dll exists so that Dynamo knows this package is loaded,
+ /// even though it really only contains an extension.
+ ///
+ internal class Class1
+ {
+
+ }
+}
diff --git a/DSironPythonEmpty/DSIronPythonEmpty.csproj b/DSironPythonEmpty/DSIronPythonEmpty.csproj
new file mode 100644
index 0000000..063c28e
--- /dev/null
+++ b/DSironPythonEmpty/DSIronPythonEmpty.csproj
@@ -0,0 +1,12 @@
+
+
+
+
+
+ $(SolutionDir)\package_output\DSIronPython\bin\
+ net6.0
+ enable
+ enable
+
+
+
diff --git a/IronPythonExtension/IronPythonExtension.cs b/IronPythonExtension/IronPythonExtension.cs
index 89be644..6c08bf4 100644
--- a/IronPythonExtension/IronPythonExtension.cs
+++ b/IronPythonExtension/IronPythonExtension.cs
@@ -1,10 +1,12 @@
-using System;
+using Dynamo.Extensions;
+using Dynamo.Graph.Workspaces;
+using Dynamo.Logging;
+using Dynamo.PythonServices;
+using System;
using System.IO;
+using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
-using Dynamo.Extensions;
-using Dynamo.Logging;
-using Dynamo.PythonServices;
namespace IronPythonExtension
{
@@ -59,27 +61,87 @@ public void Startup(StartupParams sp)
/// Action to be invoked when the Dynamo has started up and is ready
/// for user interaction.
///
- ///
- public void Ready(ReadyParams sp)
+ ///
+ public void Ready(ReadyParams rp)
{
- var extraPath = Path.Combine(new FileInfo(Assembly.GetAssembly(typeof(IronPythonExtension)).Location).Directory.Parent.FullName, "extra");
- var alc = new IsolatedPythoContext(Path.Combine(extraPath,"DSIronPython.dll"));
- alc.LoadFromAssemblyName(new AssemblyName("DSIronPython"));
- }
+ var extraPath = Path.Combine(new FileInfo(Assembly.GetExecutingAssembly().Location).Directory.Parent.FullName, "extra");
+ var alc = new IsolatedPythonContext(Path.Combine(extraPath,$"{PythonEvaluatorAssembly}.dll"));
+ var dsIronAssem = alc.LoadFromAssemblyName(new AssemblyName(PythonEvaluatorAssembly));
- ///
- /// Action to be invoked when shutdown has begun.
- ///
+ //load the engine into Dynamo ourselves.
+ LoadPythonEngine(dsIronAssem);
+
+ //we used to do this:
+ //but it's not neccesary to load anything into the VM.
+ //instead we skip all the extra work and trigger the side effect we want
+ //which is re executing the graph after the dsIronPython evaluator is loaded into the PythonEngineManager.
+ //rp.StartupParams.LibraryLoader.LoadNodeLibrary(dsIronAssem);
+
+ if(rp.CurrentWorkspaceModel is HomeWorkspaceModel hwm)
+ {
+ foreach (var n in hwm.Nodes)
+ {
+ n.MarkNodeAsModified(true);
+ }
+ hwm.Run();
+ }
+ }
public void Shutdown()
{
// Do nothing for now
}
+
+ private static void LoadPythonEngine(Assembly assembly)
+ {
+ if (assembly == null)
+ {
+ return;
+ }
+
+ // Currently we are using try-catch to validate loaded assembly and Singleton Instance method exist
+ // but we can optimize by checking all loaded types against evaluators interface later
+ try
+ {
+ Type eType = null;
+ PropertyInfo instanceProp = null;
+ try
+ {
+ eType = assembly.GetTypes().FirstOrDefault(x => typeof(PythonEngine).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract);
+ if (eType == null) return;
+
+ instanceProp = eType?.GetProperty("Instance", BindingFlags.NonPublic | BindingFlags.Static);
+ if (instanceProp == null) return;
+ }
+ catch
+ {
+ // Ignore exceptions from iterating assembly types.
+ return;
+ }
+
+ PythonEngine engine = (PythonEngine)instanceProp.GetValue(null);
+ if (engine == null)
+ {
+ throw new Exception($"Could not get a valid PythonEngine instance by calling the {eType.Name}.Instance method");
+ }
+
+ if (PythonEngineManager.Instance.AvailableEngines.All(x => x.Name != engine.Name))
+ {
+ PythonEngineManager.Instance.AvailableEngines.Add(engine);
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new Exception($"Failed to add a Python engine from assembly {assembly.GetName().Name}.dll with error: {ex.Message}");
+ }
+ }
+
+
}
- internal class IsolatedPythoContext : AssemblyLoadContext
+ internal class IsolatedPythonContext : AssemblyLoadContext
{
private AssemblyDependencyResolver resolver;
- public IsolatedPythoContext(string libPath)
+ public IsolatedPythonContext(string libPath)
{
resolver = new AssemblyDependencyResolver(libPath);
}