2022-01-26 06:54:36 -08:00
|
|
|
package segments
|
2020-10-02 02:55:27 -07:00
|
|
|
|
2022-01-26 04:53:35 -08:00
|
|
|
import (
|
2022-10-04 23:10:30 -07:00
|
|
|
"errors"
|
2022-07-25 22:28:54 -07:00
|
|
|
"fmt"
|
2022-04-19 20:51:00 -07:00
|
|
|
"path/filepath"
|
2022-04-06 14:33:56 -07:00
|
|
|
"strings"
|
2022-12-28 08:30:48 -08:00
|
|
|
|
|
|
|
"github.com/jandedobbeleer/oh-my-posh/platform"
|
|
|
|
"github.com/jandedobbeleer/oh-my-posh/properties"
|
2022-01-26 04:53:35 -08:00
|
|
|
)
|
2022-01-26 01:23:18 -08:00
|
|
|
|
2022-01-26 05:10:18 -08:00
|
|
|
type Python struct {
|
2021-12-03 11:19:57 -08:00
|
|
|
language
|
2021-12-04 01:26:30 -08:00
|
|
|
|
|
|
|
Venv string
|
2020-10-02 02:55:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
2021-12-04 02:56:55 -08:00
|
|
|
// FetchVirtualEnv fetches the virtual env
|
2022-04-06 14:33:56 -07:00
|
|
|
FetchVirtualEnv properties.Property = "fetch_virtual_env"
|
|
|
|
UsePythonVersionFile properties.Property = "use_python_version_file"
|
2020-10-02 02:55:27 -07:00
|
|
|
)
|
|
|
|
|
2022-01-26 05:26:56 -08:00
|
|
|
func (p *Python) Template() string {
|
2022-02-01 05:07:58 -08:00
|
|
|
return " {{ if .Error }}{{ .Error }}{{ else }}{{ if .Venv }}{{ .Venv }} {{ end }}{{ .Full }}{{ end }} "
|
2020-10-02 02:55:27 -07:00
|
|
|
}
|
|
|
|
|
2022-11-09 11:27:54 -08:00
|
|
|
func (p *Python) Init(props properties.Properties, env platform.Environment) {
|
2021-12-03 11:19:57 -08:00
|
|
|
p.language = language{
|
2021-02-03 10:11:32 -08:00
|
|
|
env: env,
|
|
|
|
props: props,
|
2022-04-23 00:46:57 -07:00
|
|
|
extensions: []string{"*.py", "*.ipynb", "pyproject.toml", "venv.bak"},
|
|
|
|
folders: []string{".venv", "venv", "virtualenv", "env", "venv-win", "pyenv-win"},
|
2021-02-03 10:11:32 -08:00
|
|
|
loadContext: p.loadContext,
|
|
|
|
inContext: p.inContext,
|
|
|
|
commands: []*cmd{
|
2022-04-19 20:51:00 -07:00
|
|
|
{
|
|
|
|
getVersion: p.pyenvVersion,
|
|
|
|
regex: `(?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+).(?P<patch>[0-9]+)))`,
|
|
|
|
},
|
2021-02-03 10:11:32 -08:00
|
|
|
{
|
|
|
|
executable: "python",
|
|
|
|
args: []string{"--version"},
|
|
|
|
regex: `(?:Python (?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+).(?P<patch>[0-9]+))))`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
executable: "python3",
|
|
|
|
args: []string{"--version"},
|
|
|
|
regex: `(?:Python (?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+).(?P<patch>[0-9]+))))`,
|
|
|
|
},
|
2021-01-10 03:14:43 -08:00
|
|
|
},
|
2022-03-23 01:14:21 -07:00
|
|
|
versionURLTemplate: "https://docs.python.org/release/{{ .Major }}.{{ .Minor }}.{{ .Patch }}/whatsnew/changelog.html#python-{{ .Major }}-{{ .Minor }}-{{ .Patch }}",
|
2022-01-26 04:09:21 -08:00
|
|
|
displayMode: props.GetString(DisplayMode, DisplayModeEnvironment),
|
2020-11-14 11:04:04 -08:00
|
|
|
}
|
2020-10-02 02:55:27 -07:00
|
|
|
}
|
|
|
|
|
2022-01-26 05:26:56 -08:00
|
|
|
func (p *Python) Enabled() bool {
|
|
|
|
return p.language.Enabled()
|
2021-01-12 11:38:13 -08:00
|
|
|
}
|
|
|
|
|
2022-01-26 05:10:18 -08:00
|
|
|
func (p *Python) loadContext() {
|
2022-01-26 04:09:21 -08:00
|
|
|
if !p.language.props.GetBool(FetchVirtualEnv, true) {
|
2021-04-17 04:47:28 -07:00
|
|
|
return
|
|
|
|
}
|
2020-10-02 02:55:27 -07:00
|
|
|
venvVars := []string{
|
|
|
|
"VIRTUAL_ENV",
|
|
|
|
"CONDA_ENV_PATH",
|
2021-01-20 04:09:13 -08:00
|
|
|
"CONDA_DEFAULT_ENV",
|
2020-10-02 02:55:27 -07:00
|
|
|
}
|
|
|
|
var venv string
|
|
|
|
for _, venvVar := range venvVars {
|
2022-01-23 12:37:51 -08:00
|
|
|
venv = p.language.env.Getenv(venvVar)
|
2022-10-04 23:03:43 -07:00
|
|
|
if len(venv) == 0 {
|
|
|
|
continue
|
|
|
|
}
|
2022-11-09 11:27:54 -08:00
|
|
|
name := platform.Base(p.language.env, venv)
|
2021-01-20 04:09:13 -08:00
|
|
|
if p.canUseVenvName(name) {
|
2021-12-04 01:26:30 -08:00
|
|
|
p.Venv = name
|
2020-10-02 02:55:27 -07:00
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2021-01-12 11:38:13 -08:00
|
|
|
}
|
|
|
|
|
2022-01-26 05:10:18 -08:00
|
|
|
func (p *Python) inContext() bool {
|
2021-12-04 01:26:30 -08:00
|
|
|
return p.Venv != ""
|
2020-10-02 02:55:27 -07:00
|
|
|
}
|
2021-01-20 04:09:13 -08:00
|
|
|
|
2022-01-26 05:10:18 -08:00
|
|
|
func (p *Python) canUseVenvName(name string) bool {
|
2022-01-26 04:53:35 -08:00
|
|
|
if p.language.props.GetBool(properties.DisplayDefault, true) {
|
2021-01-20 04:09:13 -08:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
invalidNames := [2]string{"system", "base"}
|
|
|
|
for _, a := range invalidNames {
|
|
|
|
if a == name {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
2022-04-19 20:51:00 -07:00
|
|
|
|
2022-10-04 23:10:30 -07:00
|
|
|
func (p *Python) pyenvVersion() (string, error) {
|
2022-04-19 20:51:00 -07:00
|
|
|
// Use `pyenv root` instead of $PYENV_ROOT?
|
|
|
|
// Is our Python executable at $PYENV_ROOT/bin/python ?
|
|
|
|
// Should p.env expose command paths?
|
|
|
|
path := p.env.CommandPath("python")
|
2022-07-25 22:28:54 -07:00
|
|
|
if len(path) == 0 {
|
2022-04-19 20:51:00 -07:00
|
|
|
path = p.env.CommandPath("python3")
|
|
|
|
}
|
2022-07-25 22:28:54 -07:00
|
|
|
if len(path) == 0 {
|
2022-10-04 23:10:30 -07:00
|
|
|
return "", errors.New("no python executable found")
|
2022-04-19 20:51:00 -07:00
|
|
|
}
|
2022-07-25 22:28:54 -07:00
|
|
|
pyEnvRoot := p.env.Getenv("PYENV_ROOT")
|
2022-04-19 20:51:00 -07:00
|
|
|
// TODO: pyenv-win has this at $PYENV_ROOT/pyenv-win/shims
|
2022-07-25 22:28:54 -07:00
|
|
|
if path != filepath.Join(pyEnvRoot, "shims", "python") {
|
2022-10-04 23:10:30 -07:00
|
|
|
return "", fmt.Errorf("executable at %s is not a pyenv shim", path)
|
2022-04-19 20:51:00 -07:00
|
|
|
}
|
|
|
|
// pyenv version-name will return current version or virtualenv
|
|
|
|
cmdOutput, err := p.env.RunCommand("pyenv", "version-name")
|
|
|
|
if err != nil {
|
2022-10-04 23:10:30 -07:00
|
|
|
return "", err
|
2022-04-19 20:51:00 -07:00
|
|
|
}
|
|
|
|
versionString := strings.Split(cmdOutput, ":")[0]
|
2022-07-25 22:28:54 -07:00
|
|
|
if len(versionString) == 0 {
|
2022-10-04 23:10:30 -07:00
|
|
|
return "", errors.New("no pyenv version-name found")
|
2022-04-19 20:51:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// $PYENV_ROOT/versions + versionString (symlinks resolved) == $PYENV_ROOT/versions/(version)[/envs/(virtualenv)]
|
2022-07-25 22:28:54 -07:00
|
|
|
realPath, err := p.env.ResolveSymlink(filepath.Join(pyEnvRoot, "versions", versionString))
|
2022-04-19 20:51:00 -07:00
|
|
|
if err != nil {
|
2022-10-04 23:10:30 -07:00
|
|
|
return "", err
|
2022-04-19 20:51:00 -07:00
|
|
|
}
|
|
|
|
// ../versions/(version)[/envs/(virtualenv)]
|
2022-07-25 22:28:54 -07:00
|
|
|
shortPath, err := filepath.Rel(filepath.Join(pyEnvRoot, "versions"), realPath)
|
2022-04-19 20:51:00 -07:00
|
|
|
if err != nil {
|
2022-10-04 23:10:30 -07:00
|
|
|
return "", err
|
2022-04-19 20:51:00 -07:00
|
|
|
}
|
2022-07-27 22:48:52 -07:00
|
|
|
// override virtualenv if pyenv set one
|
2022-04-19 20:51:00 -07:00
|
|
|
parts := strings.Split(shortPath, string(filepath.Separator))
|
|
|
|
if len(parts) > 2 && p.canUseVenvName(parts[2]) {
|
|
|
|
p.Venv = parts[2]
|
|
|
|
}
|
2022-10-04 23:10:30 -07:00
|
|
|
return parts[0], nil
|
2022-04-19 20:51:00 -07:00
|
|
|
}
|