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

fix bug where loading package does not re-execute graph. #4

Merged
merged 6 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 6 additions & 0 deletions DSIronPython.sln
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
12 changes: 0 additions & 12 deletions DSIronPython/DSIronPython.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,6 @@
</AssemblyAttribute>
</ItemGroup>

<!--<Target Name="Move python libs to extra" AfterTargets="Build">
<ItemGroup>
<MySourceFiles Include="$(OutputPath)\*lib\**;" />
</ItemGroup>

<Move SourceFiles="@(MySourceFiles)" DestinationFiles="$(OutputPath)..\extra\%(RecursiveDir)%(Filename)%(Extension)" />
</Target>

<Target Name="Remove Lib" AfterTargets="Move python libs to extra">
<RemoveDir Directories="$(OutputPath)\lib" />
</Target>-->

<Target Name="copypkgjson" AfterTargets="Build">
<Copy SourceFiles="pkg.json" DestinationFolder="$(OutputPath)..\"/>
</Target>
Expand Down
2 changes: 1 addition & 1 deletion DSIronPython/pkg.json
Original file line number Diff line number Diff line change
Expand Up @@ -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" ]
}
11 changes: 11 additions & 0 deletions DSironPythonEmpty/Class1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace DSironPythonEmpty
{
/// <summary>
/// This class/dll exists so that Dynamo knows this package is loaded,
/// even though it really only contains an extension.
/// </summary>
internal class Class1
{

}
}
12 changes: 12 additions & 0 deletions DSironPythonEmpty/DSIronPythonEmpty.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<ImportGroup Label="PropertySheets">
<Import Project="$(SolutionDir)Config\shared.props" />
</ImportGroup>
<PropertyGroup>
<OutputPath>$(SolutionDir)\package_output\DSIronPython\bin\</OutputPath>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
92 changes: 77 additions & 15 deletions IronPythonExtension/IronPythonExtension.cs
Original file line number Diff line number Diff line change
@@ -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
{
Expand Down Expand Up @@ -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.
/// </summary>
/// <param name="sp"></param>
public void Ready(ReadyParams sp)
/// <param name="rp"></param>
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));

/// <summary>
/// Action to be invoked when shutdown has begun.
/// </summary>
//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);
}
Expand Down