Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Flow.Launcher.Core/Flow.Launcher.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Droplex" Version="1.2.0" />
<PackageReference Include="Droplex" Version="1.3.1" />
<PackageReference Include="FSharp.Core" Version="4.7.1" />
<PackageReference Include="squirrel.windows" Version="1.5.2" />
</ItemGroup>
Expand Down
154 changes: 51 additions & 103 deletions Flow.Launcher.Core/Plugin/PluginsLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ namespace Flow.Launcher.Core.Plugin
{
public static class PluginsLoader
{
public const string PATH = "PATH";
public const string Python = "python";
public const string PythonExecutable = "pythonw.exe";

public static List<PluginPair> Plugins(List<PluginMetadata> metadatas, PluginsSettings settings)
Expand Down Expand Up @@ -117,119 +115,65 @@ public static IEnumerable<PluginPair> PythonPlugins(List<PluginMetadata> source,
if (!source.Any(o => o.Language.ToUpper() == AllowedLanguage.Python))
return new List<PluginPair>();

// Try setting Constant.PythonPath first, either from
// PATH or from the given pythonDirectory
if (string.IsNullOrEmpty(settings.PythonDirectory))
if (!string.IsNullOrEmpty(settings.PythonDirectory) && FilesFolders.LocationExists(settings.PythonDirectory))
return SetPythonPathForPluginPairs(source, Path.Combine(settings.PythonDirectory, PythonExecutable));

var pythonPath = string.Empty;

if (MessageBox.Show("Flow detected you have installed Python plugins, " +
"would you like to install Python to run them? " +
Environment.NewLine + Environment.NewLine +
"Click no if it's already installed, " +
"and you will be prompted to select the folder that contains the Python executable",
string.Empty, MessageBoxButtons.YesNo) == DialogResult.No
&& string.IsNullOrEmpty(settings.PythonDirectory))
{
var whereProcess = Process.Start(new ProcessStartInfo
var dlg = new FolderBrowserDialog
{
FileName = "where.exe",
Arguments = "pythonw",
RedirectStandardOutput = true,
CreateNoWindow = true,
UseShellExecute = false
});

var pythonPath = whereProcess?.StandardOutput.ReadToEnd().Trim();

if (!string.IsNullOrEmpty(pythonPath))
{
pythonPath = FilesFolders.GetPreviousExistingDirectory(FilesFolders.LocationExists, pythonPath);
}

if (string.IsNullOrEmpty(pythonPath))
{
var paths = Environment.GetEnvironmentVariable(PATH);

pythonPath = paths?
.Split(';')
.FirstOrDefault(p => p.ToLower().Contains(Python));
}
SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)
};

if (!string.IsNullOrEmpty(pythonPath))
{
Constant.PythonPath = Path.Combine(pythonPath, PythonExecutable);
settings.PythonDirectory =
FilesFolders.GetPreviousExistingDirectory(FilesFolders.LocationExists, Constant.PythonPath);
}
else
var result = dlg.ShowDialog();
if (result == DialogResult.OK)
{
Log.Error("PluginsLoader",
"Failed to set Python path despite the environment variable PATH is found",
"PythonPlugins");
string pythonDirectory = dlg.SelectedPath;
if (!string.IsNullOrEmpty(pythonDirectory))
{
pythonPath = Path.Combine(pythonDirectory, PythonExecutable);
if (File.Exists(pythonPath))
{
settings.PythonDirectory = pythonDirectory;
Constant.PythonPath = pythonPath;
}
else
{
MessageBox.Show("Can't find python in given directory");
}
}
}
}
else
{
var path = Path.Combine(settings.PythonDirectory, PythonExecutable);
if (File.Exists(path))
{
Constant.PythonPath = path;
}
else
{
Log.Error("PluginsLoader", $"Tried to automatically set from Settings.PythonDirectory " +
$"but can't find python executable in {path}", "PythonPlugins");
}
}
var installedPythonDirectory = Path.Combine(DataLocation.DataDirectory(), "Python Embeddable");

if (string.IsNullOrEmpty(settings.PythonDirectory))
{
if (MessageBox.Show("Flow detected you have installed Python plugins, " +
"would you like to install Python to run them? " +
Environment.NewLine + Environment.NewLine +
"Click no if it's already installed, " +
"and you will be prompted to select the folder that contains the Python executable",
string.Empty, MessageBoxButtons.YesNo) == DialogResult.No
&& string.IsNullOrEmpty(settings.PythonDirectory))
{
var dlg = new FolderBrowserDialog
{
SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)
};
// Python 3.8.9 is used for Windows 7 compatibility
DroplexPackage.Drop(App.python_3_8_9_embeddable, installedPythonDirectory).Wait();

var result = dlg.ShowDialog();
if (result == DialogResult.OK)
{
string pythonDirectory = dlg.SelectedPath;
if (!string.IsNullOrEmpty(pythonDirectory))
{
var pythonPath = Path.Combine(pythonDirectory, PythonExecutable);
if (File.Exists(pythonPath))
{
settings.PythonDirectory = pythonDirectory;
Constant.PythonPath = pythonPath;
}
else
{
MessageBox.Show("Can't find python in given directory");
}
}
}
pythonPath = Path.Combine(installedPythonDirectory, PythonExecutable);
if (FilesFolders.FileExists(pythonPath))
{
settings.PythonDirectory = installedPythonDirectory;
Constant.PythonPath = pythonPath;
}
else
{
DroplexPackage.Drop(App.python3_9_1).Wait();

var installedPythonDirectory =
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
@"Programs\Python\Python39");
var pythonPath = Path.Combine(installedPythonDirectory, PythonExecutable);
if (FilesFolders.FileExists(pythonPath))
{
settings.PythonDirectory = installedPythonDirectory;
Constant.PythonPath = pythonPath;
}
else
{
Log.Error("PluginsLoader",
$"Failed to set Python path after Droplex install, {pythonPath} does not exist",
"PythonPlugins");
}
Log.Error("PluginsLoader",
$"Failed to set Python path after Droplex install, {pythonPath} does not exist",
"PythonPlugins");
}
}

if (string.IsNullOrEmpty(settings.PythonDirectory))
if (string.IsNullOrEmpty(settings.PythonDirectory) || string.IsNullOrEmpty(pythonPath))
{
MessageBox.Show(
"Unable to set Python executable path, please try from Flow's settings (scroll down to the bottom).");
Expand All @@ -240,16 +184,20 @@ public static IEnumerable<PluginPair> PythonPlugins(List<PluginMetadata> source,
return new List<PluginPair>();
}

return source
return SetPythonPathForPluginPairs(source, pythonPath);
}

private static IEnumerable<PluginPair> SetPythonPathForPluginPairs(List<PluginMetadata> source, string pythonPath)
=> source
.Where(o => o.Language.ToUpper() == AllowedLanguage.Python)
.Select(metadata => new PluginPair
{
Plugin = new PythonPlugin(Constant.PythonPath), Metadata = metadata
Plugin = new PythonPlugin(pythonPath),
Metadata = metadata
})
.ToList();
}

public static IEnumerable<PluginPair> ExecutablePlugins(IEnumerable<PluginMetadata> source)
public static IEnumerable<PluginPair> ExecutablePlugins(IEnumerable<PluginMetadata> source)
{
return source
.Where(o => o.Language.ToUpper() == AllowedLanguage.Executable)
Expand Down