Free cookie consent management tool by TermsFeed Policy Generator

source: branches/PythonScript/HeuristicLab.Scripting.Python/3.3/PythonScript.cs @ 15866

Last change on this file since 15866 was 10567, checked in by abeham, 11 years ago

#2165: Imported branch of adding python scripting support through IronPython

File size: 5.6 KB
RevLine 
[10567]1using System;
2using System.Drawing;
3using System.IO;
4using System.Reflection;
5using System.Text;
6using System.Threading;
7using HeuristicLab.Common;
8using HeuristicLab.Common.Resources;
9using HeuristicLab.Core;
10using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
11
12namespace HeuristicLab.Scripting.Python {
13  [Item("Python Script", "An empty python script.")]
14  [Creatable("Scripts")]
15  [StorableClass]
16  public sealed class PythonScript : NamedItem, IStorableContent {
17    #region Constants
18    private const string CodeTemplate =
19@"# adding imports from some HeuristicLab namespaces
20from HeuristicLab.Common import *
21from HeuristicLab.Core import *
22from HeuristicLab.Data import *
23from HeuristicLab.MainForm import MainFormManager
24
25# add paths to IronPython/Lib and further libraries
26# import sys
27# sys.path.append(r""path/to/lib"")
28
29# use 'vars' to access global variables in the variable store
30
31";
32    #endregion
33
34    #region Fields & Properties
35    public string Filename { get; set; }
36
37    public static new Image StaticItemImage {
38      get { return VSImageLibrary.Script; }
39    }
40
41    [Storable]
42    private VariableStore variableStore;
43    public VariableStore VariableStore {
44      get { return variableStore; }
45    }
46
47    [Storable]
48    private string code;
49    public string Code {
50      get { return code; }
51      set {
52        if (value == code) return;
53        code = value;
54        OnCodeChanged();
55      }
56    }
57
58    #endregion
59
60    [StorableConstructor]
61    private PythonScript(bool deserializing) : base(deserializing) { }
62    private PythonScript(PythonScript original, Cloner cloner)
63      : base(original, cloner) {
64      code = original.code;
65      variableStore = new VariableStore();
66    }
67    public PythonScript() {
68      name = ItemName;
69      description = ItemDescription;
70      code = CodeTemplate;
71      variableStore = new VariableStore();
72    }
73
74    public override IDeepCloneable Clone(Cloner cloner) {
75      return new PythonScript(this, cloner);
76    }
77
78    private Thread scriptThread;
79    public void Execute() {
80      scriptThread = new Thread(() => {
81        Exception ex = null;
82        try {
83          var pyEngine = IronPython.Hosting.Python.CreateEngine();
84          foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
85            pyEngine.Runtime.LoadAssembly(assembly);
86
87          using (var outputStream = new PyConsoleStream()) {
88            outputStream.TextAdded += OutputStreamOnStreamChanged;
89            pyEngine.Runtime.IO.SetOutput(outputStream, Encoding.UTF8);
90
91            var pyScope = pyEngine.CreateScope();
92            pyScope.SetVariable("vars", (dynamic)(new Variables(variableStore)));
93
94            OnScriptExecutionStarted();
95            pyEngine.CreateScriptSourceFromString(code).Compile().Execute(pyScope);
96            outputStream.Close();
97          }
98        } catch (ThreadAbortException) {
99          // the execution was cancelled by the user
100        } catch (TargetInvocationException e) {
101          ex = e.InnerException;
102        } catch (Exception e) {
103          ex = e;
104        } finally {
105          OnScriptExecutionFinished(ex);
106        }
107      });
108      scriptThread.Start();
109    }
110
111    private void OutputStreamOnStreamChanged(object sender, EventArgs<string> args) {
112      OnConsoleOutputChanged(args.Value);
113    }
114
115    public void Kill() {
116      if (scriptThread != null && scriptThread.IsAlive)
117        scriptThread.Abort();
118    }
119
120
121    public event EventHandler CodeChanged;
122    private void OnCodeChanged() {
123      var handler = CodeChanged;
124      if (handler != null) handler(this, EventArgs.Empty);
125    }
126
127    public event EventHandler ScriptExecutionStarted;
128    private void OnScriptExecutionStarted() {
129      var handler = ScriptExecutionStarted;
130      if (handler != null) handler(this, EventArgs.Empty);
131    }
132
133    public event EventHandler<EventArgs<Exception>> ScriptExecutionFinished;
134    private void OnScriptExecutionFinished(Exception e) {
135      var handler = ScriptExecutionFinished;
136      if (handler != null) handler(this, new EventArgs<Exception>(e));
137    }
138
139    public event EventHandler<EventArgs<string>> ConsoleOutputChanged;
140    private void OnConsoleOutputChanged(string args) {
141      var handler = ConsoleOutputChanged;
142      if (handler != null) handler(null, new EventArgs<string>(args));
143    }
144
145    class PyConsoleStream : Stream {
146      public override void Flush() { }
147
148      public override long Seek(long offset, SeekOrigin origin) {
149        throw new NotSupportedException();
150      }
151
152      public override void SetLength(long value) {
153        throw new NotSupportedException();
154      }
155
156      public override int Read(byte[] buffer, int offset, int count) {
157        throw new NotSupportedException();
158      }
159
160      public override void Write(byte[] buffer, int offset, int count) {
161        OnStreamChanged(Encoding.UTF8.GetString(buffer, offset, count));
162      }
163
164      public override bool CanRead {
165        get { return false; }
166      }
167
168      public override bool CanSeek {
169        get { return false; }
170      }
171
172      public override bool CanWrite {
173        get { return true; }
174      }
175
176      public override long Length {
177        get { return 0; }
178      }
179
180      public override long Position {
181        get { return 0; }
182        set { }
183      }
184
185      public event EventHandler<EventArgs<string>> TextAdded;
186      private void OnStreamChanged(string text) {
187        var handler = TextAdded;
188        if (handler != null) handler(this, new EventArgs<string>(text));
189      }
190    }
191  }
192}
Note: See TracBrowser for help on using the repository browser.