|
| 1 | + |
| 2 | +using System; |
| 3 | +using System.IO; |
| 4 | +using System.Threading.Tasks; |
| 5 | +using System.Linq; |
| 6 | +using System.IO.Compression; |
| 7 | +using System.Diagnostics; |
| 8 | +using System.Collections.Generic; |
| 9 | +using System.Runtime.InteropServices; |
| 10 | + |
| 11 | + |
| 12 | +namespace PythonShell { |
| 13 | + public class PythonShellConfig { |
| 14 | + public String DefaultPythonPath { get; set; } = "python3"; |
| 15 | + public String DefaultPythonVersion { get; set; } = "3.9.13"; |
| 16 | + // public String? DefaultWorkingDirectory { get; set; } = null; |
| 17 | + // public String? PythonRequireFile { get; set; } = null; |
| 18 | + // public String[]? PythonRequires { get; set; } = null; |
| 19 | + |
| 20 | + // internal String? AppDir { get; set; } = null; |
| 21 | + // internal String TempDir { |
| 22 | + // get => Path.Join(AppDir, "temp"); |
| 23 | + // } |
| 24 | + // internal String InstanceDir { |
| 25 | + // get => Path.Join(AppDir, "instances"); |
| 26 | + // } |
| 27 | + // internal String? DefaultPythonEnvPath { get; set; } = null; |
| 28 | + |
| 29 | + public PythonShellConfig() { |
| 30 | + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { |
| 31 | + if (this.DefaultPythonPath == "python" || this.DefaultPythonPath == "python2" || this.DefaultPythonPath == "python3") { |
| 32 | + this.DefaultPythonPath = $"/usr/bin/{this.DefaultPythonPath}"; |
| 33 | + } |
| 34 | + else if (!File.Exists(this.DefaultPythonPath)) { |
| 35 | + this.DefaultPythonPath = "/usr/bin/python3"; |
| 36 | + } |
| 37 | + } |
| 38 | + |
| 39 | + // if (this.DefaultWorkingDirectory != null) { |
| 40 | + // this.DefaultWorkingDirectory = Path.GetFullPath(this.DefaultWorkingDirectory); |
| 41 | + // } |
| 42 | + } |
| 43 | + } |
| 44 | + |
| 45 | + public class PythonShell { |
| 46 | + public PythonShell(PythonShellConfig shellConfig) {} |
| 47 | + |
| 48 | + public void Clear() { |
| 49 | + Shell.ShellManager.Clear(); |
| 50 | + foreach (var path in Directory.GetDirectories(Config.TempDir)) { |
| 51 | + Directory.Delete(path, true); |
| 52 | + } |
| 53 | + foreach (var path in Directory.GetFiles(Config.TempDir)) { |
| 54 | + File.Delete(path); |
| 55 | + } |
| 56 | + } |
| 57 | + |
| 58 | + public async Task Initialize() { |
| 59 | + Console.WriteLine("Initializing shell..."); |
| 60 | + Config.DefaultPythonVersion = Config.CheckPythonVersion(Config.DefaultPythonVersion); |
| 61 | + |
| 62 | + if (!Directory.Exists(Config.AppDir)) Directory.CreateDirectory(Config.AppDir); |
| 63 | + if (!Directory.Exists(Config.InstanceDir)) Directory.CreateDirectory(Config.InstanceDir); |
| 64 | + if (!Directory.Exists(Config.TempDir)) Directory.CreateDirectory(Config.TempDir); |
| 65 | + |
| 66 | + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { |
| 67 | + Console.WriteLine("Check default python binary files..."); |
| 68 | + String pythonDir = Path.Join(Config.AppDir, "python"); |
| 69 | + if (!Directory.Exists(pythonDir)) { |
| 70 | + String pythonZipFile = Path.Join(Config.TempDir, "python.zip"); |
| 71 | + await Util.DownloadFile($"https://www.python.org/ftp/python/{Config.DefaultPythonVersion}/python-{Config.DefaultPythonVersion}-embed-{Config.PythonRuntimeBit}.zip", pythonZipFile, "binary"); |
| 72 | + ZipFile.ExtractToDirectory(pythonZipFile, pythonDir); |
| 73 | + File.Delete(pythonZipFile); |
| 74 | + |
| 75 | + var pthFile = Path.Join(pythonDir, $"python{Config.DefaultPythonVersion.Replace($".{Config.DefaultPythonVersion.Split(".").Last()}", "").Replace(".", "")}._pth"); |
| 76 | + File.WriteAllText( |
| 77 | + pthFile, |
| 78 | + File.ReadAllText(pthFile).Replace("#import site", "import site") |
| 79 | + ); |
| 80 | + } |
| 81 | + Console.WriteLine("Python check finished."); |
| 82 | + |
| 83 | + Config.DefaultPythonPath = Path.Join(pythonDir, "python.exe"); |
| 84 | + } |
| 85 | + |
| 86 | + if (File.Exists(Config.DefaultPythonPath)) { |
| 87 | + Console.WriteLine("Default settings for virtualenv..."); |
| 88 | + var p = Util.RunSettingCmd(Config.DefaultPythonPath, new String[] { "-m", "pip", "install", "pip", "--upgrade" }); |
| 89 | + if (p.ExitCode != 0) { |
| 90 | + String pipInstallFile = Path.Join(Config.TempDir, "get-pip.py"); |
| 91 | + await Util.DownloadFile("https://bootstrap.pypa.io/pip/get-pip.py", pipInstallFile, "text"); |
| 92 | + Util.RunSettingCmd(Config.DefaultPythonPath, new String[] { pipInstallFile }); |
| 93 | + File.Delete(pipInstallFile); |
| 94 | + } |
| 95 | + |
| 96 | + Util.RunSettingCmd(Config.DefaultPythonPath, new String[] { "-m", "pip", "install", "virtualenv", "--upgrade" }); |
| 97 | + Console.WriteLine("Virtualenv settings finished."); |
| 98 | + } |
| 99 | + |
| 100 | + String defaultEnvdir = Path.Join(Config.InstanceDir, "default"); |
| 101 | + if (!Directory.Exists(defaultEnvdir)) { |
| 102 | + Console.WriteLine("Creating default env..."); |
| 103 | + Shell.ShellManager.CreateInstance("default"); |
| 104 | + Console.WriteLine("Default env created."); |
| 105 | + } |
| 106 | + |
| 107 | + Console.WriteLine("Shell initialized."); |
| 108 | + } |
| 109 | + |
| 110 | + public async Task RunFile(String pythonFile, Shell.ShellInstance? instance = null, String? workingDirectory = null, Listener.ShellListener? listener = null, Boolean echo = true) { |
| 111 | + instance = instance ?? Shell.ShellManager.GetInstance("default"); |
| 112 | + await instance.RunFile(pythonFile, workingDirectory, listener, echo); |
| 113 | + } |
| 114 | + |
| 115 | + public async Task RunString(String pythonCode, Shell.ShellInstance? instance = null, String? workingDirectory = null, Listener.ShellListener? listener = null, Boolean echo = true) { |
| 116 | + instance = instance ?? Shell.ShellManager.GetInstance("default"); |
| 117 | + await instance.RunString(pythonCode, workingDirectory, listener, echo); |
| 118 | + } |
| 119 | + } |
| 120 | +} |
0 commit comments