From f9c70982da3dd192046f10a262abe7701e1d9cb1 Mon Sep 17 00:00:00 2001 From: Roi Martin Date: Mon, 26 Jun 2017 10:14:33 +0200 Subject: [PATCH] Fix issue #569 (#1040) * Fix issue #569 - Split python interpreter search in paths and virtualenvs - Remove dupplicated venv path checks * Fix possible race condition on suggestionsFromKnownVenvs() * Minor changes --- .../providers/setInterpreterProvider.ts | 51 ++++++++++++------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/src/client/providers/setInterpreterProvider.ts b/src/client/providers/setInterpreterProvider.ts index 5d22c48f496c..4e62fbf9ac61 100644 --- a/src/client/providers/setInterpreterProvider.ts +++ b/src/client/providers/setInterpreterProvider.ts @@ -36,9 +36,6 @@ function getSearchPaths(): Promise { if (localAppData) { lookupParentDirectories.push(path.join(appData, 'Programs')); } - if (settings.PythonSettings.getInstance().venvPath) { - lookupParentDirectories.push(settings.PythonSettings.getInstance().venvPath); - } const dirPromises = lookupParentDirectories.map(rootDir => { if (!rootDir) { return Promise.resolve([]); @@ -69,8 +66,7 @@ function getSearchPaths(): Promise { return validPathsCollection.reduce((previousValue, currentValue) => previousValue.concat(currentValue), []); }); } else { - let paths = ['/usr/local/bin', '/usr/bin', '/bin', '/usr/sbin', '/sbin', '/usr/local/sbin', '/Envs', '/.virtualenvs', '/.pyenv', - '/.pyenv/versions']; + let paths = ['/usr/local/bin', '/usr/bin', '/bin', '/usr/sbin', '/sbin', '/usr/local/sbin']; paths.forEach(p => { paths.push(untildify('~' + p)); }); @@ -79,12 +75,23 @@ function getSearchPaths(): Promise { paths.push(path.join(process.env['HOME'], 'anaconda', 'bin')); paths.push(path.join(process.env['HOME'], 'python', 'bin')); } - if (settings.PythonSettings.getInstance().venvPath) { - paths.push(settings.PythonSettings.getInstance().venvPath); - } return Promise.resolve(paths); } } +function getSearchVenvs(): Promise { + let paths = []; + if (!utils.IS_WINDOWS) { + const defaultPaths = ['/Envs', '/.virtualenvs', '/.pyenv', '/.pyenv/versions']; + defaultPaths.forEach(p => { + paths.push(untildify('~' + p)); + }); + } + const venvPath = settings.PythonSettings.getInstance().venvPath; + if (venvPath) { + paths.push(untildify(venvPath)); + } + return Promise.resolve(paths); +} export function activateSetInterpreterProvider(): vscode.Disposable { return vscode.commands.registerCommand("python.setInterpreter", setInterpreter); @@ -104,7 +111,7 @@ function lookForInterpretersInPath(pathToCheck: string): Promise { }); }); } -function lookForInterpretersInVirtualEnvs(pathToCheck: string): Promise { +function lookForInterpretersInVenvs(pathToCheck: string): Promise { return new Promise(resolve => { // Now look for Interpreters in this directory fs.readdir(pathToCheck, (err, subDirs) => { @@ -168,6 +175,21 @@ function suggestionsFromKnownPaths(): Promise { }); }); } +function suggestionsFromKnownVenvs(): Promise { + return getSearchVenvs().then(paths => { + const promises = paths.map(p => { + return lookForInterpretersInVenvs(p); + }); + + return Promise.all(promises).then(listOfInterpreters => { + let suggestions: PythonPathSuggestion[] = []; + listOfInterpreters.forEach(s => { + suggestions.push(...s); + }); + return suggestions; + }); + }); +} function suggestionsFromConda(): Promise { return new Promise((resolve, reject) => { // interrogate conda (if it's on the path) to find all environments @@ -217,15 +239,10 @@ function suggestPythonPaths(): Promise { // For now we only interrogate conda for suggestions. const condaSuggestions = suggestionsFromConda(); const knownPathSuggestions = suggestionsFromKnownPaths(); - const workspaceVirtualEnvSuggestions = lookForInterpretersInVirtualEnvs(vscode.workspace.rootPath); - - const suggestionPromises = [condaSuggestions, knownPathSuggestions, workspaceVirtualEnvSuggestions]; - - if (settings.PythonSettings.getInstance().venvPath) { - suggestionPromises.push(lookForInterpretersInVirtualEnvs(settings.PythonSettings.getInstance().venvPath)); - } + const knownVenvSuggestions = suggestionsFromKnownVenvs(); + const workspaceVirtualEnvSuggestions = lookForInterpretersInVenvs(vscode.workspace.rootPath); - // Here we could also look for virtualenvs/default install locations... + const suggestionPromises = [condaSuggestions, knownPathSuggestions, knownVenvSuggestions, workspaceVirtualEnvSuggestions]; return Promise.all(suggestionPromises).then(suggestions => { const quickPicks: PythonPathQuickPickItem[] = [];