using System; using umbraco.IO; namespace umbraco.scripting { /// /// Something like a proxy to IronPython. Does some initial settings and calls. /// Maps IronPython's StandardOutput and StandardError to a simple string. /// public class python { protected internal static PythonEngine Engine; protected static System.IO.MemoryStream ms; protected static System.IO.StreamReader sr; protected internal static System.Collections.Hashtable scripts; static python() { Engine = new PythonEngine(); initEnv(); loadScripts(); ms = new System.IO.MemoryStream(); sr = new System.IO.StreamReader(ms); Engine.SetStandardOutput(ms); Engine.SetStandardError(ms); } /// /// To be able to import umbraco dll's we have to append the umbraco path to python. /// It should also be possible to import other python scripts from umbracos python folder. /// And finally to run run some custom init stuff the script site.py in umbraco's /// root folder will be executed. /// /// private static void initEnv() { // Add umbracos bin folder to python's path string path = IOHelper.MapPath(SystemDirectories.Bin); Engine.AddToPath(path); // Add umbracos python folder to python's path path = IOHelper.MapPath(SystemDirectories.Python); Engine.AddToPath(path); // execute the site.py to do all the initial stuff string initFile = IOHelper.MapPath(SystemDirectories.Root + "/site.py"); Engine.ExecuteFile(initFile); } /// /// /// /// private static void loadScripts() { scripts = new System.Collections.Hashtable(); string path = IOHelper.MapPath(SystemDirectories.Python); System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(path); foreach (System.IO.FileInfo f in dir.GetFiles("*.py")) { if (!f.Name.EndsWith("_temp.py")) { try { scripts[f.FullName] = Engine.CompileFile(f.FullName ); } catch { scripts[f.FullName] = Engine.Compile("print 'error in file " + f.Name + "'"); } } } } /// /// Executes a python command like in console /// /// command to execute /// returns standard out of executed command public static string execute(string expression) { if (!(expression == null)) { string ret; ms.SetLength(0); ms.Flush(); try { Engine.Execute(expression); ms.Position = 0; ret = sr.ReadToEnd(); } catch (Exception ex) { ret = ex.Message; } return ret; } else { return string.Empty; } } /// /// Executes a python script like in console /// /// absolute path to script /// returns standard out of executed script public static string executeFile(string file) { if (System.IO.File.Exists(file)) { string ret; ms.SetLength(0); ms.Flush(); scripts[file].GetType().InvokeMember("Execute", System.Reflection.BindingFlags.InvokeMethod, null, scripts[file], null); ms.Position = 0; ret = sr.ReadToEnd(); return ret; } else { return "The File " + file + " could not be found."; } } /// /// Compiles a python script and add it to umbraco's script collection. /// If compilation fails then an exception will be raised. /// /// absolute path to script /// public static void compileFile(string file) { loadScripts(); scripts[file] = Engine.CompileFile(file); } /// /// Compiles a python script. /// If compilation fails then an exception will be raised. /// /// absolute path to script /// public static void tryCompile(string file) { Engine.CompileFile(file); } } /// /// The Class PythonEngine is just a wrapper for the real class IronPython.Hosting.PythonEngine /// in IronPython. In this manner we does not need a hard reference to the IronPython assembly. /// I've implemented only the methods i need for my purpose. /// public class PythonEngine { protected object Engine; public PythonEngine() { string path = IOHelper.MapPath(SystemDirectories.Bin + "/IronPython.dll"); System.Reflection.Assembly asm = System.Reflection.Assembly.LoadFile(path); System.Type EngineType = asm.GetType("IronPython.Hosting.PythonEngine"); Engine = System.Activator.CreateInstance(EngineType); } public void AddToPath(string path) { Engine.GetType().InvokeMember("AddToPath", System.Reflection.BindingFlags.InvokeMethod, null, Engine, new object[] { path }); } public void SetStandardOutput(System.IO.Stream stream) { Engine.GetType().InvokeMember("SetStandardOutput", System.Reflection.BindingFlags.InvokeMethod, null, Engine, new object[] { stream }); } public void SetStandardError(System.IO.Stream stream) { Engine.GetType().InvokeMember("SetStandardError", System.Reflection.BindingFlags.InvokeMethod, null, Engine, new object[] { stream }); } public void ExecuteFile(string FileName) { Engine.GetType().InvokeMember("ExecuteFile", System.Reflection.BindingFlags.InvokeMethod, null, Engine, new object[] { FileName }); } public void Execute(string ScriptCode) { Engine.GetType().InvokeMember("Execute", System.Reflection.BindingFlags.InvokeMethod, null, Engine, new object[] { ScriptCode }); } public Object CompileFile(string FileName) { return Engine.GetType().InvokeMember("CompileFile", System.Reflection.BindingFlags.InvokeMethod, null, Engine, new object[] { FileName }); } public Object Compile(string Expression) { return Engine.GetType().InvokeMember("Compile", System.Reflection.BindingFlags.InvokeMethod, null, Engine, new object[] { Expression }); } public Object CreateModule(string Modulename, bool publish) { return Engine.GetType().InvokeMember("CreateModule", System.Reflection.BindingFlags.InvokeMethod, null, Engine, new object[] { Modulename, publish }); } public System.Collections.IDictionary Globals { set { Engine.GetType().InvokeMember("Globals", System.Reflection.BindingFlags.SetProperty, null, Engine, new object[] { value }); } get { return (System.Collections.IDictionary)Engine.GetType().InvokeMember("Globals", System.Reflection.BindingFlags.GetProperty, null, Engine, null); } } } }