diff --git a/docs/docs/segment-python.md b/docs/docs/segment-python.md index 1693fb8b..6cdfdc62 100644 --- a/docs/docs/segment-python.md +++ b/docs/docs/segment-python.md @@ -26,6 +26,7 @@ Supports conda, virtualenv and pyenv. - home_enabled: `boolean` - display the segment in the HOME folder or not - defaults to `false` - fetch_virtual_env: `boolean` - fetch the name of the virtualenv or not - defaults to `true` +- use_python_version_file: `boolean` - Use pyenv `.python-version` files to determine virtual env - defaults to `false` - display_default: `boolean` - show the name of the virtualenv when it's default (`system`, `base`) or not - defaults to `true` - fetch_version: `boolean` - fetch the python version - defaults to `true` diff --git a/src/segments/python.go b/src/segments/python.go index 96f8a67c..4fc6ea6e 100644 --- a/src/segments/python.go +++ b/src/segments/python.go @@ -3,6 +3,8 @@ package segments import ( "oh-my-posh/environment" "oh-my-posh/properties" + "oh-my-posh/regex" + "strings" ) type Python struct { @@ -13,7 +15,8 @@ type Python struct { const ( // FetchVirtualEnv fetches the virtual env - FetchVirtualEnv properties.Property = "fetch_virtual_env" + FetchVirtualEnv properties.Property = "fetch_virtual_env" + UsePythonVersionFile properties.Property = "use_python_version_file" ) func (p *Python) Template() string { @@ -68,6 +71,15 @@ func (p *Python) loadContext() { break } } + if !p.language.props.GetBool(UsePythonVersionFile, false) { + return + } + if f, err := p.language.env.HasParentFilePath(".python-version"); err == nil { + contents := strings.Split(p.language.env.FileContent(f.Path), "\n") + if contents[0] != "" && regex.MatchString("[0-9]+.[0-9]+.[0-9]", contents[0]) == false && p.canUseVenvName(contents[0]) { + p.Venv = contents[0] + } + } } func (p *Python) inContext() bool { diff --git a/src/segments/python_test.go b/src/segments/python_test.go index 4dd2a16b..62066c5f 100644 --- a/src/segments/python_test.go +++ b/src/segments/python_test.go @@ -1,6 +1,7 @@ package segments import ( + "errors" "oh-my-posh/environment" "oh-my-posh/mock" "oh-my-posh/properties" @@ -17,6 +18,7 @@ func TestPythonTemplate(t *testing.T) { Template string VirtualEnvName string FetchVersion bool + PyenvLocal string }{ {Case: "No virtual env present", FetchVersion: true, Expected: "3.8.4", Template: "{{ if .Venv }}{{ .Venv }} {{ end }}{{ .Full }}"}, {Case: "Virtual env present", FetchVersion: true, Expected: "VENV 3.8.4", VirtualEnvName: "VENV", Template: "{{ if .Venv }}{{ .Venv }} {{ end }}{{ .Full }}"}, @@ -41,6 +43,20 @@ func TestPythonTemplate(t *testing.T) { VirtualEnvName: "billy", Template: "{{ if ne .Venv \"default\" }}{{ .Venv }} {{ end }}{{ .Major }}.{{ .Minor }}", }, + { + Case: "Pyenv show env", + FetchVersion: true, + Expected: "VENV 3.8", + PyenvLocal: "VENV\n", + Template: "{{ if ne .Venv \"default\" }}{{ .Venv }} {{ end }}{{ .Major }}.{{ .Minor }}", + }, + { + Case: "Pyenv skip version", + FetchVersion: true, + Expected: "3.8", + PyenvLocal: "3.8.7\n", + Template: "{{ if ne .Venv \"default\" }}{{ .Venv }} {{ end }}{{ .Major }}.{{ .Minor }}", + }, } for _, tc := range cases { @@ -48,6 +64,12 @@ func TestPythonTemplate(t *testing.T) { env.On("HasCommand", "python").Return(true) env.On("RunCommand", "python", []string{"--version"}).Return("Python 3.8.4", nil) env.On("HasFiles", "*.py").Return(true) + env.On("HasParentFilePath", ".python-version").Return(&environment.FileInfo{ + ParentFolder: "/usr/home/project", + Path: "/usr/home/project/.python-version", + IsDir: false, + }, nil) + env.On("FileContent", "/usr/home/project/.python-version").Return(tc.PyenvLocal) env.On("Getenv", "VIRTUAL_ENV").Return(tc.VirtualEnvName) env.On("Getenv", "CONDA_ENV_PATH").Return(tc.VirtualEnvName) env.On("Getenv", "CONDA_DEFAULT_ENV").Return(tc.VirtualEnvName) @@ -57,6 +79,7 @@ func TestPythonTemplate(t *testing.T) { env.On("Home").Return("/usr/home") props := properties.Map{ properties.FetchVersion: tc.FetchVersion, + UsePythonVersionFile: true, DisplayMode: DisplayModeAlways, } env.On("TemplateCache").Return(&environment.TemplateCache{ @@ -85,6 +108,7 @@ func TestPythonPythonInContext(t *testing.T) { env.On("Getenv", "CONDA_ENV_PATH").Return("") env.On("Getenv", "CONDA_DEFAULT_ENV").Return("") env.On("Getenv", "PYENV_VERSION").Return("") + env.On("HasParentFilePath", ".python-version").Return(&environment.FileInfo{}, errors.New("no match at root level")) python := &Python{} python.Init(properties.Map{}, env) python.loadContext()