From 8ad93f6667a54fe71fde419904f05037265b7db1 Mon Sep 17 00:00:00 2001 From: andreamah Date: Fri, 17 Apr 2020 12:19:04 -0700 Subject: [PATCH 1/5] made setup changes for python3 call --- src/constants.ts | 1 + src/service/setupService.ts | 153 ++++++++++++++++++++++++------------ 2 files changed, 102 insertions(+), 52 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index fb77451e7..1c759917d 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -547,6 +547,7 @@ export const HELPER_FILES = { export const GLOBAL_ENV_VARS = { PYTHON: "python", + PYTHON3: "python3" }; export const LANGUAGE_VARS = { PYTHON: { ID: "python", FILE_ENDS: ".py" }, diff --git a/src/service/setupService.ts b/src/service/setupService.ts index c68f78fbd..22f9fdcde 100644 --- a/src/service/setupService.ts +++ b/src/service/setupService.ts @@ -159,26 +159,29 @@ export class SetupService { return pythonExecutablePath; }; - public getCurrentPythonExecutablePath = async () => { + public getCurrentPythonExecutablePath = async (tryingPython3: boolean = false) => { let originalpythonExecutablePath = ""; - + const systemPythonVar = tryingPython3 ? GLOBAL_ENV_VARS.PYTHON3 : GLOBAL_ENV_VARS.PYTHON; // try to get name from interpreter try { originalpythonExecutablePath = getConfig(CONFIG.PYTHON_PATH); } catch (err) { - originalpythonExecutablePath = GLOBAL_ENV_VARS.PYTHON; + originalpythonExecutablePath = systemPythonVar; } if ( + originalpythonExecutablePath === GLOBAL_ENV_VARS.PYTHON3 || originalpythonExecutablePath === GLOBAL_ENV_VARS.PYTHON || originalpythonExecutablePath === "" ) { + // catching any instance where the python path needs to be resolved + // from an system variable this.telemetryAI.trackFeatureUsage( TelemetryEventName.SETUP_AUTO_RESOLVE_PYTHON_PATH ); try { const { stdout } = await this.executePythonCommand( - GLOBAL_ENV_VARS.PYTHON, + systemPythonVar, `-c "import sys; print(sys.executable)"` ); originalpythonExecutablePath = stdout.trim(); @@ -186,17 +189,102 @@ export class SetupService { this.telemetryAI.trackFeatureUsage( TelemetryEventName.SETUP_NO_PYTHON_PATH ); + if (tryingPython3) { + // if trying python3 failed, that means that BOTH + // python and python3 failed as system variables + // so that means that there is no python + vscode.window + .showErrorMessage( + CONSTANTS.ERROR.NO_PYTHON_PATH, + DialogResponses.INSTALL_PYTHON + ) + .then((selection: vscode.MessageItem | undefined) => { + if (selection === DialogResponses.INSTALL_PYTHON) { + const okAction = () => { + this.telemetryAI.trackFeatureUsage( + TelemetryEventName.SETUP_DOWNLOAD_PYTHON + ); + open(CONSTANTS.LINKS.DOWNLOAD_PYTHON); + }; + showPrivacyModal( + okAction, + CONSTANTS.INFO.THIRD_PARTY_WEBSITE_PYTHON + ); + } + }); + // no python installed, cannot get path + return ""; + } else { + // "python" didn't resolve to anything, trying "python3" + return this.getCurrentPythonExecutablePath(true); + } + } + if (!(await this.validatePythonVersion(originalpythonExecutablePath))) { + this.telemetryAI.trackFeatureUsage( + TelemetryEventName.SETUP_INVALID_PYTHON_VER + ); + if (tryingPython3) { + // if we're trying python3, it means we already tried python and it + // all doesn't seem to work, but it got this far, so it means that + // their system python3 version is still not above 3.7, but they + // don't have a path selected. + vscode.window + .showInformationMessage( + CONSTANTS.ERROR.INVALID_PYTHON_PATH, + DialogResponses.INSTALL_PYTHON + ) + .then((installChoice: vscode.MessageItem | undefined) => { + if (installChoice === DialogResponses.INSTALL_PYTHON) { + const okAction = () => { + open(CONSTANTS.LINKS.DOWNLOAD_PYTHON); + }; + showPrivacyModal( + okAction, + CONSTANTS.INFO.THIRD_PARTY_WEBSITE_PYTHON + ); + } + }); + return ""; + } else { + // otherwise, we ran the "python" system variable + // and we can try python3 + return this.getCurrentPythonExecutablePath(true); + } + + } + } else { + // should only be applicable if the user defined their own path + + // fix path to be absolute + if (!path.isAbsolute(originalpythonExecutablePath)) { + originalpythonExecutablePath = path.join( + vscode.workspace.rootPath, + originalpythonExecutablePath + ); + } + + if (!fs.existsSync(originalpythonExecutablePath)) { + await vscode.window.showErrorMessage( + CONSTANTS.ERROR.BAD_PYTHON_PATH + ); + this.telemetryAI.trackFeatureUsage( + TelemetryEventName.SETUP_INVALID_PYTHON_INTERPRETER_PATH + ); + return ""; + } + + if (!(await this.validatePythonVersion(originalpythonExecutablePath))) { + this.telemetryAI.trackFeatureUsage( + TelemetryEventName.SETUP_INVALID_PYTHON_VER + ); vscode.window - .showErrorMessage( - CONSTANTS.ERROR.NO_PYTHON_PATH, + .showInformationMessage( + CONSTANTS.ERROR.INVALID_PYTHON_PATH, DialogResponses.INSTALL_PYTHON ) - .then((selection: vscode.MessageItem | undefined) => { - if (selection === DialogResponses.INSTALL_PYTHON) { + .then((installChoice: vscode.MessageItem | undefined) => { + if (installChoice === DialogResponses.INSTALL_PYTHON) { const okAction = () => { - this.telemetryAI.trackFeatureUsage( - TelemetryEventName.SETUP_DOWNLOAD_PYTHON - ); open(CONSTANTS.LINKS.DOWNLOAD_PYTHON); }; showPrivacyModal( @@ -205,34 +293,11 @@ export class SetupService { ); } }); - // no python installed, cannot get path return ""; - } - } - // fix path to be absolute - if (!path.isAbsolute(originalpythonExecutablePath)) { - originalpythonExecutablePath = path.join( - vscode.workspace.rootPath, - originalpythonExecutablePath - ); - } - if (!fs.existsSync(originalpythonExecutablePath)) { - await vscode.window.showErrorMessage( - CONSTANTS.ERROR.BAD_PYTHON_PATH - ); - this.telemetryAI.trackFeatureUsage( - TelemetryEventName.SETUP_INVALID_PYTHON_INTERPRETER_PATH - ); - return ""; + } } - if (!(await this.validatePythonVersion(originalpythonExecutablePath))) { - this.telemetryAI.trackFeatureUsage( - TelemetryEventName.SETUP_INVALID_PYTHON_VER - ); - return ""; - } return originalpythonExecutablePath; }; @@ -247,7 +312,7 @@ export class SetupService { } catch (err) { vscode.window .showErrorMessage( - CONSTANTS.ERROR.NO_PIP, + `We found that you may not Pip installed on your interpreter at ${pythonExecutablePath}, please install it and try again.`, DialogResponses.INSTALL_PIP ) .then((selection: vscode.MessageItem | undefined) => { @@ -294,22 +359,6 @@ export class SetupService { "--version" ); if (stdout < VERSIONS.MIN_PY_VERSION) { - vscode.window - .showInformationMessage( - CONSTANTS.ERROR.INVALID_PYTHON_PATH, - DialogResponses.INSTALL_PYTHON - ) - .then((installChoice: vscode.MessageItem | undefined) => { - if (installChoice === DialogResponses.INSTALL_PYTHON) { - const okAction = () => { - open(CONSTANTS.LINKS.DOWNLOAD_PYTHON); - }; - showPrivacyModal( - okAction, - CONSTANTS.INFO.THIRD_PARTY_WEBSITE_PYTHON - ); - } - }); return false; } else { return true; From d701e8d94ca675aa947598fb7976b51f8f3deb6d Mon Sep 17 00:00:00 2001 From: andreamah Date: Fri, 17 Apr 2020 20:55:43 +0000 Subject: [PATCH 2/5] dependency fixes --- src/constants.ts | 6 +----- src/install_dependencies.py | 2 +- src/service/setupService.ts | 6 +++--- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index 1c759917d..d5b4347c9 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -112,10 +112,6 @@ export const CONSTANTS = { "error.noProgramFoundDebug", "Cannot find a program to debug." ), - NO_PIP: localize( - "error.noPip", - "We found that you don't have Pip installed on your computer, please install it and try again." - ), NO_PYTHON_PATH: localize( "error.noPythonPath", "We found that you don't have Python 3 installed on your computer, please install the latest version, add it to your PATH and try again." @@ -533,7 +529,7 @@ export const STATUS_BAR_PRIORITY = { }; export const VERSIONS = { - MIN_PY_VERSION: "3.7.0", + MIN_PY_VERSION: "Python 3.7.0", }; export const HELPER_FILES = { diff --git a/src/install_dependencies.py b/src/install_dependencies.py index afadb9dd5..00fe81d37 100644 --- a/src/install_dependencies.py +++ b/src/install_dependencies.py @@ -3,7 +3,7 @@ import pathlib import os -os.chdir(pathlib.Path(__file__).parent.parent.absolute()) +os.chdir(str(pathlib.Path(__file__).parent.parent.absolute())) subprocess.check_call( [sys.executable, "-m", "pip", "install", "-r", "./out/requirements.txt"] ) diff --git a/src/service/setupService.ts b/src/service/setupService.ts index 22f9fdcde..34e04331a 100644 --- a/src/service/setupService.ts +++ b/src/service/setupService.ts @@ -304,7 +304,7 @@ export class SetupService { public isPipInstalled = async (pythonExecutablePath: string) => { try { - const { stdout } = await this.executePythonCommand( + await this.executePythonCommand( pythonExecutablePath, " -m pip" ); @@ -312,7 +312,7 @@ export class SetupService { } catch (err) { vscode.window .showErrorMessage( - `We found that you may not Pip installed on your interpreter at ${pythonExecutablePath}, please install it and try again.`, + `We found that you may not have Pip installed on your interpreter at ${pythonExecutablePath}, please install it and try again.`, DialogResponses.INSTALL_PIP ) .then((selection: vscode.MessageItem | undefined) => { @@ -447,7 +447,7 @@ export class SetupService { ); vscode.window .showErrorMessage( - `Virtual environment for download could not be completed. Using original interpreter at: ${pythonExecutable}.`, + `Virtual environment for download could not be completed. Using original interpreter at: ${pythonExecutable}. If you're on Linux, try running "sudo apt-get install python3-venv".`, DialogResponses.READ_INSTALL_MD ) .then((selection: vscode.MessageItem | undefined) => { From 8ee166a8de96d16e18d3911e254f9e7c8c2e041a Mon Sep 17 00:00:00 2001 From: andreamah Date: Fri, 17 Apr 2020 13:57:59 -0700 Subject: [PATCH 3/5] formatting --- src/constants.ts | 2 +- src/service/setupService.ts | 60 ++++++++++++++++++++++--------------- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index d5b4347c9..bcde974b7 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -543,7 +543,7 @@ export const HELPER_FILES = { export const GLOBAL_ENV_VARS = { PYTHON: "python", - PYTHON3: "python3" + PYTHON3: "python3", }; export const LANGUAGE_VARS = { PYTHON: { ID: "python", FILE_ENDS: ".py" }, diff --git a/src/service/setupService.ts b/src/service/setupService.ts index 34e04331a..221909738 100644 --- a/src/service/setupService.ts +++ b/src/service/setupService.ts @@ -159,9 +159,13 @@ export class SetupService { return pythonExecutablePath; }; - public getCurrentPythonExecutablePath = async (tryingPython3: boolean = false) => { + public getCurrentPythonExecutablePath = async ( + tryingPython3: boolean = false + ) => { let originalpythonExecutablePath = ""; - const systemPythonVar = tryingPython3 ? GLOBAL_ENV_VARS.PYTHON3 : GLOBAL_ENV_VARS.PYTHON; + const systemPythonVar = tryingPython3 + ? GLOBAL_ENV_VARS.PYTHON3 + : GLOBAL_ENV_VARS.PYTHON; // try to get name from interpreter try { originalpythonExecutablePath = getConfig(CONFIG.PYTHON_PATH); @@ -219,38 +223,47 @@ export class SetupService { return this.getCurrentPythonExecutablePath(true); } } - if (!(await this.validatePythonVersion(originalpythonExecutablePath))) { + if ( + !(await this.validatePythonVersion( + originalpythonExecutablePath + )) + ) { this.telemetryAI.trackFeatureUsage( TelemetryEventName.SETUP_INVALID_PYTHON_VER ); if (tryingPython3) { - // if we're trying python3, it means we already tried python and it - // all doesn't seem to work, but it got this far, so it means that - // their system python3 version is still not above 3.7, but they + // if we're trying python3, it means we already tried python and it + // all doesn't seem to work, but it got this far, so it means that + // their system python3 version is still not above 3.7, but they // don't have a path selected. vscode.window .showInformationMessage( CONSTANTS.ERROR.INVALID_PYTHON_PATH, DialogResponses.INSTALL_PYTHON ) - .then((installChoice: vscode.MessageItem | undefined) => { - if (installChoice === DialogResponses.INSTALL_PYTHON) { - const okAction = () => { - open(CONSTANTS.LINKS.DOWNLOAD_PYTHON); - }; - showPrivacyModal( - okAction, - CONSTANTS.INFO.THIRD_PARTY_WEBSITE_PYTHON - ); + .then( + (installChoice: vscode.MessageItem | undefined) => { + if ( + installChoice === + DialogResponses.INSTALL_PYTHON + ) { + const okAction = () => { + open(CONSTANTS.LINKS.DOWNLOAD_PYTHON); + }; + showPrivacyModal( + okAction, + CONSTANTS.INFO + .THIRD_PARTY_WEBSITE_PYTHON + ); + } } - }); + ); return ""; } else { // otherwise, we ran the "python" system variable // and we can try python3 return this.getCurrentPythonExecutablePath(true); } - } } else { // should only be applicable if the user defined their own path @@ -273,7 +286,11 @@ export class SetupService { return ""; } - if (!(await this.validatePythonVersion(originalpythonExecutablePath))) { + if ( + !(await this.validatePythonVersion( + originalpythonExecutablePath + )) + ) { this.telemetryAI.trackFeatureUsage( TelemetryEventName.SETUP_INVALID_PYTHON_VER ); @@ -294,20 +311,15 @@ export class SetupService { } }); return ""; - } } - return originalpythonExecutablePath; }; public isPipInstalled = async (pythonExecutablePath: string) => { try { - await this.executePythonCommand( - pythonExecutablePath, - " -m pip" - ); + await this.executePythonCommand(pythonExecutablePath, " -m pip"); return true; } catch (err) { vscode.window From ef77c0136be691fd24f4a64ab4d992cebfe0c5f2 Mon Sep 17 00:00:00 2001 From: andreamah Date: Fri, 17 Apr 2020 22:08:21 +0000 Subject: [PATCH 4/5] pr feedback --- src/service/setupService.ts | 50 +++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/src/service/setupService.ts b/src/service/setupService.ts index 221909738..45def4a03 100644 --- a/src/service/setupService.ts +++ b/src/service/setupService.ts @@ -32,8 +32,8 @@ export class SetupService { context: vscode.ExtensionContext, needsResponse: boolean = false ) => { - const originalpythonExecutablePath = await this.getCurrentPythonExecutablePath(); - let pythonExecutablePath = originalpythonExecutablePath; + const originalPythonExecutablePath = await this.getCurrentPythonExecutablePath(); + let pythonExecutablePath = originalPythonExecutablePath; const pythonExecutableName: string = os.platform() === "win32" ? HELPER_FILES.PYTHON_EXE @@ -71,7 +71,7 @@ export class SetupService { } else { pythonExecutablePath = await this.promptInstallVenv( context, - originalpythonExecutablePath, + originalPythonExecutablePath, pythonExecutableName ); this.telemetryAI.trackFeatureUsage( @@ -92,7 +92,7 @@ export class SetupService { TelemetryEventName.SETUP_HAS_VENV ); } - if (pythonExecutablePath === originalpythonExecutablePath) { + if (pythonExecutablePath === originalPythonExecutablePath) { // going with original interpreter, either because // already in venv or error in creating custom venv if (checkConfig(CONFIG.SHOW_DEPENDENCY_INSTALL)) { @@ -160,23 +160,23 @@ export class SetupService { }; public getCurrentPythonExecutablePath = async ( - tryingPython3: boolean = false + isTryingPython3: boolean = false ) => { - let originalpythonExecutablePath = ""; - const systemPythonVar = tryingPython3 + let originalPythonExecutablePath = ""; + const systemPythonVar = isTryingPython3 ? GLOBAL_ENV_VARS.PYTHON3 : GLOBAL_ENV_VARS.PYTHON; // try to get name from interpreter try { - originalpythonExecutablePath = getConfig(CONFIG.PYTHON_PATH); + originalPythonExecutablePath = getConfig(CONFIG.PYTHON_PATH); } catch (err) { - originalpythonExecutablePath = systemPythonVar; + originalPythonExecutablePath = systemPythonVar; } if ( - originalpythonExecutablePath === GLOBAL_ENV_VARS.PYTHON3 || - originalpythonExecutablePath === GLOBAL_ENV_VARS.PYTHON || - originalpythonExecutablePath === "" + originalPythonExecutablePath === GLOBAL_ENV_VARS.PYTHON3 || + originalPythonExecutablePath === GLOBAL_ENV_VARS.PYTHON || + originalPythonExecutablePath === "" ) { // catching any instance where the python path needs to be resolved // from an system variable @@ -188,12 +188,12 @@ export class SetupService { systemPythonVar, `-c "import sys; print(sys.executable)"` ); - originalpythonExecutablePath = stdout.trim(); + originalPythonExecutablePath = stdout.trim(); } catch (err) { this.telemetryAI.trackFeatureUsage( TelemetryEventName.SETUP_NO_PYTHON_PATH ); - if (tryingPython3) { + if (isTryingPython3) { // if trying python3 failed, that means that BOTH // python and python3 failed as system variables // so that means that there is no python @@ -225,13 +225,13 @@ export class SetupService { } if ( !(await this.validatePythonVersion( - originalpythonExecutablePath + originalPythonExecutablePath )) ) { this.telemetryAI.trackFeatureUsage( TelemetryEventName.SETUP_INVALID_PYTHON_VER ); - if (tryingPython3) { + if (isTryingPython3) { // if we're trying python3, it means we already tried python and it // all doesn't seem to work, but it got this far, so it means that // their system python3 version is still not above 3.7, but they @@ -248,6 +248,9 @@ export class SetupService { DialogResponses.INSTALL_PYTHON ) { const okAction = () => { + this.telemetryAI.trackFeatureUsage( + TelemetryEventName.SETUP_DOWNLOAD_PYTHON + ); open(CONSTANTS.LINKS.DOWNLOAD_PYTHON); }; showPrivacyModal( @@ -269,14 +272,14 @@ export class SetupService { // should only be applicable if the user defined their own path // fix path to be absolute - if (!path.isAbsolute(originalpythonExecutablePath)) { - originalpythonExecutablePath = path.join( + if (!path.isAbsolute(originalPythonExecutablePath)) { + originalPythonExecutablePath = path.join( vscode.workspace.rootPath, - originalpythonExecutablePath + originalPythonExecutablePath ); } - if (!fs.existsSync(originalpythonExecutablePath)) { + if (!fs.existsSync(originalPythonExecutablePath)) { await vscode.window.showErrorMessage( CONSTANTS.ERROR.BAD_PYTHON_PATH ); @@ -288,7 +291,7 @@ export class SetupService { if ( !(await this.validatePythonVersion( - originalpythonExecutablePath + originalPythonExecutablePath )) ) { this.telemetryAI.trackFeatureUsage( @@ -302,6 +305,9 @@ export class SetupService { .then((installChoice: vscode.MessageItem | undefined) => { if (installChoice === DialogResponses.INSTALL_PYTHON) { const okAction = () => { + this.telemetryAI.trackFeatureUsage( + TelemetryEventName.SETUP_DOWNLOAD_PYTHON + ); open(CONSTANTS.LINKS.DOWNLOAD_PYTHON); }; showPrivacyModal( @@ -314,7 +320,7 @@ export class SetupService { } } - return originalpythonExecutablePath; + return originalPythonExecutablePath; }; public isPipInstalled = async (pythonExecutablePath: string) => { From dc8ed9553f9d44e00c201e91b6103b88b0acdd30 Mon Sep 17 00:00:00 2001 From: andreamah Date: Fri, 17 Apr 2020 22:47:31 +0000 Subject: [PATCH 5/5] fixed version too low issue --- src/service/setupService.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/service/setupService.ts b/src/service/setupService.ts index 45def4a03..04c757a72 100644 --- a/src/service/setupService.ts +++ b/src/service/setupService.ts @@ -33,6 +33,9 @@ export class SetupService { needsResponse: boolean = false ) => { const originalPythonExecutablePath = await this.getCurrentPythonExecutablePath(); + if (originalPythonExecutablePath === "") { + return; + } let pythonExecutablePath = originalPythonExecutablePath; const pythonExecutableName: string = os.platform() === "win32"