From e9e00ba1cfc4a6ae6b4bf9c5d0ebd033fc7bc8ff Mon Sep 17 00:00:00 2001 From: glopesdev Date: Wed, 3 Jul 2024 23:07:28 +0100 Subject: [PATCH] Move ironpython package into separate repository --- .../Bonsai.Scripting.IronPython.Design.csproj | 16 -- .../Properties/launchSettings.json | 9 -- .../PythonScriptEditor.cs | 43 ----- .../PythonScriptEditorDialog.Designer.cs | 96 ----------- .../PythonScriptEditorDialog.cs | 79 --------- .../PythonScriptEditorDialog.resx | 120 -------------- .../Bonsai.Scripting.IronPython.csproj | 15 -- .../IScriptingElement.cs | 7 - .../Properties/AssemblyInfo.cs | 7 - .../Properties/launchSettings.json | 9 -- Bonsai.Scripting.IronPython/PythonEngine.cs | 38 ----- Bonsai.Scripting.IronPython/PythonHelper.cs | 66 -------- .../PythonProcessor.cs | 37 ----- .../PythonSelectMany.cs | 150 ----------------- Bonsai.Scripting.IronPython/PythonSource.cs | 122 -------------- .../PythonTransform.cs | 150 ----------------- .../ScriptingElementTypeDescriptor.cs | 33 ---- Bonsai.Scripting/Bonsai.Scripting.csproj | 14 -- Bonsai.Scripting/ExpressionCondition.cs | 76 --------- Bonsai.Scripting/ExpressionSink.cs | 85 ---------- Bonsai.Scripting/ExpressionTransform.cs | 77 --------- Bonsai.Scripting/IScriptingElement.cs | 7 - Bonsai.Scripting/Properties/AssemblyInfo.cs | 6 - .../Properties/launchSettings.json | 9 -- Bonsai.Scripting/PythonCondition.cs | 75 --------- Bonsai.Scripting/PythonEngine.cs | 23 --- Bonsai.Scripting/PythonHelper.cs | 66 -------- Bonsai.Scripting/PythonProcessor.cs | 37 ----- Bonsai.Scripting/PythonSelectMany.cs | 151 ------------------ Bonsai.Scripting/PythonSink.cs | 96 ----------- Bonsai.Scripting/PythonSource.cs | 123 -------------- Bonsai.Scripting/PythonTextWriter.cs | 54 ------- Bonsai.Scripting/PythonTransform.cs | 151 ------------------ .../ScriptingElementTypeDescriptor.cs | 33 ---- Bonsai.sln | 6 - 35 files changed, 2086 deletions(-) delete mode 100644 Bonsai.Scripting.IronPython.Design/Bonsai.Scripting.IronPython.Design.csproj delete mode 100644 Bonsai.Scripting.IronPython.Design/Properties/launchSettings.json delete mode 100644 Bonsai.Scripting.IronPython.Design/PythonScriptEditor.cs delete mode 100644 Bonsai.Scripting.IronPython.Design/PythonScriptEditorDialog.Designer.cs delete mode 100644 Bonsai.Scripting.IronPython.Design/PythonScriptEditorDialog.cs delete mode 100644 Bonsai.Scripting.IronPython.Design/PythonScriptEditorDialog.resx delete mode 100644 Bonsai.Scripting.IronPython/Bonsai.Scripting.IronPython.csproj delete mode 100644 Bonsai.Scripting.IronPython/IScriptingElement.cs delete mode 100644 Bonsai.Scripting.IronPython/Properties/AssemblyInfo.cs delete mode 100644 Bonsai.Scripting.IronPython/Properties/launchSettings.json delete mode 100644 Bonsai.Scripting.IronPython/PythonEngine.cs delete mode 100644 Bonsai.Scripting.IronPython/PythonHelper.cs delete mode 100644 Bonsai.Scripting.IronPython/PythonProcessor.cs delete mode 100644 Bonsai.Scripting.IronPython/PythonSelectMany.cs delete mode 100644 Bonsai.Scripting.IronPython/PythonSource.cs delete mode 100644 Bonsai.Scripting.IronPython/PythonTransform.cs delete mode 100644 Bonsai.Scripting.IronPython/ScriptingElementTypeDescriptor.cs delete mode 100644 Bonsai.Scripting/Bonsai.Scripting.csproj delete mode 100644 Bonsai.Scripting/ExpressionCondition.cs delete mode 100644 Bonsai.Scripting/ExpressionSink.cs delete mode 100644 Bonsai.Scripting/ExpressionTransform.cs delete mode 100644 Bonsai.Scripting/IScriptingElement.cs delete mode 100644 Bonsai.Scripting/Properties/AssemblyInfo.cs delete mode 100644 Bonsai.Scripting/Properties/launchSettings.json delete mode 100644 Bonsai.Scripting/PythonCondition.cs delete mode 100644 Bonsai.Scripting/PythonEngine.cs delete mode 100644 Bonsai.Scripting/PythonHelper.cs delete mode 100644 Bonsai.Scripting/PythonProcessor.cs delete mode 100644 Bonsai.Scripting/PythonSelectMany.cs delete mode 100644 Bonsai.Scripting/PythonSink.cs delete mode 100644 Bonsai.Scripting/PythonSource.cs delete mode 100644 Bonsai.Scripting/PythonTextWriter.cs delete mode 100644 Bonsai.Scripting/PythonTransform.cs delete mode 100644 Bonsai.Scripting/ScriptingElementTypeDescriptor.cs diff --git a/Bonsai.Scripting.IronPython.Design/Bonsai.Scripting.IronPython.Design.csproj b/Bonsai.Scripting.IronPython.Design/Bonsai.Scripting.IronPython.Design.csproj deleted file mode 100644 index b34eff060..000000000 --- a/Bonsai.Scripting.IronPython.Design/Bonsai.Scripting.IronPython.Design.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - Bonsai - IronPython Scripting Design Library - Bonsai Design Library containing editor classes for IronPython scripting in Bonsai. - Bonsai Rx Scripting Iron Python Design - true - net462 - - - - - - - - - \ No newline at end of file diff --git a/Bonsai.Scripting.IronPython.Design/Properties/launchSettings.json b/Bonsai.Scripting.IronPython.Design/Properties/launchSettings.json deleted file mode 100644 index ddd052fdd..000000000 --- a/Bonsai.Scripting.IronPython.Design/Properties/launchSettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "profiles": { - "Bonsai": { - "commandName": "Executable", - "executablePath": "$(SolutionDir)Bonsai/bin/$(Configuration)/net472/Bonsai.exe", - "commandLineArgs": "--lib:$(TargetDir)." - } - } -} \ No newline at end of file diff --git a/Bonsai.Scripting.IronPython.Design/PythonScriptEditor.cs b/Bonsai.Scripting.IronPython.Design/PythonScriptEditor.cs deleted file mode 100644 index 7829ce28d..000000000 --- a/Bonsai.Scripting.IronPython.Design/PythonScriptEditor.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using System.Drawing.Design; -using System.ComponentModel; -using System.Windows.Forms.Design; -using System.Windows.Forms; -using Bonsai.Design; - -namespace Bonsai.Scripting.IronPython.Design -{ - /// - /// Provides a user interface editor that displays a dialog box for editing - /// the Python script. - /// - public class PythonScriptEditor : RichTextEditor - { - static readonly bool IsRunningOnMono = Type.GetType("Mono.Runtime") != null; - - /// - public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) - { - return UITypeEditorEditStyle.Modal; - } - - /// - public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) - { - if (provider != null && !IsRunningOnMono) - { - var editorService = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService)); - if (editorService != null) - { - using var editorDialog = new PythonScriptEditorDialog(); - editorDialog.Script = (string)value; - return editorService.ShowDialog(editorDialog) == DialogResult.OK - ? editorDialog.Script - : value; - } - } - - return base.EditValue(context, provider, value); - } - } -} diff --git a/Bonsai.Scripting.IronPython.Design/PythonScriptEditorDialog.Designer.cs b/Bonsai.Scripting.IronPython.Design/PythonScriptEditorDialog.Designer.cs deleted file mode 100644 index d42ea56ac..000000000 --- a/Bonsai.Scripting.IronPython.Design/PythonScriptEditorDialog.Designer.cs +++ /dev/null @@ -1,96 +0,0 @@ -namespace Bonsai.Scripting.IronPython.Design -{ - partial class PythonScriptEditorDialog - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - this.scintilla = new ScintillaNET.Scintilla(); - this.okButton = new System.Windows.Forms.Button(); - this.cancelButton = new System.Windows.Forms.Button(); - this.SuspendLayout(); - // - // scintilla - // - this.scintilla.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.scintilla.Location = new System.Drawing.Point(12, 12); - this.scintilla.Name = "scintilla"; - this.scintilla.Size = new System.Drawing.Size(600, 229); - this.scintilla.TabIndex = 3; - this.scintilla.TabWidth = 2; - this.scintilla.UseTabs = false; - this.scintilla.WrapMode = ScintillaNET.WrapMode.Word; - this.scintilla.KeyDown += new System.Windows.Forms.KeyEventHandler(this.scintilla_KeyDown); - this.scintilla.TextChanged += new System.EventHandler(this.scintilla_TextChanged); - // - // okButton - // - this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK; - this.okButton.Location = new System.Drawing.Point(456, 247); - this.okButton.Name = "okButton"; - this.okButton.Size = new System.Drawing.Size(75, 23); - this.okButton.TabIndex = 1; - this.okButton.Text = "OK"; - this.okButton.UseVisualStyleBackColor = true; - // - // cancelButton - // - this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.cancelButton.Location = new System.Drawing.Point(537, 247); - this.cancelButton.Name = "cancelButton"; - this.cancelButton.Size = new System.Drawing.Size(75, 23); - this.cancelButton.TabIndex = 2; - this.cancelButton.Text = "Cancel"; - this.cancelButton.UseVisualStyleBackColor = true; - // - // PythonScriptEditorDialog - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(624, 282); - this.Controls.Add(this.cancelButton); - this.Controls.Add(this.okButton); - this.Controls.Add(this.scintilla); - this.KeyPreview = true; - this.MinimumSize = new System.Drawing.Size(640, 320); - this.Name = "PythonScriptEditorDialog"; - this.ShowIcon = false; - this.Text = "Python Script"; - this.ResumeLayout(false); - - } - - #endregion - - private ScintillaNET.Scintilla scintilla; - private System.Windows.Forms.Button okButton; - private System.Windows.Forms.Button cancelButton; - } -} diff --git a/Bonsai.Scripting.IronPython.Design/PythonScriptEditorDialog.cs b/Bonsai.Scripting.IronPython.Design/PythonScriptEditorDialog.cs deleted file mode 100644 index e4afce1b4..000000000 --- a/Bonsai.Scripting.IronPython.Design/PythonScriptEditorDialog.cs +++ /dev/null @@ -1,79 +0,0 @@ -using ScintillaNET; -using System; -using System.Drawing; -using System.Windows.Forms; - -namespace Bonsai.Scripting.IronPython.Design -{ - internal partial class PythonScriptEditorDialog : Form - { - public PythonScriptEditorDialog() - { - InitializeComponent(); - scintilla.StyleResetDefault(); - scintilla.Styles[Style.Default].Font = "Consolas"; - scintilla.Styles[Style.Default].Size = 10; - scintilla.StyleClearAll(); - - scintilla.CaretLineBackColor = ColorTranslator.FromHtml("#feefff"); - scintilla.Styles[Style.Python.Default].ForeColor = Color.Black; - scintilla.Styles[Style.Python.Character].ForeColor = ColorTranslator.FromHtml("#00aa00"); - scintilla.Styles[Style.Python.ClassName].ForeColor = Color.Black; - scintilla.Styles[Style.Python.ClassName].Bold = true; - scintilla.Styles[Style.Python.CommentLine].ForeColor = ColorTranslator.FromHtml("#adadad"); - scintilla.Styles[Style.Python.CommentBlock].ForeColor = ColorTranslator.FromHtml("#adadad"); - scintilla.Styles[Style.Python.DefName].ForeColor = Color.Black; - scintilla.Styles[Style.Python.DefName].Bold = true; - scintilla.Styles[Style.Python.Number].ForeColor = ColorTranslator.FromHtml("#800000"); - scintilla.Styles[Style.Python.String].ForeColor = ColorTranslator.FromHtml("#00aa00"); - scintilla.Styles[Style.Python.StringEol].ForeColor = ColorTranslator.FromHtml("#00aa00"); - scintilla.Styles[Style.Python.Triple].ForeColor = ColorTranslator.FromHtml("#adadad"); - scintilla.Styles[Style.Python.TripleDouble].ForeColor = ColorTranslator.FromHtml("#adadad"); - scintilla.Styles[Style.Python.Word].ForeColor = ColorTranslator.FromHtml("#0000ff"); - scintilla.Styles[Style.Python.Word2].ForeColor = ColorTranslator.FromHtml("#900090"); - scintilla.Lexer = Lexer.Python; - - scintilla.SetKeywords(0, "and del from not while as elif global or with assert else if pass yield break except import print class exec in raise continue finally is return def for lambda try"); - scintilla.SetKeywords(1, "self None True False abs divmod input open staticmethod all enumerate int ord str any eval isinstance pow sum basestring execfile issubclass print super bin file iter property tuple bool filter len range type bytearray float list raw_input unichr callable format locals reduce unicode chr frozenset long reload vars classmethod getattr map repr xrange cmp globals max reversed zip compile hasattr memoryview round __import__ complex hash min set delattr help next setattr dict hex object slice dir id oct sorted"); - } - - public string Script { get; set; } - - protected override void OnLoad(EventArgs e) - { - scintilla.Text = Script; - scintilla.EmptyUndoBuffer(); - if (Owner != null) - { - Icon = Owner.Icon; - ShowIcon = true; - } - - base.OnLoad(e); - } - - protected override void OnKeyDown(KeyEventArgs e) - { - if (e.KeyCode == Keys.Escape && !e.Handled) - { - Close(); - e.Handled = true; - } - - base.OnKeyDown(e); - } - - private void scintilla_KeyDown(object sender, KeyEventArgs e) - { - if (e.KeyCode == Keys.Enter && e.Modifiers == Keys.Control) - { - okButton.PerformClick(); - } - } - - private void scintilla_TextChanged(object sender, EventArgs e) - { - Script = scintilla.Text; - } - } -} diff --git a/Bonsai.Scripting.IronPython.Design/PythonScriptEditorDialog.resx b/Bonsai.Scripting.IronPython.Design/PythonScriptEditorDialog.resx deleted file mode 100644 index 1af7de150..000000000 --- a/Bonsai.Scripting.IronPython.Design/PythonScriptEditorDialog.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/Bonsai.Scripting.IronPython/Bonsai.Scripting.IronPython.csproj b/Bonsai.Scripting.IronPython/Bonsai.Scripting.IronPython.csproj deleted file mode 100644 index 033c59202..000000000 --- a/Bonsai.Scripting.IronPython/Bonsai.Scripting.IronPython.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - Bonsai - IronPython Scripting Library - Bonsai Scripting Library containing IronPython scripting infrastructure for Bonsai. - Bonsai Rx Scripting Iron Python - net462 - - - - - - - - - \ No newline at end of file diff --git a/Bonsai.Scripting.IronPython/IScriptingElement.cs b/Bonsai.Scripting.IronPython/IScriptingElement.cs deleted file mode 100644 index ed70047c0..000000000 --- a/Bonsai.Scripting.IronPython/IScriptingElement.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Bonsai.Scripting.IronPython -{ - interface IScriptingElement : INamedElement - { - string Description { get; } - } -} diff --git a/Bonsai.Scripting.IronPython/Properties/AssemblyInfo.cs b/Bonsai.Scripting.IronPython/Properties/AssemblyInfo.cs deleted file mode 100644 index b93832ee8..000000000 --- a/Bonsai.Scripting.IronPython/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Bonsai; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: XmlNamespacePrefix("clr-namespace:Bonsai.Scripting.IronPython", "ipy")] -[assembly: WorkflowNamespaceIcon("Bonsai:ElementIcon.Scripting")] diff --git a/Bonsai.Scripting.IronPython/Properties/launchSettings.json b/Bonsai.Scripting.IronPython/Properties/launchSettings.json deleted file mode 100644 index ddd052fdd..000000000 --- a/Bonsai.Scripting.IronPython/Properties/launchSettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "profiles": { - "Bonsai": { - "commandName": "Executable", - "executablePath": "$(SolutionDir)Bonsai/bin/$(Configuration)/net472/Bonsai.exe", - "commandLineArgs": "--lib:$(TargetDir)." - } - } -} \ No newline at end of file diff --git a/Bonsai.Scripting.IronPython/PythonEngine.cs b/Bonsai.Scripting.IronPython/PythonEngine.cs deleted file mode 100644 index 917a80609..000000000 --- a/Bonsai.Scripting.IronPython/PythonEngine.cs +++ /dev/null @@ -1,38 +0,0 @@ -using Microsoft.Scripting.Hosting; -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; - -namespace Bonsai.Scripting.IronPython -{ - static class PythonEngine - { - const string ExtensionsPath = "Extensions"; - const string RepositoryPath = "Packages"; - - internal static ScriptEngine Create() - { - var searchPaths = new List(); - var editorPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); - var editorExtensionsPath = Path.Combine(editorPath, ExtensionsPath); - var editorRepositoryPath = Path.Combine(editorPath, RepositoryPath); - var customExtensionsPath = Path.Combine(Environment.CurrentDirectory, ExtensionsPath); - searchPaths.Add(customExtensionsPath); - searchPaths.Add(editorExtensionsPath); - - var libPath = Directory.GetDirectories(editorRepositoryPath, "IronPython.StdLib.*"); - if (libPath.Length == 1) - { - var lib = Path.Combine(libPath[0], "content", "Lib"); - var sitePackages = Path.Combine(lib, "site-packages"); - searchPaths.Add(lib); - searchPaths.Add(sitePackages); - } - - var engine = global::IronPython.Hosting.Python.CreateEngine(); - engine.SetSearchPaths(searchPaths); - return engine; - } - } -} diff --git a/Bonsai.Scripting.IronPython/PythonHelper.cs b/Bonsai.Scripting.IronPython/PythonHelper.cs deleted file mode 100644 index c21dc1427..000000000 --- a/Bonsai.Scripting.IronPython/PythonHelper.cs +++ /dev/null @@ -1,66 +0,0 @@ -using IronPython.Runtime; -using IronPython.Runtime.Types; -using Microsoft.Scripting.Hosting; -using System; - -namespace Bonsai.Scripting.IronPython -{ - static class PythonHelper - { - internal const string ReturnsDecorator = "import clr\ndef returns(type):\n def decorator(func):\n func.__returntype__ = clr.GetClrType(type)\n return func\n return decorator\n\n"; - internal const string ReturnTypeAttribute = "__returntype__"; - internal const string LoadFunction = "load"; - internal const string UnloadFunction = "unload"; - internal const string ProcessFunction = "process"; - internal const string GenerateFunction = "generate"; - - internal static bool TryGetClass(ScriptScope scope, string className, out object pythonClass) - { - if (scope.TryGetVariable(className, out object variable)) - { - pythonClass = variable as OldClass; - if (pythonClass != null) - { - return true; - } - - pythonClass = variable as PythonType; - return pythonClass != null; - } - - pythonClass = null; - return false; - } - - internal static Type GetOutputType(ObjectOperations op, object pythonClass, string methodName) - { - var function = (PythonFunction)op.GetMember(pythonClass, methodName).__func__; - if (function.func_dict.TryGetValue(ReturnTypeAttribute, out object returnType)) - { - return (Type)returnType; - } - - return typeof(object); - } - - internal static Type GetOutputType(ScriptScope scope, string functionName) - { - var function = scope.GetVariable(functionName); - if (function.func_dict.TryGetValue(ReturnTypeAttribute, out object returnType)) - { - return (Type)returnType; - } - else - { - if (scope.TryGetVariable("getOutputType", out Func getOutputType)) - { - return getOutputType(); - } - else - { - return typeof(object); - } - } - } - } -} diff --git a/Bonsai.Scripting.IronPython/PythonProcessor.cs b/Bonsai.Scripting.IronPython/PythonProcessor.cs deleted file mode 100644 index f5c8a6861..000000000 --- a/Bonsai.Scripting.IronPython/PythonProcessor.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Microsoft.Scripting.Hosting; -using System; - -namespace Bonsai.Scripting.IronPython -{ - class PythonProcessor - { - internal PythonProcessor(ScriptScope scope) - { - scope.TryGetVariable(PythonHelper.LoadFunction, out Action load); - scope.TryGetVariable(PythonHelper.UnloadFunction, out Action unload); - Process = scope.GetVariable>(PythonHelper.ProcessFunction); - Load = load; - Unload = unload; - } - - internal PythonProcessor(ObjectOperations op, object processorClass) - { - var processor = (object)op.CreateInstance(processorClass); - Process = op.GetMember>(processor, PythonHelper.ProcessFunction); - if (op.ContainsMember(processor, PythonHelper.UnloadFunction)) - { - Unload = op.GetMember(processor, PythonHelper.UnloadFunction); - } - if (op.ContainsMember(processor, PythonHelper.LoadFunction)) - { - Load = op.GetMember(processor, PythonHelper.LoadFunction); - } - } - - internal Action Load { get; private set; } - - internal Action Unload { get; private set; } - - internal Func Process { get; private set; } - } -} diff --git a/Bonsai.Scripting.IronPython/PythonSelectMany.cs b/Bonsai.Scripting.IronPython/PythonSelectMany.cs deleted file mode 100644 index bdf4a219e..000000000 --- a/Bonsai.Scripting.IronPython/PythonSelectMany.cs +++ /dev/null @@ -1,150 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.ComponentModel; -using Microsoft.Scripting.Hosting; -using Bonsai.Expressions; -using System.Reactive.Linq; -using System.Linq.Expressions; -using IronPython.Runtime; - -namespace Bonsai.Scripting.IronPython -{ - /// - /// Represents an operator that uses a Python script to project each element of an - /// observable sequence into multiple elements. - /// - [DefaultProperty(nameof(Script))] - [WorkflowElementCategory(ElementCategory.Combinator)] - [TypeDescriptionProvider(typeof(PythonSelectManyTypeDescriptionProvider))] - [Description("A Python script used to project each element of the sequence into multiple elements.")] - public class PythonSelectMany : SingleArgumentExpressionBuilder, IScriptingElement - { - /// - /// Initializes a new instance of the class. - /// - public PythonSelectMany() - { - Script = "@returns(bool)\ndef process(value):\n yield True"; - } - - /// - /// Gets or sets the name of the python operator. - /// - [Category("Design")] - [Externalizable(false)] - [Description("The name of the python operator.")] - public string Name { get; set; } - - /// - /// Gets or sets a description for the python operator. - /// - [Category("Design")] - [Externalizable(false)] - [Description("A description for the python operator.")] - [Editor(DesignTypes.MultilineStringEditor, DesignTypes.UITypeEditor)] - public string Description { get; set; } - - /// - /// Gets or sets the script that determines how each element is projected into a sequence of elements. - /// - [Editor("Bonsai.Scripting.IronPython.Design.PythonScriptEditor, Bonsai.Scripting.IronPython.Design", DesignTypes.UITypeEditor)] - [Description("The script that determines how each element is projected into a sequence of elements.")] - public string Script { get; set; } - - /// - public override Expression Build(IEnumerable arguments) - { - var engine = PythonEngine.Create(); - var scope = engine.CreateScope(); - var script = PythonHelper.ReturnsDecorator + Script; - var scriptSource = engine.CreateScriptSourceFromString(script); - scriptSource.Execute(scope); - - var source = arguments.Single(); - var observableType = source.Type.GetGenericArguments()[0]; - if (PythonHelper.TryGetClass(scope, "SelectMany", out object selectMany)) - { - var classExpression = Expression.Constant(selectMany); - var opExpression = Expression.Constant(engine.Operations); - var outputType = PythonHelper.GetOutputType(engine.Operations, selectMany, PythonHelper.ProcessFunction); - return Expression.Call( - typeof(PythonTransform), - nameof(Process), - new[] { observableType, outputType }, - source, - opExpression, - classExpression); - } - else - { - var outputType = PythonHelper.GetOutputType(scope, PythonHelper.ProcessFunction); - var scopeExpression = Expression.Constant(scope); - return Expression.Call( - typeof(PythonSelectMany), - nameof(Process), - new[] { observableType, outputType }, - source, - scopeExpression); - } - } - - static IObservable Process( - IObservable source, - ObjectOperations op, - object processorClass) - { - return Observable.Defer(() => - { - var processor = new PythonProcessor(op, processorClass); - var result = source.SelectMany(input => processor.Process(input).Cast()); - processor.Load?.Invoke(); - if (processor.Unload != null) - { - return result.Finally(processor.Unload); - } - else return result; - }); - } - - static IObservable Process( - IObservable source, - ScriptScope scope) - { - var processor = new PythonProcessor(scope); - var result = source.SelectMany(input => processor.Process(input).Cast()); - if (processor.Unload != null) - { - result = result.Finally(processor.Unload); - } - - if (processor.Load != null) - { - var observable = result; - result = Observable.Defer(() => - { - processor.Load(); - return observable; - }); - } - - return result; - } - - class PythonSelectManyTypeDescriptionProvider : TypeDescriptionProvider - { - static readonly TypeDescriptionProvider parentProvider = TypeDescriptor.GetProvider(typeof(PythonSelectMany)); - - public PythonSelectManyTypeDescriptionProvider() - : base(parentProvider) - { - } - - public override ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance) - { - return new ScriptingElementTypeDescriptor(instance, - "A Python script used to project each element of the sequence into multiple elements."); - } - } - } -} diff --git a/Bonsai.Scripting.IronPython/PythonSource.cs b/Bonsai.Scripting.IronPython/PythonSource.cs deleted file mode 100644 index fe91b5373..000000000 --- a/Bonsai.Scripting.IronPython/PythonSource.cs +++ /dev/null @@ -1,122 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.ComponentModel; -using Bonsai.Expressions; -using System.Reactive.Linq; -using System.Linq.Expressions; -using IronPython.Runtime; -using System.Threading.Tasks; -using Microsoft.Scripting.Hosting; - -namespace Bonsai.Scripting.IronPython -{ - /// - /// Represents an operator that uses a Python script to generate an observable - /// sequence of values. - /// - [DefaultProperty(nameof(Script))] - [WorkflowElementCategory(ElementCategory.Source)] - [TypeDescriptionProvider(typeof(PythonSourceTypeDescriptionProvider))] - [Description("A Python script used to generate an observable sequence of values.")] - public class PythonSource : ZeroArgumentExpressionBuilder, IScriptingElement - { - /// - /// Initializes a new instance of the class. - /// - public PythonSource() - { - Script = "@returns(int)\ndef generate():\n yield 0"; - } - - /// - /// Gets or sets the name of the python source. - /// - [Category("Design")] - [Externalizable(false)] - [Description("The name of the python source.")] - public string Name { get; set; } - - /// - /// Gets or sets a description for the python source. - /// - [Category("Design")] - [Externalizable(false)] - [Description("A description for the python source.")] - [Editor(DesignTypes.MultilineStringEditor, DesignTypes.UITypeEditor)] - public string Description { get; set; } - - /// - /// Gets or sets the script that determines the operation of the source. - /// - [Editor("Bonsai.Scripting.IronPython.Design.PythonScriptEditor, Bonsai.Scripting.IronPython.Design", DesignTypes.UITypeEditor)] - [Description("The script that determines the operation of the source.")] - public string Script { get; set; } - - /// - public override Expression Build(IEnumerable arguments) - { - var engine = PythonEngine.Create(); - var scope = engine.CreateScope(); - var script = PythonHelper.ReturnsDecorator + Script; - var scriptSource = engine.CreateScriptSourceFromString(script); - scriptSource.Execute(scope); - - var scopeExpression = Expression.Constant(scope); - var outputType = PythonHelper.GetOutputType(scope, PythonHelper.GenerateFunction); - var generatorType = Expression.GetFuncType(typeof(PythonGenerator)); - var generateExpression = Expression.Call( - scopeExpression, - nameof(ScriptScope.GetVariable), - new[] { generatorType }, - Expression.Constant(PythonHelper.GenerateFunction)); - - var combinatorExpression = Expression.Constant(this); - return Expression.Call(combinatorExpression, nameof(Generate), new[] { outputType }, generateExpression); - } - - IObservable Generate(Func generate) - { - return Observable.Create(async (observer, token) => - { - await Task.Run(() => - { - try - { - var generator = generate(); - try - { - foreach (var value in generator.Cast()) - { - if (token.IsCancellationRequested) break; - observer.OnNext(value); - } - } - finally { generator.close(); } - observer.OnCompleted(); - } - catch (Exception ex) - { - observer.OnError(ex); - } - }); - }); - } - - class PythonSourceTypeDescriptionProvider : TypeDescriptionProvider - { - static readonly TypeDescriptionProvider parentProvider = TypeDescriptor.GetProvider(typeof(PythonSource)); - - public PythonSourceTypeDescriptionProvider() - : base(parentProvider) - { - } - - public override ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance) - { - return new ScriptingElementTypeDescriptor(instance, - "A Python script used to generate an observable sequence of values."); - } - } - } -} diff --git a/Bonsai.Scripting.IronPython/PythonTransform.cs b/Bonsai.Scripting.IronPython/PythonTransform.cs deleted file mode 100644 index a730f5118..000000000 --- a/Bonsai.Scripting.IronPython/PythonTransform.cs +++ /dev/null @@ -1,150 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.ComponentModel; -using Microsoft.Scripting.Hosting; -using Bonsai.Expressions; -using System.Reactive.Linq; -using System.Linq.Expressions; - -namespace Bonsai.Scripting.IronPython -{ - /// - /// Represents an operator that uses a Python script to transform each - /// element of an observable sequence. - /// - [DefaultProperty(nameof(Script))] - [WorkflowElementCategory(ElementCategory.Transform)] - [TypeDescriptionProvider(typeof(PythonTransformTypeDescriptionProvider))] - [Description("A Python script used to transform each element of the sequence.")] - public class PythonTransform : SingleArgumentExpressionBuilder, IScriptingElement - { - /// - /// Initializes a new instance of the class. - /// - public PythonTransform() - { - Script = "@returns(bool)\ndef process(value):\n return True"; - } - - /// - /// Gets or sets the name of the python transform. - /// - [Category("Design")] - [Externalizable(false)] - [Description("The name of the python transform.")] - public string Name { get; set; } - - /// - /// Gets or sets a description for the python transform. - /// - [Category("Design")] - [Externalizable(false)] - [Description("A description for the python transform.")] - [Editor(DesignTypes.MultilineStringEditor, DesignTypes.UITypeEditor)] - public string Description { get; set; } - - /// - /// Gets or sets the script that determines the operation of the transform. - /// - [Editor("Bonsai.Scripting.IronPython.Design.PythonScriptEditor, Bonsai.Scripting.IronPython.Design", DesignTypes.UITypeEditor)] - [Description("The script that determines the operation of the transform.")] - public string Script { get; set; } - - /// - public override Expression Build(IEnumerable arguments) - { - var engine = PythonEngine.Create(); - var scope = engine.CreateScope(); - var script = PythonHelper.ReturnsDecorator + Script; - var scriptSource = engine.CreateScriptSourceFromString(script); - scriptSource.Execute(scope); - - object transform; - var source = arguments.Single(); - var observableType = source.Type.GetGenericArguments()[0]; - if (PythonHelper.TryGetClass(scope, "Transform", out transform)) - { - var classExpression = Expression.Constant(transform); - var opExpression = Expression.Constant(engine.Operations); - var outputType = PythonHelper.GetOutputType(engine.Operations, transform, PythonHelper.ProcessFunction); - return Expression.Call( - typeof(PythonTransform), - nameof(Process), - new[] { observableType, outputType }, - source, - opExpression, - classExpression); - } - else - { - var outputType = PythonHelper.GetOutputType(scope, PythonHelper.ProcessFunction); - var scopeExpression = Expression.Constant(scope); - return Expression.Call( - typeof(PythonTransform), - nameof(Process), - new[] { observableType, outputType }, - source, - scopeExpression); - } - } - - static IObservable Process( - IObservable source, - ObjectOperations op, - object processorClass) - { - return Observable.Defer(() => - { - var processor = new PythonProcessor(op, processorClass); - var result = source.Select(processor.Process); - if (processor.Load != null) processor.Load(); - if (processor.Unload != null) - { - return result.Finally(processor.Unload); - } - else return result; - }); - } - - static IObservable Process( - IObservable source, - ScriptScope scope) - { - var processor = new PythonProcessor(scope); - var result = source.Select(processor.Process); - if (processor.Unload != null) - { - result = result.Finally(processor.Unload); - } - - if (processor.Load != null) - { - var observable = result; - result = Observable.Defer(() => - { - processor.Load(); - return observable; - }); - } - - return result; - } - - class PythonTransformTypeDescriptionProvider : TypeDescriptionProvider - { - static readonly TypeDescriptionProvider parentProvider = TypeDescriptor.GetProvider(typeof(PythonTransform)); - - public PythonTransformTypeDescriptionProvider() - : base(parentProvider) - { - } - - public override ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance) - { - return new ScriptingElementTypeDescriptor(instance, - "A Python script used to transform each element of the sequence."); - } - } - } -} diff --git a/Bonsai.Scripting.IronPython/ScriptingElementTypeDescriptor.cs b/Bonsai.Scripting.IronPython/ScriptingElementTypeDescriptor.cs deleted file mode 100644 index 3c5838f4a..000000000 --- a/Bonsai.Scripting.IronPython/ScriptingElementTypeDescriptor.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.ComponentModel; - -namespace Bonsai.Scripting.IronPython -{ - class ScriptingElementTypeDescriptor : CustomTypeDescriptor - { - readonly IScriptingElement element; - readonly string defaultDescription; - - public ScriptingElementTypeDescriptor(object instance, string description) - { - if (instance == null) - { - throw new ArgumentNullException(nameof(instance)); - } - - element = instance as IScriptingElement; - defaultDescription = description; - } - - public override AttributeCollection GetAttributes() - { - var description = defaultDescription; - if (element != null && !string.IsNullOrEmpty(element.Description)) - { - description = element.Description; - } - - return new AttributeCollection(new DescriptionAttribute(description)); - } - } -} diff --git a/Bonsai.Scripting/Bonsai.Scripting.csproj b/Bonsai.Scripting/Bonsai.Scripting.csproj deleted file mode 100644 index 3bfcb3edb..000000000 --- a/Bonsai.Scripting/Bonsai.Scripting.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - Bonsai - Scripting Library - Bonsai Scripting Library containing scripting infrastructure for Bonsai. - Bonsai Rx Scripting - true - net462 - - - - - - - \ No newline at end of file diff --git a/Bonsai.Scripting/ExpressionCondition.cs b/Bonsai.Scripting/ExpressionCondition.cs deleted file mode 100644 index c6c6439d9..000000000 --- a/Bonsai.Scripting/ExpressionCondition.cs +++ /dev/null @@ -1,76 +0,0 @@ -using Bonsai.Expressions; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Linq.Expressions; -using System.Reactive.Linq; -using System.Reflection; - -namespace Bonsai.Scripting -{ - /// - /// Represents an operator that uses an expression script to filter the elements - /// of an observable sequence. - /// - [Obsolete] - [DefaultProperty(nameof(Expression))] - [TypeDescriptionProvider(typeof(ExpressionConditionTypeDescriptionProvider))] - [Description("An expression script used to filter the elements of the sequence.")] - public class ExpressionCondition : SingleArgumentExpressionBuilder, IScriptingElement - { - static readonly MethodInfo whereMethod = typeof(Observable).GetMethods() - .Single(m => m.Name == nameof(Observable.Where) && - m.GetParameters().Length == 2 && - m.GetParameters()[1].ParameterType.GetGenericTypeDefinition() == typeof(Func<,>)); - - /// - /// Gets or sets the name of the expression condition. - /// - [Externalizable(false)] - [Category(nameof(CategoryAttribute.Design))] - [Description("The name of the expression condition.")] - public string Name { get; set; } - - /// - /// Gets or sets a description for the expression condition. - /// - [Externalizable(false)] - [Category(nameof(CategoryAttribute.Design))] - [Description("A description for the expression condition.")] - [Editor(DesignTypes.MultilineStringEditor, DesignTypes.UITypeEditor)] - public string Description { get; set; } - - /// - /// Gets or sets the expression that determines which elements to filter. - /// - [Editor("Bonsai.Scripting.Expressions.Design.ExpressionScriptEditor, Bonsai.Scripting.Expressions.Design", DesignTypes.UITypeEditor)] - [Description("The expression that determines which elements to filter.")] - public string Expression { get; set; } = "it"; - - /// - public override Expression Build(IEnumerable arguments) - { - var source = arguments.First(); - var sourceType = source.Type.GetGenericArguments()[0]; - var predicate = global::System.Linq.Dynamic.DynamicExpression.ParseLambda(sourceType, typeof(bool), Expression); - return System.Linq.Expressions.Expression.Call(whereMethod.MakeGenericMethod(sourceType), source, predicate); - } - - class ExpressionConditionTypeDescriptionProvider : TypeDescriptionProvider - { - static readonly TypeDescriptionProvider parentProvider = TypeDescriptor.GetProvider(typeof(ExpressionCondition)); - - public ExpressionConditionTypeDescriptionProvider() - : base(parentProvider) - { - } - - public override ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance) - { - return new ScriptingElementTypeDescriptor(instance, - "An expression script used to filter the elements of the sequence."); - } - } - } -} diff --git a/Bonsai.Scripting/ExpressionSink.cs b/Bonsai.Scripting/ExpressionSink.cs deleted file mode 100644 index c22be8793..000000000 --- a/Bonsai.Scripting/ExpressionSink.cs +++ /dev/null @@ -1,85 +0,0 @@ -using Bonsai.Expressions; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Linq.Expressions; -using System.Reactive.Linq; -using System.Reflection; - -namespace Bonsai.Scripting -{ - /// - /// Represents an operator that uses an expression script to invoke an action for - /// each element of an observable sequence. - /// - [Obsolete] - [DefaultProperty(nameof(Expression))] - [WorkflowElementCategory(ElementCategory.Sink)] - [TypeDescriptionProvider(typeof(ExpressionSinkTypeDescriptionProvider))] - [Description("An expression script used to invoke an action for each element of the sequence.")] - public class ExpressionSink : SingleArgumentExpressionBuilder, IScriptingElement - { - static readonly MethodInfo doMethod = typeof(Observable).GetMethods() - .Single(m => m.Name == nameof(Observable.Do) && - m.GetParameters().Length == 2 && - m.GetParameters()[1].ParameterType.GetGenericTypeDefinition() == typeof(Action<>)); - - /// - /// Gets or sets the name of the expression sink. - /// - [Externalizable(false)] - [Category(nameof(CategoryAttribute.Design))] - [Description("The name of the expression sink.")] - public string Name { get; set; } - - /// - /// Gets or sets a description for the expression sink. - /// - [Externalizable(false)] - [Category(nameof(CategoryAttribute.Design))] - [Description("A description for the expression sink.")] - [Editor(DesignTypes.MultilineStringEditor, DesignTypes.UITypeEditor)] - public string Description { get; set; } - - /// - /// Gets or sets the expression that determines the action to perform - /// on the input elements. - /// - [Editor("Bonsai.Scripting.Expressions.Design.ExpressionScriptEditor, Bonsai.Scripting.Expressions.Design", DesignTypes.UITypeEditor)] - [Description("The expression that determines the action to perform on the input elements.")] - public string Expression { get; set; } - - /// - public override Expression Build(IEnumerable arguments) - { - var expression = Expression; - var source = arguments.First(); - if (!string.IsNullOrEmpty(expression)) - { - var sourceType = source.Type.GetGenericArguments()[0]; - var actionType = System.Linq.Expressions.Expression.GetActionType(sourceType); - var itParameter = new[] { System.Linq.Expressions.Expression.Parameter(sourceType, string.Empty) }; - var onNext = global::System.Linq.Dynamic.DynamicExpression.ParseLambda(actionType, itParameter, null, Expression); - return System.Linq.Expressions.Expression.Call(doMethod.MakeGenericMethod(sourceType), source, onNext); - } - else return source; - } - - class ExpressionSinkTypeDescriptionProvider : TypeDescriptionProvider - { - static readonly TypeDescriptionProvider parentProvider = TypeDescriptor.GetProvider(typeof(ExpressionSink)); - - public ExpressionSinkTypeDescriptionProvider() - : base(parentProvider) - { - } - - public override ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance) - { - return new ScriptingElementTypeDescriptor(instance, - "An expression script used to invoke an action for each element of the sequence."); - } - } - } -} diff --git a/Bonsai.Scripting/ExpressionTransform.cs b/Bonsai.Scripting/ExpressionTransform.cs deleted file mode 100644 index a780a75ab..000000000 --- a/Bonsai.Scripting/ExpressionTransform.cs +++ /dev/null @@ -1,77 +0,0 @@ -using Bonsai.Expressions; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Linq.Expressions; -using System.Reactive.Linq; -using System.Reflection; - -namespace Bonsai.Scripting -{ - /// - /// Represents an operator that uses an expression script to transform each - /// element of an observable sequence. - /// - [Obsolete] - [DefaultProperty(nameof(Expression))] - [WorkflowElementCategory(ElementCategory.Transform)] - [TypeDescriptionProvider(typeof(ExpressionTransformTypeDescriptionProvider))] - [Description("An expression script used to transform each element of the sequence.")] - public class ExpressionTransform : SingleArgumentExpressionBuilder, IScriptingElement - { - static readonly MethodInfo selectMethod = typeof(Observable).GetMethods() - .Single(m => m.Name == nameof(Observable.Select) && - m.GetParameters().Length == 2 && - m.GetParameters()[1].ParameterType.GetGenericTypeDefinition() == typeof(Func<,>)); - - /// - /// Gets or sets the name of the expression transform. - /// - [Externalizable(false)] - [Category(nameof(CategoryAttribute.Design))] - [Description("The name of the expression transform.")] - public string Name { get; set; } - - /// - /// Gets or sets a description for the expression transform. - /// - [Externalizable(false)] - [Category(nameof(CategoryAttribute.Design))] - [Description("A description for the expression transform.")] - [Editor(DesignTypes.MultilineStringEditor, DesignTypes.UITypeEditor)] - public string Description { get; set; } - - /// - /// Gets or sets the expression that determines the operation of the transform. - /// - [Editor("Bonsai.Scripting.Expressions.Design.ExpressionScriptEditor, Bonsai.Scripting.Expressions.Design", DesignTypes.UITypeEditor)] - [Description("The expression that determines the operation of the transform.")] - public string Expression { get; set; } = "it"; - - /// - public override Expression Build(IEnumerable arguments) - { - var source = arguments.First(); - var sourceType = source.Type.GetGenericArguments()[0]; - var selector = global::System.Linq.Dynamic.DynamicExpression.ParseLambda(sourceType, null, Expression); - return System.Linq.Expressions.Expression.Call(selectMethod.MakeGenericMethod(sourceType, selector.ReturnType), source, selector); - } - - class ExpressionTransformTypeDescriptionProvider : TypeDescriptionProvider - { - static readonly TypeDescriptionProvider parentProvider = TypeDescriptor.GetProvider(typeof(ExpressionTransform)); - - public ExpressionTransformTypeDescriptionProvider() - : base(parentProvider) - { - } - - public override ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance) - { - return new ScriptingElementTypeDescriptor(instance, - "An expression script used to transform each element of the sequence."); - } - } - } -} diff --git a/Bonsai.Scripting/IScriptingElement.cs b/Bonsai.Scripting/IScriptingElement.cs deleted file mode 100644 index c96dd260f..000000000 --- a/Bonsai.Scripting/IScriptingElement.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Bonsai.Scripting -{ - interface IScriptingElement : INamedElement - { - string Description { get; } - } -} diff --git a/Bonsai.Scripting/Properties/AssemblyInfo.cs b/Bonsai.Scripting/Properties/AssemblyInfo.cs deleted file mode 100644 index cfe81f144..000000000 --- a/Bonsai.Scripting/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,6 +0,0 @@ -using Bonsai; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: WorkflowNamespaceIcon("Bonsai:ElementIcon.Scripting")] diff --git a/Bonsai.Scripting/Properties/launchSettings.json b/Bonsai.Scripting/Properties/launchSettings.json deleted file mode 100644 index ddd052fdd..000000000 --- a/Bonsai.Scripting/Properties/launchSettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "profiles": { - "Bonsai": { - "commandName": "Executable", - "executablePath": "$(SolutionDir)Bonsai/bin/$(Configuration)/net472/Bonsai.exe", - "commandLineArgs": "--lib:$(TargetDir)." - } - } -} \ No newline at end of file diff --git a/Bonsai.Scripting/PythonCondition.cs b/Bonsai.Scripting/PythonCondition.cs deleted file mode 100644 index 280d02760..000000000 --- a/Bonsai.Scripting/PythonCondition.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using System.Linq; -using System.ComponentModel; -using System.Reactive.Linq; - -namespace Bonsai.Scripting -{ - /// - /// Represents an operator that uses a Python script to filter the elements - /// of an observable sequence. - /// - [Obsolete] - [DefaultProperty(nameof(Script))] - [Description("A Python script used to determine which elements of the input sequence are accepted.")] - public class PythonCondition : Combinator - { - /// - /// Initializes a new instance of the class. - /// - public PythonCondition() - { - Script = "def process(value):\n return True"; - } - - /// - /// Gets or sets the script that determines the criteria for the condition. - /// - [Editor("Bonsai.Scripting.IronPython.Design.PythonScriptEditor, Bonsai.Scripting.IronPython.Design", DesignTypes.UITypeEditor)] - [Description("The script that determines the criteria for the condition.")] - public string Script { get; set; } - - /// - /// Uses a Python script to filter the elements of an observable sequence. - /// - /// - /// The type of the elements in the sequence. - /// - /// - /// The observable sequence to filter. - /// - /// - /// An observable sequence that contains the elements of the - /// sequence that satisfy the condition. - /// - public override IObservable Process(IObservable source) - { - return Observable.Defer(() => - { - var engine = PythonEngine.Create(); - var scope = engine.CreateScope(); - engine.Execute(Script, scope); - - PythonProcessor processor; - if (PythonHelper.TryGetClass(scope, "Condition", out object condition)) - { - processor = new PythonProcessor(engine.Operations, condition); - } - else processor = new PythonProcessor(scope); - - if (processor.Load != null) - { - processor.Load(); - } - - var result = source.Where(processor.Process); - if (processor.Unload != null) - { - result = result.Finally(processor.Unload); - } - - return result; - }); - } - } -} diff --git a/Bonsai.Scripting/PythonEngine.cs b/Bonsai.Scripting/PythonEngine.cs deleted file mode 100644 index d9725dfbf..000000000 --- a/Bonsai.Scripting/PythonEngine.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Microsoft.Scripting.Hosting; -using System.IO; -using System.Reflection; - -namespace Bonsai.Scripting -{ - static class PythonEngine - { - internal static ScriptEngine Create() - { - var engine = global::IronPython.Hosting.Python.CreateEngine(); - var basePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - var libPath = Directory.GetDirectories(Path.Combine(basePath, "../../../"), "IronPython.StdLib.*"); - if (libPath.Length == 1) - { - var lib = Path.Combine(libPath[0], $"content/Lib"); - var sitePackages = Path.Combine(lib, "site-packages"); - engine.SetSearchPaths(new[] { lib, sitePackages }); - } - return engine; - } - } -} diff --git a/Bonsai.Scripting/PythonHelper.cs b/Bonsai.Scripting/PythonHelper.cs deleted file mode 100644 index 4116b3ea4..000000000 --- a/Bonsai.Scripting/PythonHelper.cs +++ /dev/null @@ -1,66 +0,0 @@ -using IronPython.Runtime; -using IronPython.Runtime.Types; -using Microsoft.Scripting.Hosting; -using System; - -namespace Bonsai.Scripting -{ - static class PythonHelper - { - internal const string ReturnsDecorator = "import clr\ndef returns(type):\n def decorator(func):\n func.__returntype__ = clr.GetClrType(type)\n return func\n return decorator\n\n"; - internal const string ReturnTypeAttribute = "__returntype__"; - internal const string LoadFunction = "load"; - internal const string UnloadFunction = "unload"; - internal const string ProcessFunction = "process"; - internal const string GenerateFunction = "generate"; - - internal static bool TryGetClass(ScriptScope scope, string className, out object pythonClass) - { - if (scope.TryGetVariable(className, out object variable)) - { - pythonClass = variable as OldClass; - if (pythonClass != null) - { - return true; - } - - pythonClass = variable as PythonType; - return pythonClass != null; - } - - pythonClass = null; - return false; - } - - internal static Type GetOutputType(ObjectOperations op, object pythonClass, string methodName) - { - var function = (PythonFunction)op.GetMember(pythonClass, methodName).__func__; - if (function.func_dict.TryGetValue(ReturnTypeAttribute, out object returnType)) - { - return (Type)returnType; - } - - return typeof(object); - } - - internal static Type GetOutputType(ScriptScope scope, string functionName) - { - var function = scope.GetVariable(functionName); - if (function.func_dict.TryGetValue(ReturnTypeAttribute, out object returnType)) - { - return (Type)returnType; - } - else - { - if (scope.TryGetVariable("getOutputType", out Func getOutputType)) - { - return getOutputType(); - } - else - { - return typeof(object); - } - } - } - } -} diff --git a/Bonsai.Scripting/PythonProcessor.cs b/Bonsai.Scripting/PythonProcessor.cs deleted file mode 100644 index 19dbe7278..000000000 --- a/Bonsai.Scripting/PythonProcessor.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Microsoft.Scripting.Hosting; -using System; - -namespace Bonsai.Scripting -{ - class PythonProcessor - { - internal PythonProcessor(ScriptScope scope) - { - scope.TryGetVariable(PythonHelper.LoadFunction, out Action load); - scope.TryGetVariable(PythonHelper.UnloadFunction, out Action unload); - Process = scope.GetVariable>(PythonHelper.ProcessFunction); - Load = load; - Unload = unload; - } - - internal PythonProcessor(ObjectOperations op, object processorClass) - { - var processor = (object)op.CreateInstance(processorClass); - Process = op.GetMember>(processor, PythonHelper.ProcessFunction); - if (op.ContainsMember(processor, PythonHelper.UnloadFunction)) - { - Unload = op.GetMember(processor, PythonHelper.UnloadFunction); - } - if (op.ContainsMember(processor, PythonHelper.LoadFunction)) - { - Load = op.GetMember(processor, PythonHelper.LoadFunction); - } - } - - internal Action Load { get; private set; } - - internal Action Unload { get; private set; } - - internal Func Process { get; private set; } - } -} diff --git a/Bonsai.Scripting/PythonSelectMany.cs b/Bonsai.Scripting/PythonSelectMany.cs deleted file mode 100644 index 83eaf44c9..000000000 --- a/Bonsai.Scripting/PythonSelectMany.cs +++ /dev/null @@ -1,151 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.ComponentModel; -using Microsoft.Scripting.Hosting; -using Bonsai.Expressions; -using System.Reactive.Linq; -using System.Linq.Expressions; -using IronPython.Runtime; - -namespace Bonsai.Scripting -{ - /// - /// Represents an operator that uses a Python script to project each element of an - /// observable sequence into multiple elements. - /// - [Obsolete] - [DefaultProperty(nameof(Script))] - [WorkflowElementCategory(ElementCategory.Combinator)] - [TypeDescriptionProvider(typeof(PythonSelectManyTypeDescriptionProvider))] - [Description("A Python script used to project each element of the sequence into multiple elements.")] - public class PythonSelectMany : SingleArgumentExpressionBuilder, IScriptingElement - { - /// - /// Initializes a new instance of the class. - /// - public PythonSelectMany() - { - Script = "@returns(bool)\ndef process(value):\n yield True"; - } - - /// - /// Gets or sets the name of the python operator. - /// - [Category("Design")] - [Externalizable(false)] - [Description("The name of the python operator.")] - public string Name { get; set; } - - /// - /// Gets or sets a description for the python operator. - /// - [Category("Design")] - [Externalizable(false)] - [Description("A description for the python operator.")] - [Editor(DesignTypes.MultilineStringEditor, DesignTypes.UITypeEditor)] - public string Description { get; set; } - - /// - /// Gets or sets the script that determines how each element is projected into a sequence of elements. - /// - [Editor("Bonsai.Scripting.IronPython.Design.PythonScriptEditor, Bonsai.Scripting.IronPython.Design", DesignTypes.UITypeEditor)] - [Description("The script that determines how each element is projected into a sequence of elements.")] - public string Script { get; set; } - - /// - public override Expression Build(IEnumerable arguments) - { - var engine = PythonEngine.Create(); - var scope = engine.CreateScope(); - var script = PythonHelper.ReturnsDecorator + Script; - var scriptSource = engine.CreateScriptSourceFromString(script); - scriptSource.Execute(scope); - - var source = arguments.Single(); - var observableType = source.Type.GetGenericArguments()[0]; - if (PythonHelper.TryGetClass(scope, "SelectMany", out object selectMany)) - { - var classExpression = Expression.Constant(selectMany); - var opExpression = Expression.Constant(engine.Operations); - var outputType = PythonHelper.GetOutputType(engine.Operations, selectMany, PythonHelper.ProcessFunction); - return Expression.Call( - typeof(PythonTransform), - nameof(Process), - new[] { observableType, outputType }, - source, - opExpression, - classExpression); - } - else - { - var outputType = PythonHelper.GetOutputType(scope, PythonHelper.ProcessFunction); - var scopeExpression = Expression.Constant(scope); - return Expression.Call( - typeof(PythonSelectMany), - nameof(Process), - new[] { observableType, outputType }, - source, - scopeExpression); - } - } - - static IObservable Process( - IObservable source, - ObjectOperations op, - object processorClass) - { - return Observable.Defer(() => - { - var processor = new PythonProcessor(op, processorClass); - var result = source.SelectMany(input => processor.Process(input).Cast()); - processor.Load?.Invoke(); - if (processor.Unload != null) - { - return result.Finally(processor.Unload); - } - else return result; - }); - } - - static IObservable Process( - IObservable source, - ScriptScope scope) - { - var processor = new PythonProcessor(scope); - var result = source.SelectMany(input => processor.Process(input).Cast()); - if (processor.Unload != null) - { - result = result.Finally(processor.Unload); - } - - if (processor.Load != null) - { - var observable = result; - result = Observable.Defer(() => - { - processor.Load(); - return observable; - }); - } - - return result; - } - - class PythonSelectManyTypeDescriptionProvider : TypeDescriptionProvider - { - static readonly TypeDescriptionProvider parentProvider = TypeDescriptor.GetProvider(typeof(PythonSelectMany)); - - public PythonSelectManyTypeDescriptionProvider() - : base(parentProvider) - { - } - - public override ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance) - { - return new ScriptingElementTypeDescriptor(instance, - "A Python script used to project each element of the sequence into multiple elements."); - } - } - } -} diff --git a/Bonsai.Scripting/PythonSink.cs b/Bonsai.Scripting/PythonSink.cs deleted file mode 100644 index dce3665b3..000000000 --- a/Bonsai.Scripting/PythonSink.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using System.ComponentModel; -using Microsoft.Scripting.Hosting; -using System.Reactive.Linq; -using System.Threading.Tasks; - -namespace Bonsai.Scripting -{ - /// - /// Represents an operator that uses a Python script to invoke an action for - /// each element of an observable sequence. - /// - [Obsolete] - [DefaultProperty(nameof(Script))] - [Description("A Python script used to invoke an action for each element of the sequence.")] - public class PythonSink : Sink - { - /// - /// Initializes a new instance of the class. - /// - public PythonSink() - { - Script = "def process(value):\n return"; - } - - /// - /// Gets or sets the script that determines the operation of the sink. - /// - [Editor("Bonsai.Scripting.IronPython.Design.PythonScriptEditor, Bonsai.Scripting.IronPython.Design", DesignTypes.UITypeEditor)] - [Description("The script that determines the operation of the sink.")] - public string Script { get; set; } - - /// - /// Creates an engine for interpreting the Python script. - /// - /// - /// An instance of the class used to interpret - /// the script. - /// - protected virtual ScriptEngine CreateEngine() - { - return PythonEngine.Create(); - } - - /// - /// Uses a Python script to invoke an action for each element of an observable sequence. - /// - /// - /// The type of the elements in the sequence. - /// - /// An observable sequence. - /// - /// An observable sequence that contains the same elements of the - /// sequence, with the additional side-effect of - /// invoking the Python script on each element of the original sequence. - /// - public override IObservable Process(IObservable source) - { - return Observable.Defer(() => - { - var scriptTask = new Task(() => { }); - scriptTask.Start(); - - var engine = CreateEngine(); - var scope = engine.CreateScope(); - engine.Execute(Script, scope); - - PythonProcessor processor; - if (PythonHelper.TryGetClass(scope, "Sink", out object sink)) - { - processor = new PythonProcessor(engine.Operations, sink); - } - else processor = new PythonProcessor(scope); - - processor.Load?.Invoke(); - return source.Do(input => - { - scriptTask = scriptTask.ContinueWith(task => - { - processor.Process(input); - }); - }).Finally(() => - { - var unloadAction = processor.Unload; - if (unloadAction != null) - { - scriptTask = scriptTask.ContinueWith(task => unloadAction()); - } - - engine.Runtime.IO.OutputWriter.Close(); - scriptTask.Wait(); - }); - }); - } - } -} diff --git a/Bonsai.Scripting/PythonSource.cs b/Bonsai.Scripting/PythonSource.cs deleted file mode 100644 index 5a85e70d8..000000000 --- a/Bonsai.Scripting/PythonSource.cs +++ /dev/null @@ -1,123 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.ComponentModel; -using Bonsai.Expressions; -using System.Reactive.Linq; -using System.Linq.Expressions; -using IronPython.Runtime; -using System.Threading.Tasks; -using Microsoft.Scripting.Hosting; - -namespace Bonsai.Scripting -{ - /// - /// Represents an operator that uses a Python script to generate an observable - /// sequence of values. - /// - [Obsolete] - [DefaultProperty(nameof(Script))] - [WorkflowElementCategory(ElementCategory.Source)] - [TypeDescriptionProvider(typeof(PythonSourceTypeDescriptionProvider))] - [Description("A Python script used to generate an observable sequence of values.")] - public class PythonSource : ZeroArgumentExpressionBuilder, IScriptingElement - { - /// - /// Initializes a new instance of the class. - /// - public PythonSource() - { - Script = "@returns(int)\ndef generate():\n yield 0"; - } - - /// - /// Gets or sets the name of the python source. - /// - [Category("Design")] - [Externalizable(false)] - [Description("The name of the python source.")] - public string Name { get; set; } - - /// - /// Gets or sets a description for the python source. - /// - [Category("Design")] - [Externalizable(false)] - [Description("A description for the python source.")] - [Editor(DesignTypes.MultilineStringEditor, DesignTypes.UITypeEditor)] - public string Description { get; set; } - - /// - /// Gets or sets the script that determines the operation of the source. - /// - [Editor("Bonsai.Scripting.IronPython.Design.PythonScriptEditor, Bonsai.Scripting.IronPython.Design", DesignTypes.UITypeEditor)] - [Description("The script that determines the operation of the source.")] - public string Script { get; set; } - - /// - public override Expression Build(IEnumerable arguments) - { - var engine = PythonEngine.Create(); - var scope = engine.CreateScope(); - var script = PythonHelper.ReturnsDecorator + Script; - var scriptSource = engine.CreateScriptSourceFromString(script); - scriptSource.Execute(scope); - - var scopeExpression = Expression.Constant(scope); - var outputType = PythonHelper.GetOutputType(scope, PythonHelper.GenerateFunction); - var generatorType = Expression.GetFuncType(typeof(PythonGenerator)); - var generateExpression = Expression.Call( - scopeExpression, - nameof(ScriptScope.GetVariable), - new[] { generatorType }, - Expression.Constant(PythonHelper.GenerateFunction)); - - var combinatorExpression = Expression.Constant(this); - return Expression.Call(combinatorExpression, nameof(Generate), new[] { outputType }, generateExpression); - } - - IObservable Generate(Func generate) - { - return Observable.Create(async (observer, token) => - { - await Task.Run(() => - { - try - { - var generator = generate(); - try - { - foreach (var value in generator.Cast()) - { - if (token.IsCancellationRequested) break; - observer.OnNext(value); - } - } - finally { generator.close(); } - observer.OnCompleted(); - } - catch (Exception ex) - { - observer.OnError(ex); - } - }); - }); - } - - class PythonSourceTypeDescriptionProvider : TypeDescriptionProvider - { - static readonly TypeDescriptionProvider parentProvider = TypeDescriptor.GetProvider(typeof(PythonSource)); - - public PythonSourceTypeDescriptionProvider() - : base(parentProvider) - { - } - - public override ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance) - { - return new ScriptingElementTypeDescriptor(instance, - "A Python script used to generate an observable sequence of values."); - } - } - } -} diff --git a/Bonsai.Scripting/PythonTextWriter.cs b/Bonsai.Scripting/PythonTextWriter.cs deleted file mode 100644 index a692471ff..000000000 --- a/Bonsai.Scripting/PythonTextWriter.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using System.Text; -using System.ComponentModel; -using Microsoft.Scripting.Hosting; -using System.IO; -using Bonsai.IO; - -namespace Bonsai.Scripting -{ - /// - /// Represents an operator that uses a Python script to write each element - /// of the sequence to a text file. - /// - [Obsolete] - [Description("A Python script used to write each element of the sequence to a text file.")] - public class PythonTextWriter : PythonSink - { - StreamWriter writer; - - /// - /// Gets or sets the name of the output file. - /// - [Description("The name of the output file.")] - [Editor("Bonsai.Design.SaveFileNameEditor, Bonsai.Design", DesignTypes.UITypeEditor)] - public string FileName { get; set; } - - /// - /// Gets or sets a value indicating whether to append or overwrite the - /// specified file. - /// - [Description("Indicates whether to append or overwrite the specified file.")] - public bool Append { get; set; } - - /// - /// Gets or sets a value specifying the optional suffix used to generate - /// file names. - /// - [Description("Specifies the optional suffix used to generate file names.")] - public PathSuffix Suffix { get; set; } - - /// - protected override ScriptEngine CreateEngine() - { - var engine = base.CreateEngine(); - if (!string.IsNullOrEmpty(FileName)) - { - var fileName = PathHelper.AppendSuffix(FileName, Suffix); - writer = new StreamWriter(fileName, Append, Encoding.ASCII); - engine.Runtime.IO.SetOutput(writer.BaseStream, writer); - } - return engine; - } - } -} diff --git a/Bonsai.Scripting/PythonTransform.cs b/Bonsai.Scripting/PythonTransform.cs deleted file mode 100644 index 619a2050d..000000000 --- a/Bonsai.Scripting/PythonTransform.cs +++ /dev/null @@ -1,151 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.ComponentModel; -using Microsoft.Scripting.Hosting; -using Bonsai.Expressions; -using System.Reactive.Linq; -using System.Linq.Expressions; - -namespace Bonsai.Scripting -{ - /// - /// Represents an operator that uses a Python script to transform each - /// element of an observable sequence. - /// - [Obsolete] - [DefaultProperty(nameof(Script))] - [WorkflowElementCategory(ElementCategory.Transform)] - [TypeDescriptionProvider(typeof(PythonTransformTypeDescriptionProvider))] - [Description("A Python script used to transform each element of the sequence.")] - public class PythonTransform : SingleArgumentExpressionBuilder, IScriptingElement - { - /// - /// Initializes a new instance of the class. - /// - public PythonTransform() - { - Script = "@returns(bool)\ndef process(value):\n return True"; - } - - /// - /// Gets or sets the name of the python transform. - /// - [Category("Design")] - [Externalizable(false)] - [Description("The name of the python transform.")] - public string Name { get; set; } - - /// - /// Gets or sets a description for the python transform. - /// - [Category("Design")] - [Externalizable(false)] - [Description("A description for the python transform.")] - [Editor(DesignTypes.MultilineStringEditor, DesignTypes.UITypeEditor)] - public string Description { get; set; } - - /// - /// Gets or sets the script that determines the operation of the transform. - /// - [Editor("Bonsai.Scripting.IronPython.Design.PythonScriptEditor, Bonsai.Scripting.IronPython.Design", DesignTypes.UITypeEditor)] - [Description("The script that determines the operation of the transform.")] - public string Script { get; set; } - - /// - public override Expression Build(IEnumerable arguments) - { - var engine = PythonEngine.Create(); - var scope = engine.CreateScope(); - var script = PythonHelper.ReturnsDecorator + Script; - var scriptSource = engine.CreateScriptSourceFromString(script); - scriptSource.Execute(scope); - - object transform; - var source = arguments.Single(); - var observableType = source.Type.GetGenericArguments()[0]; - if (PythonHelper.TryGetClass(scope, "Transform", out transform)) - { - var classExpression = Expression.Constant(transform); - var opExpression = Expression.Constant(engine.Operations); - var outputType = PythonHelper.GetOutputType(engine.Operations, transform, PythonHelper.ProcessFunction); - return Expression.Call( - typeof(PythonTransform), - nameof(Process), - new[] { observableType, outputType }, - source, - opExpression, - classExpression); - } - else - { - var outputType = PythonHelper.GetOutputType(scope, PythonHelper.ProcessFunction); - var scopeExpression = Expression.Constant(scope); - return Expression.Call( - typeof(PythonTransform), - nameof(Process), - new[] { observableType, outputType }, - source, - scopeExpression); - } - } - - static IObservable Process( - IObservable source, - ObjectOperations op, - object processorClass) - { - return Observable.Defer(() => - { - var processor = new PythonProcessor(op, processorClass); - var result = source.Select(processor.Process); - if (processor.Load != null) processor.Load(); - if (processor.Unload != null) - { - return result.Finally(processor.Unload); - } - else return result; - }); - } - - static IObservable Process( - IObservable source, - ScriptScope scope) - { - var processor = new PythonProcessor(scope); - var result = source.Select(processor.Process); - if (processor.Unload != null) - { - result = result.Finally(processor.Unload); - } - - if (processor.Load != null) - { - var observable = result; - result = Observable.Defer(() => - { - processor.Load(); - return observable; - }); - } - - return result; - } - - class PythonTransformTypeDescriptionProvider : TypeDescriptionProvider - { - static readonly TypeDescriptionProvider parentProvider = TypeDescriptor.GetProvider(typeof(PythonTransform)); - - public PythonTransformTypeDescriptionProvider() - : base(parentProvider) - { - } - - public override ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance) - { - return new ScriptingElementTypeDescriptor(instance, - "A Python script used to transform each element of the sequence."); - } - } - } -} diff --git a/Bonsai.Scripting/ScriptingElementTypeDescriptor.cs b/Bonsai.Scripting/ScriptingElementTypeDescriptor.cs deleted file mode 100644 index 3b871d656..000000000 --- a/Bonsai.Scripting/ScriptingElementTypeDescriptor.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.ComponentModel; - -namespace Bonsai.Scripting -{ - class ScriptingElementTypeDescriptor : CustomTypeDescriptor - { - readonly IScriptingElement element; - readonly string defaultDescription; - - public ScriptingElementTypeDescriptor(object instance, string description) - { - if (instance == null) - { - throw new ArgumentNullException(nameof(instance)); - } - - element = instance as IScriptingElement; - defaultDescription = description; - } - - public override AttributeCollection GetAttributes() - { - var description = defaultDescription; - if (element != null && !string.IsNullOrEmpty(element.Description)) - { - description = element.Description; - } - - return new AttributeCollection(new DescriptionAttribute(description)); - } - } -} diff --git a/Bonsai.sln b/Bonsai.sln index a797ab1b2..d7ff144e7 100644 --- a/Bonsai.sln +++ b/Bonsai.sln @@ -18,16 +18,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bonsai.Vision.Design", "Bon EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bonsai.System", "Bonsai.System\Bonsai.System.csproj", "{B783D74F-CB2D-4419-B438-266CD15774FB}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bonsai.Scripting", "Bonsai.Scripting\Bonsai.Scripting.csproj", "{A341A5A1-45A6-4B35-9AB1-FE42C622F738}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bonsai.Scripting.Expressions", "Bonsai.Scripting.Expressions\Bonsai.Scripting.Expressions.csproj", "{6DAA7012-22BF-4E0B-A7DB-B7A8B2A95F0A}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bonsai.Scripting.Expressions.Design", "Bonsai.Scripting.Expressions.Design\Bonsai.Scripting.Expressions.Design.csproj", "{B9456E54-9249-4178-951A-166A6F54A206}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bonsai.Scripting.IronPython", "Bonsai.Scripting.IronPython\Bonsai.Scripting.IronPython.csproj", "{D487E501-77E3-4A1C-943E-F4F2534E3BC8}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bonsai.Scripting.IronPython.Design", "Bonsai.Scripting.IronPython.Design\Bonsai.Scripting.IronPython.Design.csproj", "{18A71178-6045-49A6-810B-1F5E50DD621F}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bonsai.Player", "Bonsai.Player\Bonsai.Player.csproj", "{156452CC-3847-4706-AC65-4FA3BECA88EF}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bonsai.Audio", "Bonsai.Audio\Bonsai.Audio.csproj", "{BFAFD84F-6D1A-4D98-B91D-BBFCEA0FACF9}"