oh-my-posh/src/segments/python.go

143 lines
3.8 KiB
Go
Raw Normal View History

2022-01-26 06:54:36 -08:00
package segments
import (
"oh-my-posh/environment"
"oh-my-posh/properties"
"path/filepath"
"strings"
)
2022-01-26 05:10:18 -08:00
type Python struct {
2021-12-03 11:19:57 -08:00
language
Venv string
}
const (
2021-12-04 02:56:55 -08:00
// FetchVirtualEnv fetches the virtual env
FetchVirtualEnv properties.Property = "fetch_virtual_env"
UsePythonVersionFile properties.Property = "use_python_version_file"
)
func (p *Python) Template() string {
2022-02-01 05:07:58 -08:00
return " {{ if .Error }}{{ .Error }}{{ else }}{{ if .Venv }}{{ .Venv }} {{ end }}{{ .Full }}{{ end }} "
}
func (p *Python) Init(props properties.Properties, env environment.Environment) {
2021-12-03 11:19:57 -08:00
p.language = language{
2021-02-03 10:11:32 -08:00
env: env,
props: props,
extensions: []string{"*.py", "*.ipynb", "pyproject.toml", "venv.bak", "venv", ".venv"},
loadContext: p.loadContext,
inContext: p.inContext,
commands: []*cmd{
{
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]+))))`,
},
},
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),
homeEnabled: props.GetBool(HomeEnabled, true),
2020-11-14 11:04:04 -08:00
}
}
func (p *Python) Enabled() bool {
return p.language.Enabled()
}
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) {
return
}
venvVars := []string{
"VIRTUAL_ENV",
"CONDA_ENV_PATH",
"CONDA_DEFAULT_ENV",
}
var venv string
for _, venvVar := range venvVars {
venv = p.language.env.Getenv(venvVar)
name := environment.Base(p.language.env, venv)
if p.canUseVenvName(name) {
p.Venv = name
break
}
}
}
2022-01-26 05:10:18 -08:00
func (p *Python) inContext() bool {
return p.Venv != ""
}
2022-01-26 05:10:18 -08:00
func (p *Python) canUseVenvName(name string) bool {
if name == "" || name == "." {
return false
}
if p.language.props.GetBool(properties.DisplayDefault, true) {
return true
}
invalidNames := [2]string{"system", "base"}
for _, a := range invalidNames {
if a == name {
return false
}
}
return true
}
func (p *Python) pyenvVersion() (string, error) {
// 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")
if path == "" {
path = p.env.CommandPath("python3")
}
if path == "" {
return "", nil
}
// TODO: pyenv-win has this at $PYENV_ROOT/pyenv-win/shims
if path != filepath.Join(p.env.Getenv("PYENV_ROOT"), "shims", "python") {
return "", nil
}
// pyenv version-name will return current version or virtualenv
cmdOutput, err := p.env.RunCommand("pyenv", "version-name")
if err != nil {
// TODO: Improve reporting
return "", nil
}
versionString := strings.Split(cmdOutput, ":")[0]
if versionString == "" {
return "", nil
}
// $PYENV_ROOT/versions + versionString (symlinks resolved) == $PYENV_ROOT/versions/(version)[/envs/(virtualenv)]
realPath, err := p.env.ResolveSymlink(filepath.Join(p.env.Getenv("PYENV_ROOT"), "versions", versionString))
if err != nil {
return "", nil
}
// ../versions/(version)[/envs/(virtualenv)]
shortPath, err := filepath.Rel(filepath.Join(p.env.Getenv("PYENV_ROOT"), "versions"), realPath)
if err != nil {
return "", nil
}
// Unset whatever loadContext thinks Venv should be
p.Venv = ""
parts := strings.Split(shortPath, string(filepath.Separator))
if len(parts) > 2 && p.canUseVenvName(parts[2]) {
p.Venv = parts[2]
}
return parts[0], nil
}