diff --git a/package-lock.json b/package-lock.json index a5b4e37b..ae06972b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "MIT", "dependencies": { "@vscode/extension-telemetry": "^0.8.5", + "@vscode/python-extension": "^1.0.5", "fs-extra": "^11.2.0", "iconv-lite": "^0.6.3", "inversify": "^6.0.1", @@ -30,7 +31,7 @@ "@types/node": "18.x", "@types/semver": "^7.3.13", "@types/sinon": "^10.0.13", - "@types/vscode": "^1.78.0", + "@types/vscode": "^1.87.0", "@typescript-eslint/eslint-plugin": "^5.31.0", "@typescript-eslint/parser": "^5.62.0", "@vscode/test-electron": "^2.3.9", @@ -53,7 +54,7 @@ "webpack-cli": "^5.1.4" }, "engines": { - "vscode": "^1.86.0" + "vscode": "^1.87.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -827,9 +828,9 @@ "dev": true }, "node_modules/@types/vscode": { - "version": "1.79.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.79.0.tgz", - "integrity": "sha512-Tfowu2rSW8hVGbqzQLSPlOEiIOYYryTkgJ+chMecpYiJcnw9n0essvSiclnK+Qh/TcSVJHgaK4EMrQDZjZJ/Sw==", + "version": "1.87.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.87.0.tgz", + "integrity": "sha512-y3yYJV2esWr8LNjp3VNbSMWG7Y43jC8pCldG8YwiHGAQbsymkkMMt0aDT1xZIOFM2eFcNiUc+dJMx1+Z0UT8fg==", "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { @@ -1108,6 +1109,15 @@ "vscode": "^1.75.0" } }, + "node_modules/@vscode/python-extension": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@vscode/python-extension/-/python-extension-1.0.5.tgz", + "integrity": "sha512-uYhXUrL/gn92mfqhjAwH2+yGOpjloBxj9ekoL4BhUsKcyJMpEg6WlNf3S3si+5x9zlbHHe7FYQNjZEbz1ymI9Q==", + "engines": { + "node": ">=16.17.1", + "vscode": "^1.78.0" + } + }, "node_modules/@vscode/test-electron": { "version": "2.3.9", "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.9.tgz", @@ -7545,9 +7555,9 @@ "dev": true }, "@types/vscode": { - "version": "1.79.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.79.0.tgz", - "integrity": "sha512-Tfowu2rSW8hVGbqzQLSPlOEiIOYYryTkgJ+chMecpYiJcnw9n0essvSiclnK+Qh/TcSVJHgaK4EMrQDZjZJ/Sw==", + "version": "1.87.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.87.0.tgz", + "integrity": "sha512-y3yYJV2esWr8LNjp3VNbSMWG7Y43jC8pCldG8YwiHGAQbsymkkMMt0aDT1xZIOFM2eFcNiUc+dJMx1+Z0UT8fg==", "dev": true }, "@typescript-eslint/eslint-plugin": { @@ -7703,6 +7713,11 @@ "applicationinsights": "^2.7.1" } }, + "@vscode/python-extension": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@vscode/python-extension/-/python-extension-1.0.5.tgz", + "integrity": "sha512-uYhXUrL/gn92mfqhjAwH2+yGOpjloBxj9ekoL4BhUsKcyJMpEg6WlNf3S3si+5x9zlbHHe7FYQNjZEbz1ymI9Q==" + }, "@vscode/test-electron": { "version": "2.3.9", "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.9.tgz", diff --git a/package.json b/package.json index 3a4cd382..16da1270 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "debugpy" ], "engines": { - "vscode": "^1.86.0" + "vscode": "^1.87.0" }, "categories": [ "Debuggers" @@ -484,6 +484,9 @@ } ] }, + "extensionDependencies": [ + "ms-python.python" + ], "scripts": { "vscode:prepublish": "npm run package", "compile": "webpack", @@ -508,7 +511,7 @@ "@types/node": "18.x", "@types/semver": "^7.3.13", "@types/sinon": "^10.0.13", - "@types/vscode": "^1.78.0", + "@types/vscode": "^1.87.0", "@typescript-eslint/eslint-plugin": "^5.31.0", "@typescript-eslint/parser": "^5.62.0", "@vscode/test-electron": "^2.3.9", @@ -532,6 +535,7 @@ }, "dependencies": { "@vscode/extension-telemetry": "^0.8.5", + "@vscode/python-extension": "^1.0.5", "fs-extra": "^11.2.0", "iconv-lite": "^0.6.3", "inversify": "^6.0.1", diff --git a/src/extension/common/python.ts b/src/extension/common/python.ts index ed1fc5f7..a82fb559 100644 --- a/src/extension/common/python.ts +++ b/src/extension/common/python.ts @@ -2,37 +2,13 @@ // Licensed under the MIT License. /* eslint-disable @typescript-eslint/naming-convention */ -import { commands, Disposable, Event, EventEmitter, extensions, Uri } from 'vscode'; -import { traceError, traceLog } from './log/logging'; -import { EnvironmentVariables } from './variables/types'; -import { - ActiveEnvironmentPathChangeEvent, - Environment, - EnvironmentPath, - EnvironmentsChangeEvent, - RefreshOptions, - ResolvedEnvironment, - Resource, -} from './pythonTypes'; +import { Environment, EnvironmentPath, PythonExtension, Resource } from '@vscode/python-extension'; +import { commands, EventEmitter, extensions, Uri, Event, Disposable } from 'vscode'; import { createDeferred } from './utils/async'; +import { traceError, traceLog } from './log/logging'; interface IExtensionApi { ready: Promise; - debug: { - getRemoteLauncherCommand(host: string, port: number, waitUntilDebuggerAttaches: boolean): Promise; - getDebuggerPackagePath(): Promise; - }; - environments: { - known: Environment[]; - getActiveEnvironmentPath(resource?: Resource): EnvironmentPath; - resolveEnvironment( - environment: Environment | EnvironmentPath | string | undefined, - ): Promise; - readonly onDidChangeActiveEnvironmentPath: Event; - getEnvironmentVariables(resource?: Resource): EnvironmentVariables; - refreshEnvironments(options?: RefreshOptions): Promise; - readonly onDidChangeEnvironments: Event; - }; settings: { getExecutionDetails(resource?: Resource): { execCommand: string[] | undefined }; }; @@ -45,7 +21,6 @@ export interface IInterpreterDetails { const onDidChangePythonInterpreterEvent = new EventEmitter(); export const onDidChangePythonInterpreter: Event = onDidChangePythonInterpreterEvent.event; - async function activateExtension() { const extension = extensions.getExtension('ms-python.python'); if (extension) { @@ -61,9 +36,15 @@ async function getPythonExtensionAPI(): Promise { return extension?.exports as IExtensionApi; } +async function getPythonExtensionEnviromentAPI(): Promise { + // Load the Python extension API + await activateExtension(); + return await PythonExtension.api(); +} + export async function initializePython(disposables: Disposable[]): Promise { try { - const api = await getPythonExtensionAPI(); + const api = await getPythonExtensionEnviromentAPI(); if (api) { disposables.push( @@ -80,11 +61,6 @@ export async function initializePython(disposables: Disposable[]): Promise } } -export async function getDebuggerPath(): Promise { - const api = await getPythonExtensionAPI(); - return api?.debug.getDebuggerPackagePath(); -} - export async function runPythonExtensionCommand(command: string, ...rest: any[]) { await activateExtension(); return await commands.executeCommand(command, ...rest); @@ -96,25 +72,23 @@ export async function getSettingsPythonPath(resource?: Uri): Promise { - const api = await getPythonExtensionAPI(); - const environment = await api?.environments.resolveEnvironment( - api?.environments.getActiveEnvironmentPath(resource), - ); + const api = await getPythonExtensionEnviromentAPI(); + const environment = await api.environments.resolveEnvironment(api.environments.getActiveEnvironmentPath(resource)); if (environment?.executable.uri) { return { path: [environment?.executable.uri.fsPath], resource }; } @@ -122,25 +96,23 @@ export async function getInterpreterDetails(resource?: Uri): Promise { - if (api.environments.known) { - onAddedToCollection.resolve(); - } - }); - const initialEnvs = api.environments.known; - if (initialEnvs.length > 0) { - return true; + const api = await getPythonExtensionEnviromentAPI(); + const onAddedToCollection = createDeferred(); + api.environments.onDidChangeEnvironments(async () => { + if (api.environments.known) { + onAddedToCollection.resolve(); } - await Promise.race([onAddedToCollection.promise, api?.environments.refreshEnvironments()]); - - return api.environments.known.length > 0; + }); + const initialEnvs = api.environments.known; + if (initialEnvs.length > 0) { + return true; } + await Promise.race([onAddedToCollection.promise, api?.environments.refreshEnvironments()]); + + return api.environments.known.length > 0; } export async function getInterpreters() { - const api = await getPythonExtensionAPI(); - return api?.environments.known || []; + const api = await getPythonExtensionEnviromentAPI(); + return api.environments.known || []; } diff --git a/src/extension/common/pythonTypes.ts b/src/extension/common/pythonTypes.ts deleted file mode 100644 index d2af2b22..00000000 --- a/src/extension/common/pythonTypes.ts +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -import { Uri, WorkspaceFolder } from 'vscode'; - -export type Environment = EnvironmentPath & { - /** - * Carries details about python executable. - */ - readonly executable: { - /** - * Uri of the python interpreter/executable. Carries `undefined` in case an executable does not belong to - * the environment. - */ - readonly uri: Uri | undefined; - /** - * Bitness if known at this moment. - */ - readonly bitness: Bitness | undefined; - /** - * Value of `sys.prefix` in sys module if known at this moment. - */ - readonly sysPrefix: string | undefined; - }; - /** - * Carries details if it is an environment, otherwise `undefined` in case of global interpreters and others. - */ - readonly environment: - | { - /** - * Type of the environment. - */ - readonly type: EnvironmentType; - /** - * Name to the environment if any. - */ - readonly name: string | undefined; - /** - * Uri of the environment folder. - */ - readonly folderUri: Uri; - /** - * Any specific workspace folder this environment is created for. - */ - readonly workspaceFolder: Uri | undefined; - } - | undefined; - /** - * Carries Python version information known at this moment. - */ - readonly version: VersionInfo & { - /** - * Value of `sys.version` in sys module if known at this moment. - */ - readonly sysVersion: string | undefined; - }; - /** - * Tools/plugins which created the environment or where it came from. First value in array corresponds - * to the primary tool which manages the environment, which never changes over time. - * - * Array is empty if no tool is responsible for creating/managing the environment. Usually the case for - * global interpreters. - */ - readonly tools: readonly EnvironmentTools[]; -}; - -/** - * Derived form of {@link Environment} where certain properties can no longer be `undefined`. Meant to represent an - * {@link Environment} with complete information. - */ -export type ResolvedEnvironment = Environment & { - /** - * Carries complete details about python executable. - */ - readonly executable: { - /** - * Uri of the python interpreter/executable. Carries `undefined` in case an executable does not belong to - * the environment. - */ - readonly uri: Uri | undefined; - /** - * Bitness of the environment. - */ - readonly bitness: Bitness; - /** - * Value of `sys.prefix` in sys module. - */ - readonly sysPrefix: string; - }; - /** - * Carries complete Python version information. - */ - readonly version: - | (ResolvedVersionInfo & { - /** - * Value of `sys.version` in sys module if known at this moment. - */ - readonly sysVersion: string; - }) - | undefined; -}; - -export type ActiveEnvironmentPathChangeEvent = EnvironmentPath & { - /** - * Workspace folder the environment changed for. - */ - readonly resource: WorkspaceFolder | undefined; -}; - -/** - * Uri of a file inside a workspace or workspace folder itself. - */ -export type Resource = Uri | WorkspaceFolder; - -export type EnvironmentDetails = { - interpreterPath: string; - envFolderPath: string; - version: {}; - environmentType: string; - metadata: {}; -}; - -export type EnvironmentPath = { - /** - * The ID of the environment. - */ - readonly id: string; - /** - * Path to environment folder or path to python executable that uniquely identifies an environment. Environments - * lacking a python executable are identified by environment folder paths, whereas other envs can be identified - * using python executable path. - */ - readonly path: string; -}; - -/** - * Tool/plugin where the environment came from. It can be {@link KnownEnvironmentTools} or custom string which - * was contributed. - */ -export type EnvironmentTools = KnownEnvironmentTools | string; -/** - * Tools or plugins the Python extension currently has built-in support for. Note this list is expected to shrink - * once tools have their own separate extensions. - */ -export type KnownEnvironmentTools = - | 'Conda' - | 'Pipenv' - | 'Poetry' - | 'VirtualEnv' - | 'Venv' - | 'VirtualEnvWrapper' - | 'Pyenv' - | 'Unknown'; - -/** - * Type of the environment. It can be {@link KnownEnvironmentTypes} or custom string which was contributed. - */ -export type EnvironmentType = KnownEnvironmentTypes | string; -/** - * Environment types the Python extension is aware of. Note this list is expected to shrink once tools have their - * own separate extensions, in which case they're expected to provide the type themselves. - */ -export type KnownEnvironmentTypes = 'VirtualEnvironment' | 'Conda' | 'Unknown'; - -/** - * Carries bitness for an environment. - */ -export type Bitness = '64-bit' | '32-bit' | 'Unknown'; - -/** - * The possible Python release levels. - */ -export type PythonReleaseLevel = 'alpha' | 'beta' | 'candidate' | 'final'; - -/** - * Release information for a Python version. - */ -export type PythonVersionRelease = { - readonly level: PythonReleaseLevel; - readonly serial: number; -}; - -export type VersionInfo = { - readonly major: number | undefined; - readonly minor: number | undefined; - readonly micro: number | undefined; - readonly release: PythonVersionRelease | undefined; -}; - -export type ResolvedVersionInfo = { - readonly major: number; - readonly minor: number; - readonly micro: number; - readonly release: PythonVersionRelease; -}; - -export type RefreshOptions = { - /** - * When `true`, force trigger a refresh regardless of whether a refresh was already triggered. Note this can be expensive so - * it's best to only use it if user manually triggers a refresh. - */ - forceRefresh?: boolean; -}; - -export type EnvironmentsChangeEvent = { - readonly env: Environment; - /** - * * "add": New environment is added. - * * "remove": Existing environment in the list is removed. - * * "update": New information found about existing environment. - */ - readonly type: 'add' | 'remove' | 'update'; -}; diff --git a/src/extension/debugger/adapter/factory.ts b/src/extension/debugger/adapter/factory.ts index d2d5b8e2..a4147596 100644 --- a/src/extension/debugger/adapter/factory.ts +++ b/src/extension/debugger/adapter/factory.ts @@ -20,11 +20,11 @@ import { executeCommand, showErrorMessage } from '../../common/vscodeapi'; import { traceLog, traceVerbose } from '../../common/log/logging'; import { EventName } from '../../telemetry/constants'; import { sendTelemetryEvent } from '../../telemetry'; -import { getActiveEnvironmentPath, resolveEnvironment, runPythonExtensionCommand } from '../../common/python'; +import { getInterpreterDetails, resolveEnvironment, runPythonExtensionCommand } from '../../common/python'; import { Commands, EXTENSION_ROOT_DIR } from '../../common/constants'; import { Common, DebugConfigStrings, Interpreters } from '../../common/utils/localize'; import { IPersistentStateFactory } from '../../common/types'; -import { Environment } from '../../common/pythonTypes'; +import { ResolvedEnvironment } from '@vscode/python-extension'; // persistent state names, exported to make use of in testing export enum debugStateKeys { @@ -121,12 +121,12 @@ export class DebugAdapterDescriptorFactory implements IDebugAdapterDescriptorFac } const resourceUri = workspaceFolder ? workspaceFolder.uri : undefined; - const interpreterPath = await getActiveEnvironmentPath(resourceUri); - const interpreter = await resolveEnvironment(interpreterPath); + + const interpreter = await getInterpreterDetails(resourceUri); if (interpreter?.path) { - traceVerbose(`Selecting active interpreter as Python Executable for DA '${interpreterPath}'`); - return this.getExecutableCommand(await resolveEnvironment(interpreterPath)); + traceVerbose(`Selecting active interpreter as Python Executable for DA '${interpreter.path[0]}'`); + return this.getExecutableCommand(await resolveEnvironment(interpreter.path[0])); } const prompts = [Interpreters.changePythonInterpreter]; @@ -139,6 +139,11 @@ export class DebugAdapterDescriptorFactory implements IDebugAdapterDescriptorFac ); if (selection === Interpreters.changePythonInterpreter) { await executeCommand(Commands.Set_Interpreter); + const interpreter = await getInterpreterDetails(resourceUri); + if (interpreter?.path) { + traceVerbose(`Selecting active interpreter as Python Executable for DA '${interpreter.path[0]}'`); + return this.getExecutableCommand(await resolveEnvironment(interpreter.path[0])); + } } return []; } @@ -171,7 +176,7 @@ export class DebugAdapterDescriptorFactory implements IDebugAdapterDescriptorFac } } - private async getExecutableCommand(interpreter: Environment | undefined): Promise { + private async getExecutableCommand(interpreter: ResolvedEnvironment | undefined): Promise { if (interpreter) { if ( (interpreter.version?.major ?? 0) < 3 || diff --git a/src/test/runTest.ts b/src/test/runTest.ts index 6e9b7057..44cc5fdf 100644 --- a/src/test/runTest.ts +++ b/src/test/runTest.ts @@ -1,6 +1,9 @@ +import * as cp from 'child_process'; import * as path from 'path'; -import { runTests } from '@vscode/test-electron'; +import { downloadAndUnzipVSCode, resolveCliArgsFromVSCodeExecutablePath, runTests } from '@vscode/test-electron'; +import { PVSC_EXTENSION_ID_FOR_TESTS } from './constants'; +import { OSType, getOSType } from '../extension/common/platform'; async function main() { try { @@ -11,9 +14,31 @@ async function main() { // The path to test runner // Passed to --extensionTestsPath const extensionTestsPath = path.resolve(__dirname, './unittest/index'); + const vscodeExecutablePath = await downloadAndUnzipVSCode('stable'); + const [cliPath, ...args] = resolveCliArgsFromVSCodeExecutablePath(vscodeExecutablePath); - // Download VS Code, unzip it and run the integration test - await runTests({ extensionDevelopmentPath, extensionTestsPath }); + // Use cp.spawn / cp.exec for custom setup + if (getOSType() == OSType.Windows) { + const exec = path.basename(cliPath); + cp.spawnSync(exec, [...args, '--install-extension', PVSC_EXTENSION_ID_FOR_TESTS], { + cwd: path.dirname(cliPath), + encoding: 'utf-8', + stdio: 'inherit', + }); + } else { + cp.spawnSync(cliPath, [...args, '--install-extension', PVSC_EXTENSION_ID_FOR_TESTS], { + encoding: 'utf-8', + stdio: 'inherit', + }); + } + + // Run the extension test + await runTests({ + // Use the specified `code` executable + vscodeExecutablePath, + extensionDevelopmentPath, + extensionTestsPath, + }); } catch (err) { console.error('Failed to run tests'); process.exit(1); diff --git a/src/test/unittest/adapter/factory.unit.test.ts b/src/test/unittest/adapter/factory.unit.test.ts index ada6cef1..d4f10204 100644 --- a/src/test/unittest/adapter/factory.unit.test.ts +++ b/src/test/unittest/adapter/factory.unit.test.ts @@ -33,7 +33,7 @@ suite('Debugging - Adapter Factory', () => { let showErrorMessageStub: sinon.SinonStub; let resolveEnvironmentStub: sinon.SinonStub; let getInterpretersStub: sinon.SinonStub; - let getActiveEnvironmentPathStub: sinon.SinonStub; + let getInterpreterDetailsStub: sinon.SinonStub; let hasInterpretersStub: sinon.SinonStub; const nodeExecutable = undefined; @@ -71,7 +71,7 @@ suite('Debugging - Adapter Factory', () => { showErrorMessageStub = sinon.stub(vscodeApi, 'showErrorMessage'); resolveEnvironmentStub = sinon.stub(pythonApi, 'resolveEnvironment'); getInterpretersStub = sinon.stub(pythonApi, 'getInterpreters'); - getActiveEnvironmentPathStub = sinon.stub(pythonApi, 'getActiveEnvironmentPath'); + getInterpreterDetailsStub = sinon.stub(pythonApi, 'getInterpreterDetails'); hasInterpretersStub = sinon.stub(pythonApi, 'hasInterpreters'); when( @@ -119,7 +119,7 @@ suite('Debugging - Adapter Factory', () => { test('Return the path of the active interpreter as the current python path, it exists and configuration.pythonPath is not defined', async () => { const session = createSession({}); const debugExecutable = new DebugAdapterExecutable(pythonPath, [debugAdapterPath]); - getActiveEnvironmentPathStub.resolves(interpreter.path); + getInterpreterDetailsStub.resolves({ path: [interpreter.path] }); resolveEnvironmentStub.resolves(interpreter); const descriptor = await factory.createDebugAdapterDescriptor(session, nodeExecutable); @@ -127,7 +127,7 @@ suite('Debugging - Adapter Factory', () => { }); test('Display a message if no python interpreter is set', async () => { - getActiveEnvironmentPathStub.resolves(undefined); + getInterpreterDetailsStub.resolves(undefined); const session = createSession({}); const promise = factory.createDebugAdapterDescriptor(session, nodeExecutable); @@ -149,7 +149,7 @@ suite('Debugging - Adapter Factory', () => { version: new SemVer('3.6.12-test'), }; when(state.value).thenReturn(false); - getActiveEnvironmentPathStub.resolves(deprecatedInterpreter.path); + getInterpreterDetailsStub.resolves({ path: [deprecatedInterpreter.path] }); resolveEnvironmentStub.resolves(deprecatedInterpreter); await factory.createDebugAdapterDescriptor(session, nodeExecutable); @@ -195,7 +195,7 @@ suite('Debugging - Adapter Factory', () => { test('Return Debug Adapter executable if request is "attach", and listen is specified', async () => { const session = createSession({ request: 'attach', listen: { port: 5678, host: 'localhost' } }); const debugExecutable = new DebugAdapterExecutable(pythonPath, [debugAdapterPath]); - getActiveEnvironmentPathStub.resolves(interpreter.path); + getInterpreterDetailsStub.resolves({ path: [interpreter.path] }); resolveEnvironmentStub.resolves(interpreter); const descriptor = await factory.createDebugAdapterDescriptor(session, nodeExecutable); @@ -226,7 +226,7 @@ suite('Debugging - Adapter Factory', () => { EXTENSION_ROOT_DIR, ]); - getActiveEnvironmentPathStub.resolves(interpreter.path); + getInterpreterDetailsStub.resolves({ path: [interpreter.path] }); resolveEnvironmentStub.withArgs(interpreter.path).resolves(interpreter); const descriptor = await factory.createDebugAdapterDescriptor(session, nodeExecutable); @@ -238,7 +238,7 @@ suite('Debugging - Adapter Factory', () => { const session = createSession({}); const debugExecutable = new DebugAdapterExecutable(pythonPath, [debugAdapterPath]); - getActiveEnvironmentPathStub.resolves(interpreter.path); + getInterpreterDetailsStub.resolves({ path: [interpreter.path] }); resolveEnvironmentStub.withArgs(interpreter.path).resolves(interpreter); const descriptor = await factory.createDebugAdapterDescriptor(session, nodeExecutable); @@ -250,7 +250,7 @@ suite('Debugging - Adapter Factory', () => { const session = createSession({ logToFile: false }); const debugExecutable = new DebugAdapterExecutable(pythonPath, [debugAdapterPath]); - getActiveEnvironmentPathStub.resolves(interpreter.path); + getInterpreterDetailsStub.resolves({ path: [interpreter.path] }); resolveEnvironmentStub.withArgs(interpreter.path).resolves(interpreter); const descriptor = await factory.createDebugAdapterDescriptor(session, nodeExecutable); @@ -260,7 +260,7 @@ suite('Debugging - Adapter Factory', () => { test('Send attach to local process telemetry if attaching to a local process', async () => { const session = createSession({ request: 'attach', processId: 1234 }); - getActiveEnvironmentPathStub.resolves(interpreter.path); + getInterpreterDetailsStub.resolves({ path: [interpreter.path] }); resolveEnvironmentStub.withArgs(interpreter.path).resolves(interpreter); await factory.createDebugAdapterDescriptor(session, nodeExecutable); @@ -270,7 +270,7 @@ suite('Debugging - Adapter Factory', () => { test("Don't send any telemetry if not attaching to a local process", async () => { const session = createSession({}); - getActiveEnvironmentPathStub.resolves(interpreter.path); + getInterpreterDetailsStub.resolves({ path: [interpreter.path] }); resolveEnvironmentStub.withArgs(interpreter.path).resolves(interpreter); await factory.createDebugAdapterDescriptor(session, nodeExecutable); @@ -282,7 +282,7 @@ suite('Debugging - Adapter Factory', () => { const customAdapterPath = 'custom/debug/adapter/path'; const session = createSession({ debugAdapterPath: customAdapterPath }); const debugExecutable = new DebugAdapterExecutable(pythonPath, [customAdapterPath]); - getActiveEnvironmentPathStub.resolves(interpreter.path); + getInterpreterDetailsStub.resolves({ path: [interpreter.path] }); resolveEnvironmentStub.withArgs(interpreter.path).resolves(interpreter); const descriptor = await factory.createDebugAdapterDescriptor(session, nodeExecutable); @@ -310,7 +310,7 @@ suite('Debugging - Adapter Factory', () => { test('Do not use "python" to spawn the debug adapter', async () => { const session = createSession({ python: '/bin/custompy' }); const debugExecutable = new DebugAdapterExecutable(pythonPath, [debugAdapterPath]); - getActiveEnvironmentPathStub.resolves(interpreter.path); + getInterpreterDetailsStub.resolves({ path: [interpreter.path] }); resolveEnvironmentStub.withArgs(interpreter.path).resolves(interpreter); const descriptor = await factory.createDebugAdapterDescriptor(session, nodeExecutable);