From 38fa2f6f26cf1661cb173aa3eef75310033348ee Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Thu, 23 Jun 2022 17:34:07 -0700 Subject: [PATCH] Use `$VIRTUAL_ENV` when set Closes #36 --- README.md | 4 +++ package.json | 8 ++++- src/extension.ts | 56 ++++++++++++++++++++++---------- src/test/suite/extension.test.ts | 29 ++++++++++------- 4 files changed, 67 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 2a71e65..dc0a10e 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,10 @@ This extension is meant act as a playground for the [Python extension](https://m ## Features +### Automatic detection of activated virtual environments + +If the `VIRTUAL_ENV` environment variable is set, WWBD will use that to set the selected Python environment. + ### `Create Environment` command 1. Use an appropriate interpreter (the selected interpreter, ask the user to use the newest version of Python installed, or ask the user to pick an interpreter). diff --git a/package.json b/package.json index 31b193d..eda9a0f 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,13 @@ "Other" ], "activationEvents": [ - "onCommand:wwbd.createEnvironment" + "onCommand:wwbd.createEnvironment", + "onLanguage:python", + "workspaceContains:*.py", + "workspaceContains:mspythonconfig.json", + "workspaceContains:pyproject.toml", + "workspaceContains:Pipfile", + "workspaceContains:requirements.txt" ], "main": "./out/extension.js", "contributes": { diff --git a/src/extension.ts b/src/extension.ts index a730540..69a084a 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -3,6 +3,7 @@ import * as child_process from "node:child_process"; import * as fs from "node:fs"; import * as os from "node:os"; import * as path from "node:path"; +import * as process from "node:process"; import * as vscode from "vscode"; import * as pvsc from "./pvsc"; @@ -15,7 +16,21 @@ export interface PythonPayload { requirementsFile: string | null; } -export function activate(context: vscode.ExtensionContext): void { +export function venvExecutable(dir: undefined): undefined; +export function venvExecutable(dir: string): string; +export function venvExecutable(dir: string | undefined): string | undefined; +export function venvExecutable(dir: string | undefined): string | undefined { + if (dir === undefined) { + return undefined; + } + return os.platform() === "win32" + ? path.join(dir, "Scripts", "python.exe") + : path.join(dir, "bin", "python"); +} + +export async function activate( + context: vscode.ExtensionContext +): Promise { let disposable = vscode.commands.registerCommand( "wwbd.createEnvironment", () => @@ -32,6 +47,19 @@ export function activate(context: vscode.ExtensionContext): void { ); context.subscriptions.push(disposable); + + const activatedVirtualEnv = venvExecutable(process.env.VIRTUAL_ENV); + if (activatedVirtualEnv !== undefined) { + outputChannel.appendLine( + `$VIRTUAL_ENV is set to ${process.env.VIRTUAL_ENV}` + ); + const pythonExtension = await pvscApi(); + await pythonExtension?.environment.setActiveEnvironment( + activatedVirtualEnv + ); + } else { + outputChannel.appendLine("$VIRTUAL_ENV is not set"); + } } export function deactivate(): void {} @@ -197,12 +225,6 @@ function noInterpreterSelected(): void { vscode.window.showErrorMessage("No interpreter selected."); } -export function venvExecutable(dir: string): string { - return os.platform() === "win32" - ? path.join(dir, "Scripts", "python.exe") - : path.join(dir, "bin", "python"); -} - export function parseOutput(output: string): PythonPayload | undefined { const jsonMatch = jsonTagRegex.exec(output); @@ -279,17 +301,15 @@ async function createEnvironment( if (fs.existsSync(venvInterpreter)) { const selectEnvironmentButton = "Select Environment"; - vscode.window - .showWarningMessage( - "A virtual environment already exists at `.venv`. Would you like to select it and halt environment creation?", - selectEnvironmentButton, - "Cancel" - ) - .then((selected) => { - if (selected === selectEnvironmentButton) { - pythonExtension.environment.setActiveEnvironment(venvInterpreter); - } - }); + const selected = await vscode.window.showWarningMessage( + "A virtual environment already exists at `.venv`. Would you like to select it and halt environment creation?", + selectEnvironmentButton, + "Cancel" + ); + + if (selected === selectEnvironmentButton) { + await pythonExtension.environment.setActiveEnvironment(venvInterpreter); + } return; } else { diff --git a/src/test/suite/extension.test.ts b/src/test/suite/extension.test.ts index 4a0c844..4762386 100644 --- a/src/test/suite/extension.test.ts +++ b/src/test/suite/extension.test.ts @@ -1,6 +1,7 @@ import * as assert from "node:assert"; import * as os from "node:os"; import * as path from "node:path"; +import * as process from "node:process"; import * as vscode from "vscode"; import * as wwbd from "../../extension"; import * as pvsc from "../../pvsc"; @@ -14,6 +15,23 @@ function arrayEquals(a: T[], b: T[]): void { suite("Unit Tests", function () { vscode.window.showInformationMessage("Start all tests."); + suite("venvExecutable()", function () { + test("string", function () { + const dir = ".venv"; + + const expect = + os.platform() === "win32" + ? path.join(dir, "Scripts", "python.exe") + : path.join(dir, "bin", "python"); + + assert.strictEqual(wwbd.venvExecutable(dir), expect); + }); + + test("undefined", function () { + assert.strictEqual(wwbd.venvExecutable(undefined), undefined); + }); + }); + suite("isGlobal()", function () { const knownKinds = [ pvsc.PythonEnvKind.Unknown, @@ -129,17 +147,6 @@ suite("Unit Tests", function () { arrayEquals(wwbd.filterByPathType(given), expected); }); - test("venvExecutable()", function () { - const dir = ".venv"; - - const expect = - os.platform() === "win32" - ? path.join(dir, "Scripts", "python.exe") - : path.join(dir, "bin", "python"); - - assert.strictEqual(wwbd.venvExecutable(dir), expect); - }); - suite("parseOutput()", function () { const badOutput = "People put the strangest stuff in their `sitecustomize.py` ...";