-
Notifications
You must be signed in to change notification settings - Fork 182
Make pydabs/venv_path optional
#1687
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,9 +3,23 @@ package python | |
| import ( | ||
| "context" | ||
| "errors" | ||
| "fmt" | ||
| "io/fs" | ||
| "os" | ||
| "os/exec" | ||
| "path/filepath" | ||
| "runtime" | ||
| ) | ||
|
|
||
| // DetectExecutable looks up the path to the python3 executable from the PATH | ||
| // environment variable. | ||
| // | ||
| // If virtualenv is activated, executable from the virtualenv is returned, | ||
| // because activating virtualenv adds python3 executable on a PATH. | ||
| // | ||
| // If python3 executable is not found on the PATH, the interpreter with the | ||
| // least version that satisfies minimal 3.8 version is returned, e.g. | ||
| // python3.10. | ||
| func DetectExecutable(ctx context.Context) (string, error) { | ||
| // TODO: add a shortcut if .python-version file is detected somewhere in | ||
| // the parent directory tree. | ||
|
|
@@ -32,3 +46,35 @@ func DetectExecutable(ctx context.Context) (string, error) { | |
| } | ||
| return interpreter.Path, nil | ||
| } | ||
|
|
||
| // DetectVEnvExecutable returns the path to the python3 executable inside venvPath, | ||
| // that is not necessarily activated. | ||
| // | ||
| // If virtualenv is not created, or executable doesn't exist, the error is returned. | ||
| func DetectVEnvExecutable(venvPath string) (string, error) { | ||
| interpreterPath := filepath.Join(venvPath, "bin", "python3") | ||
| if runtime.GOOS == "windows" { | ||
| interpreterPath = filepath.Join(venvPath, "Scripts", "python3.exe") | ||
| } | ||
|
|
||
| if _, err := os.Stat(interpreterPath); err != nil { | ||
| if os.IsNotExist(err) { | ||
| return "", fmt.Errorf("can't find %q, check if virtualenv is created", interpreterPath) | ||
| } else { | ||
| return "", fmt.Errorf("can't find %q: %w", interpreterPath, err) | ||
| } | ||
| } | ||
|
|
||
| // pyvenv.cfg must be always present in correctly configured virtualenv, | ||
| // read more in https://snarky.ca/how-virtual-environments-work/ | ||
| pyvenvPath := filepath.Join(venvPath, "pyvenv.cfg") | ||
| if _, err := os.Stat(pyvenvPath); err != nil { | ||
| if errors.Is(err, fs.ErrNotExist) { | ||
| return "", fmt.Errorf("expected %q to be virtualenv, but pyvenv.cfg is missing", venvPath) | ||
| } else { | ||
| return "", fmt.Errorf("can't find %q: %w", pyvenvPath, err) | ||
| } | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What happens on other errors?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure what else can go wrong. What do you mean?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any other error, like Like the conditional above, it's good practice to never swallow errors.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 Oh, I see. This is a mistake, it wasn't intended. I will fix it |
||
|
|
||
| return interpreterPath, nil | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| package python | ||
|
|
||
| import ( | ||
| "os" | ||
| "path/filepath" | ||
| "runtime" | ||
| "testing" | ||
|
|
||
| "github.com/stretchr/testify/assert" | ||
| "github.com/stretchr/testify/require" | ||
| ) | ||
|
|
||
| func TestDetectVEnvExecutable(t *testing.T) { | ||
| dir := t.TempDir() | ||
| interpreterPath := interpreterPath(dir) | ||
|
|
||
| err := os.Mkdir(filepath.Dir(interpreterPath), 0755) | ||
| require.NoError(t, err) | ||
|
|
||
| err = os.WriteFile(interpreterPath, []byte(""), 0755) | ||
| require.NoError(t, err) | ||
|
|
||
| err = os.WriteFile(filepath.Join(dir, "pyvenv.cfg"), []byte(""), 0755) | ||
| require.NoError(t, err) | ||
|
|
||
| executable, err := DetectVEnvExecutable(dir) | ||
|
|
||
| assert.NoError(t, err) | ||
| assert.Equal(t, interpreterPath, executable) | ||
| } | ||
|
|
||
| func TestDetectVEnvExecutable_badLayout(t *testing.T) { | ||
| dir := t.TempDir() | ||
|
|
||
| _, err := DetectVEnvExecutable(dir) | ||
|
|
||
| assert.Errorf(t, err, "can't find %q, check if virtualenv is created", interpreterPath(dir)) | ||
| } | ||
|
|
||
| func interpreterPath(venvPath string) string { | ||
| if runtime.GOOS == "windows" { | ||
| return filepath.Join(venvPath, "Scripts", "python3.exe") | ||
| } else { | ||
| return filepath.Join(venvPath, "bin", "python3") | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.