From fbcdab554c601a7ddfd2a378d1df1465008b3c07 Mon Sep 17 00:00:00 2001 From: pinzart Date: Thu, 14 Dec 2023 13:32:36 -0500 Subject: [PATCH 1/6] Update PythonServices.cs --- src/NodeServices/PythonServices.cs | 36 ++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/NodeServices/PythonServices.cs b/src/NodeServices/PythonServices.cs index 62ed23fc9d4..029c6c620fa 100644 --- a/src/NodeServices/PythonServices.cs +++ b/src/NodeServices/PythonServices.cs @@ -111,12 +111,29 @@ internal static readonly Lazy public static PythonEngineManager Instance { get { return lazy.Value; } } #endregion + /// + /// A readonly collection of all the loaded Python engines + /// + public ReadOnlyCollection PythonEngines => new ReadOnlyCollection(AvailableEngines); + //TODO see DYN-6550 when hiding/replacing this obsolete field. /// /// An observable collection of all the loaded Python engines /// [Obsolete("AvailableEngines field will be replaced in a future Dynamo release.")] - public ObservableCollection AvailableEngines; + internal ObservableCollection AvailableEngines; + + public delegate void PythonEngineChangedHandler(PythonEngine engine); + + /// + /// Event that is triggered for every new engine that is added. + /// + public static PythonEngineChangedHandler PythonEngineAdded; + + /// + /// Event that is triggered for every engine that is removed. + /// + public static PythonEngineChangedHandler PythonEngineRemoved; #region Constant strings @@ -157,7 +174,7 @@ internal static readonly Lazy private PythonEngineManager() { AvailableEngines = new ObservableCollection(); - + AvailableEngines.CollectionChanged += AvailableEngines_CollectionChanged; // We check only for the default python engine because it is the only one loaded by static references. // Other engines can only be loaded through package manager LoadDefaultPythonEngine(AppDomain.CurrentDomain.GetAssemblies(). @@ -166,6 +183,21 @@ private PythonEngineManager() AppDomain.CurrentDomain.AssemblyLoad += new AssemblyLoadEventHandler((object sender, AssemblyLoadEventArgs args) => LoadDefaultPythonEngine(args.LoadedAssembly)); } + private void AvailableEngines_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + { + if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add) + { + for (var ii=0; ii< e.NewItems.Count; ii++) + PythonEngineAdded?.Invoke(e.NewItems[ii] as PythonEngine); + } + + if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove) + { + for (var ii = 0; ii < e.OldItems.Count; ii++) + PythonEngineRemoved?.Invoke(e.OldItems[ii] as PythonEngine); + } + } + private void LoadDefaultPythonEngine(Assembly a) { if (a == null || From dac5b258be6126791e844cc633456cce8eb5bfe4 Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Wed, 7 Feb 2024 15:22:55 -0500 Subject: [PATCH 2/6] update --- src/DynamoPackages/PackageLoader.cs | 2 +- src/NodeServices/PythonServices.cs | 83 ++++++++++++++++++++++++----- 2 files changed, 70 insertions(+), 15 deletions(-) diff --git a/src/DynamoPackages/PackageLoader.cs b/src/DynamoPackages/PackageLoader.cs index 352e44aa99a..93d332c16d9 100644 --- a/src/DynamoPackages/PackageLoader.cs +++ b/src/DynamoPackages/PackageLoader.cs @@ -267,7 +267,7 @@ private void TryLoadPackageIntoLibrary(Package package) PythonServices.PythonEngineManager.Instance. - LoadPythonEngine(package.LoadedAssemblies.Select(x => x.Assembly)); + LoadPythonEngine(Log, package.LoadedAssemblies.Select(x => x.Assembly)); Log($"Loaded Package {package.Name} {package.VersionName} from {package.RootDirectory}"); PackgeLoaded?.Invoke(package); diff --git a/src/NodeServices/PythonServices.cs b/src/NodeServices/PythonServices.cs index 3a03ba436af..481395ef0e7 100644 --- a/src/NodeServices/PythonServices.cs +++ b/src/NodeServices/PythonServices.cs @@ -116,15 +116,34 @@ internal static readonly Lazy /// public ReadOnlyCollection PythonEngines => new ReadOnlyCollection(AvailableEngines); - //TODO see DYN-6550 when hiding/replacing this obsolete field. /// /// An observable collection of all the loaded Python engines /// - [Obsolete("AvailableEngines field will be replaced in a future Dynamo release.")] internal ObservableCollection AvailableEngines; public delegate void PythonEngineChangedHandler(PythonEngine engine); + private Action customizeEngine; + + /// + /// Use this function to customize how Python engines should execute. + /// This function will on all existing (PythonEngines) or future python engines (on PythonEngineAdded, right after is triggered). + /// + public Action CustomizeEngine + { + set + { + customizeEngine = value; + if (customizeEngine != null) + { + foreach (var engine in AvailableEngines) + { + customizeEngine(engine); + } + } + } + } + /// /// Event that is triggered for every new engine that is added. /// @@ -149,16 +168,11 @@ internal static readonly Lazy internal static string PythonEvaluatorSingletonInstance = "Instance"; - internal static string IronPythonEvaluatorClass = "IronPythonEvaluator"; - internal static string IronPythonEvaluationMethod = "EvaluateIronPythonScript"; - internal static string CPythonEvaluatorClass = "CPythonEvaluator"; internal static string CPythonEvaluationMethod = "EvaluatePythonScript"; - internal static string IronPythonAssemblyName = "DSIronPython"; internal static string CPythonAssemblyName = "DSCPython"; - internal static string IronPythonTypeName = IronPythonAssemblyName + "." + IronPythonEvaluatorClass; internal static string CPythonTypeName = CPythonAssemblyName + "." + CPythonEvaluatorClass; internal static string PythonInputMarshalerProperty = "InputMarshaler"; @@ -188,13 +202,40 @@ private void AvailableEngines_CollectionChanged(object sender, System.Collection if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add) { for (var ii=0; ii< e.NewItems.Count; ii++) - PythonEngineAdded?.Invoke(e.NewItems[ii] as PythonEngine); + { + try + { + PythonEngineAdded?.Invoke(e.NewItems[ii] as PythonEngine); + } + catch(Exception ex) + { + Console.WriteLine("PythonEngineAdded event failed with error : " + ex.Message + Environment.NewLine + ex.StackTrace); + } + + try + { + customizeEngine.Invoke(e.NewItems[ii] as PythonEngine); + } + catch (Exception ex) + { + Console.WriteLine("CustomizeEngine failed with error : " + ex.Message + Environment.NewLine + ex.StackTrace); + } + } } if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove) { for (var ii = 0; ii < e.OldItems.Count; ii++) - PythonEngineRemoved?.Invoke(e.OldItems[ii] as PythonEngine); + { + try + { + PythonEngineRemoved?.Invoke(e.OldItems[ii] as PythonEngine); + } + catch (Exception ex) + { + Console.WriteLine("PythonEngineRemoved event failed with error : " + ex.Message + Environment.NewLine + ex.StackTrace); + } + } } } @@ -212,7 +253,7 @@ private void LoadDefaultPythonEngine(Assembly a) } catch (Exception e) { - System.Diagnostics.Debug.WriteLine($"Failed to load {CPythonAssemblyName} with error: {e.Message}"); + Console.WriteLine($"Failed to load {CPythonAssemblyName} with error: {e.Message}"); } } @@ -221,16 +262,30 @@ private PythonEngine GetEngine(string name) return AvailableEngines.FirstOrDefault(x => x.Name == name); } - // This method can throw exceptions. - internal void LoadPythonEngine(IEnumerable assemblies) + /// + /// Load Python Engines from an array of assemblies + /// + /// + internal void LoadPythonEngine(Action logger, IEnumerable assemblies) { foreach (var a in assemblies) { - LoadPythonEngine(a); + try + { + LoadPythonEngine(a); + } + catch(Exception e) + { + logger?.Invoke("Failed when looking for PythonEngines with error: " + e.Message + Environment.NewLine + e.StackTrace); + } } } - // This method can throw exceptions. + /// + /// Load Python Engines from an assembly + /// + /// + /// private void LoadPythonEngine(Assembly assembly) { if (assembly == null) From a012e57f7dca7aaa19d79914a311baa10a2d4a68 Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Wed, 14 Feb 2024 10:56:08 -0500 Subject: [PATCH 3/6] Update PythonServices.cs --- src/NodeServices/PythonServices.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/NodeServices/PythonServices.cs b/src/NodeServices/PythonServices.cs index 481395ef0e7..aeaf37f3651 100644 --- a/src/NodeServices/PythonServices.cs +++ b/src/NodeServices/PythonServices.cs @@ -126,8 +126,8 @@ internal static readonly Lazy private Action customizeEngine; /// - /// Use this function to customize how Python engines should execute. - /// This function will on all existing (PythonEngines) or future python engines (on PythonEngineAdded, right after is triggered). + /// Use this function to customize Python engine initialization. + /// This function will be called only once on all existing or future python engines (on PythonEngineAdded). /// public Action CustomizeEngine { @@ -286,6 +286,8 @@ internal void LoadPythonEngine(Action logger, IEnumerable asse /// /// /// + /// Make this public to support custom loading of Python Engines (ex load in isolated alc on the python assembly side) + /// How to transition to Dynamo loading in isolated ALC ? private void LoadPythonEngine(Assembly assembly) { if (assembly == null) From 395f9fabf178c3bd716695da69bad6c7fbce6443 Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Wed, 14 Feb 2024 15:18:44 -0500 Subject: [PATCH 4/6] Update PythonServices.cs --- src/NodeServices/PythonServices.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/NodeServices/PythonServices.cs b/src/NodeServices/PythonServices.cs index aeaf37f3651..7cd8745622d 100644 --- a/src/NodeServices/PythonServices.cs +++ b/src/NodeServices/PythonServices.cs @@ -136,10 +136,14 @@ public Action CustomizeEngine customizeEngine = value; if (customizeEngine != null) { - foreach (var engine in AvailableEngines) + try { - customizeEngine(engine); + foreach (var engine in AvailableEngines) + { + customizeEngine(engine); + } } + catch { } } } } From 75016e0179934916ebb4ace4d6be866450164c70 Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Wed, 14 Feb 2024 16:26:00 -0500 Subject: [PATCH 5/6] Update PythonServices.cs --- src/NodeServices/PythonServices.cs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/NodeServices/PythonServices.cs b/src/NodeServices/PythonServices.cs index 7cd8745622d..863a6082c82 100644 --- a/src/NodeServices/PythonServices.cs +++ b/src/NodeServices/PythonServices.cs @@ -126,24 +126,22 @@ internal static readonly Lazy private Action customizeEngine; /// - /// Use this function to customize Python engine initialization. - /// This function will be called only once on all existing or future python engines (on PythonEngineAdded). + /// Provides an easy way to run initialization code on PythonEngine instances /// - public Action CustomizeEngine + /// Action to be called on PythonEngines. + /// If true, the action will be called on existing PythonEngines. If false the action will be called when new Python engines are added. + public void ApplyInitializationAction(Action initAction, bool callOnExistingEngines = true) { - set + if (initAction != null) { - customizeEngine = value; - if (customizeEngine != null) + customizeEngine = initAction; + + if (callOnExistingEngines) { - try + foreach (var engine in AvailableEngines) { - foreach (var engine in AvailableEngines) - { - customizeEngine(engine); - } + initAction(engine); } - catch { } } } } From 0c393c2f94537be32e1e5f1e416fc4027b9b14c9 Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Wed, 14 Feb 2024 16:29:06 -0500 Subject: [PATCH 6/6] Update PythonServices.cs --- src/NodeServices/PythonServices.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/NodeServices/PythonServices.cs b/src/NodeServices/PythonServices.cs index 863a6082c82..8fdb95ea327 100644 --- a/src/NodeServices/PythonServices.cs +++ b/src/NodeServices/PythonServices.cs @@ -149,12 +149,12 @@ public void ApplyInitializationAction(Action initAction, bool call /// /// Event that is triggered for every new engine that is added. /// - public static PythonEngineChangedHandler PythonEngineAdded; + public event PythonEngineChangedHandler PythonEngineAdded; /// /// Event that is triggered for every engine that is removed. /// - public static PythonEngineChangedHandler PythonEngineRemoved; + public event PythonEngineChangedHandler PythonEngineRemoved; #region Constant strings