public static bool RunPyString(Dictionary <string, object> args) { try { PythonHelper.RunCode(args["script"].ToString()); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } return(true); }
public static bool RunPyFile(Dictionary <string, object> args) { try { PythonHelper.RunCode(Objects.ShiftFS.Utils.ReadAllText(args["script"].ToString())); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } return(true); }
/// <summary> /// Finds Python mods and adds them to ReflectMan's Types list. /// </summary> public static void Scan() { if (scanned) { throw new Exception("PythonAPI.Scan() called multiple times"); } scopes = new Dictionary <string, ScriptScope>(); var resman = new System.Resources.ResourceManager("ShiftOS.Engine.Properties.Resources", typeof(Properties.Resources).Assembly); var provider = new CSharpCodeProvider(); var refs = AppDomain.CurrentDomain.GetAssemblies().Select(f => f.Location).Concat(new string[] { "Microsoft.CSharp.dll" }).ToArray(); var types = new List <Type>(); var sha = new SHA512Managed(); var oldcache = new Dictionary <string, AsmCacheEntry>(); var newcache = new Dictionary <string, AsmCacheEntry>(); if (File.Exists("pyasmcache.dat")) { using (var stream = File.OpenRead("pyasmcache.dat")) try { oldcache = AsmCache.Load(stream); } catch (Exception ex) { #if DEBUG Console.WriteLine("[dev] Failed to read the assembly cache."); Console.WriteLine(ex.ToString()); #endif } } foreach (var fname in Directory.GetFiles(Environment.CurrentDirectory, "*.py").Select(Path.GetFileName)) { byte[] checksum; using (FileStream stream = File.OpenRead(fname)) checksum = sha.ComputeHash(stream); var script = File.ReadAllText(fname); try { scopes[fname] = PythonHelper.RunCode(script); } catch (Exception ex) { Console.WriteLine("[dev] Failed to execute Python script " + fname); Console.WriteLine(ex.ToString()); continue; } if (oldcache.ContainsKey(fname)) { var oldentry = oldcache[fname]; if (checksum.SequenceEqual(oldentry.checksum)) { try { foreach (var asm in oldentry.asms) { types.AddRange(Assembly.Load(asm).GetTypes()); } newcache.Add(fname, oldentry); continue; } catch (Exception ex) { #if DEBUG Console.WriteLine("[dev] Failed to load cached assembly for " + fname); Console.WriteLine(ex.ToString()); #endif } } } var scriptlines = script.Replace("\r\n", "\n").Replace("\r", "\n").Split('\n'); // line-ending independent... int pos = 0; var entry = new AsmCacheEntry(); entry.checksum = checksum; var parameters = new CompilerParameters(); parameters.ReferencedAssemblies.AddRange(refs); parameters.GenerateInMemory = false; // We need to keep the temporary file around long enough to copy it to the cache. parameters.GenerateExecutable = false; try { while (pos < scriptlines.Length) { while (!scriptlines[pos].StartsWith("#ShiftOS")) { pos++; } var templatename = scriptlines[pos].Split(':')[1]; pos++; string decorators = ""; while (scriptlines[pos].StartsWith("#")) { decorators += scriptlines[pos].Substring(1) + Environment.NewLine; // remove # and add to string pos++; } if (!scriptlines[pos].StartsWith("class ")) { throw new Exception("ShiftOS decorators without matching global class"); } var classname = scriptlines[pos].Split(' ')[1]; if (classname.Contains("(")) // derived class { classname = classname.Split('(')[0]; } else { classname = classname.Remove(classname.Length - 1); // remove : } var code = String.Format(resman.GetString(templatename), decorators, classname, fname.Replace("\\", "\\\\")); // generate the C# wrapper class from template #if DEBUG Console.WriteLine(code); #endif var results = provider.CompileAssemblyFromSource(parameters, code); if (results.Errors.HasErrors) { string except = "The wrapper class failed to compile."; foreach (CompilerError error in results.Errors) { except += Environment.NewLine + error.ErrorText; } throw new Exception(except); } types.AddRange(results.CompiledAssembly.GetTypes()); // We did it! entry.asms.Add(File.ReadAllBytes(results.PathToAssembly)); pos++; // keep scanning the file for more classes } } catch (Exception ex) // Skip any file that has issues { #if DEBUG Console.WriteLine("[dev] Exception in the Python API: file " + fname + ", line " + pos.ToString() + "."); Console.WriteLine(ex.ToString()); #endif } newcache.Add(fname, entry); } #if DEBUG Console.WriteLine("[dev] " + types.Count.ToString() + " Python mods loaded successfully."); #endif if (types.Count > 0) { ReflectMan.AddTypes(types.ToArray()); using (var stream = File.OpenWrite("pyasmcache.dat")) AsmCache.Save(stream, newcache); } scanned = true; }