Wox/wox.core/plugin/host/host_python.go

105 lines
3.0 KiB
Go

package host
import (
"context"
"fmt"
"path"
"strings"
"wox/plugin"
"wox/util"
"github.com/Masterminds/semver/v3"
"github.com/mitchellh/go-homedir"
)
func init() {
host := &PythonHost{}
host.websocketHost = &WebsocketHost{
host: host,
requestMap: util.NewHashMap[string, chan JsonRpcResponse](),
}
plugin.AllHosts = append(plugin.AllHosts, host)
}
type PythonHost struct {
websocketHost *WebsocketHost
}
func (n *PythonHost) GetRuntime(ctx context.Context) plugin.Runtime {
return plugin.PLUGIN_RUNTIME_PYTHON
}
func (n *PythonHost) Start(ctx context.Context) error {
return n.websocketHost.StartHost(ctx, n.findPythonPath(ctx), path.Join(util.GetLocation().GetHostDirectory(), "python-host.pyz"), []string{"SHIV_ROOT=" + util.GetLocation().GetCacheDirectory()})
}
func (n *PythonHost) findPythonPath(ctx context.Context) string {
util.GetLogger().Debug(ctx, "start finding python path")
var possiblePythonPaths = []string{
"/opt/homebrew/bin/python3",
"/usr/local/bin/python3",
"/usr/bin/python3",
"/usr/local/python3",
}
pyenvPaths, _ := homedir.Expand("~/.pyenv/versions")
if util.IsDirExists(pyenvPaths) {
versions, _ := util.ListDir(pyenvPaths)
for _, v := range versions {
possiblePythonPaths = append(possiblePythonPaths, path.Join(pyenvPaths, v, "bin", "python3"))
}
}
foundVersion, _ := semver.NewVersion("v0.0.1")
foundPath := ""
for _, p := range possiblePythonPaths {
if util.IsFileExists(p) {
versionOriginal, versionErr := util.ShellRunOutput(p, "--version")
if versionErr != nil {
util.GetLogger().Error(ctx, fmt.Sprintf("failed to get python version: %s, path=%s", versionErr, p))
continue
}
// Python version output format is like "Python 3.9.0"
version := strings.TrimSpace(string(versionOriginal))
version = strings.TrimPrefix(version, "Python ")
version = "v" + version
installedVersion, err := semver.NewVersion(version)
if err != nil {
util.GetLogger().Error(ctx, fmt.Sprintf("failed to parse python version: %s, path=%s", err, p))
continue
}
util.GetLogger().Debug(ctx, fmt.Sprintf("found python path: %s, version: %s", p, installedVersion.String()))
if installedVersion.GreaterThan(foundVersion) {
foundPath = p
foundVersion = installedVersion
}
}
}
if foundPath != "" {
util.GetLogger().Info(ctx, fmt.Sprintf("finally use python path: %s, version: %s", foundPath, foundVersion.String()))
return foundPath
}
util.GetLogger().Info(ctx, "finally use default python3 from env path")
return "python3"
}
func (n *PythonHost) IsStarted(ctx context.Context) bool {
return n.websocketHost.IsHostStarted(ctx)
}
func (n *PythonHost) Stop(ctx context.Context) {
n.websocketHost.StopHost(ctx)
}
func (n *PythonHost) LoadPlugin(ctx context.Context, metadata plugin.Metadata, pluginDirectory string) (plugin.Plugin, error) {
return n.websocketHost.LoadPlugin(ctx, metadata, pluginDirectory)
}
func (n *PythonHost) UnloadPlugin(ctx context.Context, metadata plugin.Metadata) {
n.websocketHost.UnloadPlugin(ctx, metadata)
}