|
7 | 7 | import { expect } from 'chai'; |
8 | 8 | import * as path from 'path'; |
9 | 9 | import * as sinon from 'sinon'; |
10 | | -import { anything, instance, mock, when } from 'ts-mockito'; |
| 10 | +import { anything, capture, instance, mock, verify, when } from 'ts-mockito'; |
11 | 11 | import { DebugConfiguration, Uri, WorkspaceFolder } from 'vscode'; |
12 | 12 | import { CancellationToken } from 'vscode-jsonrpc'; |
13 | 13 | import { ConfigurationService } from '../../../../../client/common/configuration/service'; |
@@ -289,6 +289,91 @@ suite('Debugging - Config Resolver', () => { |
289 | 289 | expect(config).to.have.property('debugLauncherPython', pythonPath); |
290 | 290 | }); |
291 | 291 |
|
| 292 | + test('uses one exact program lookup for command-valued pythonPath and python', async () => { |
| 293 | + const workspaceUri = Uri.file(path.resolve('workspace')); |
| 294 | + const programPath = path.join(workspaceUri.fsPath, 'script.py'); |
| 295 | + const workspacePython = path.resolve('workspace-env', 'python'); |
| 296 | + const programPython = path.resolve('program-env', 'python'); |
| 297 | + const config = { |
| 298 | + program: path.join('${workspaceFolder}', 'script.py'), |
| 299 | + pythonPath: '${command:python.interpreterPath}', |
| 300 | + python: '${command:python.interpreterPath}', |
| 301 | + }; |
| 302 | + when(interpreterService.getActiveInterpreter(anything(), anything())).thenCall(async (resource) => |
| 303 | + resource?.fsPath === Uri.file(programPath).fsPath |
| 304 | + ? ({ path: programPython } as PythonEnvironment) |
| 305 | + : ({ path: workspacePython } as PythonEnvironment), |
| 306 | + ); |
| 307 | + |
| 308 | + await resolver.resolveAndUpdatePythonPath(workspaceUri, config as LaunchRequestArguments); |
| 309 | + |
| 310 | + expect(config).to.not.have.property('pythonPath'); |
| 311 | + expect(config).to.have.property('python', programPython); |
| 312 | + expect(config).to.have.property('__pythonIsProgramInterpreter', true); |
| 313 | + verify(interpreterService.getActiveInterpreter(anything(), anything())).twice(); |
| 314 | + verify(interpreterService.getActiveInterpreter(anything())).never(); |
| 315 | + const [resource, options] = capture(interpreterService.getActiveInterpreter).first(); |
| 316 | + expect(resource?.fsPath).to.equal(Uri.file(programPath).fsPath); |
| 317 | + expect(options).to.deep.equal({ exactResource: true }); |
| 318 | + }); |
| 319 | + |
| 320 | + test('falls back to the workspace interpreter when exact program lookup has no environment', async () => { |
| 321 | + const workspaceUri = Uri.file(path.resolve('workspace')); |
| 322 | + const programPath = path.join(workspaceUri.fsPath, 'script.py'); |
| 323 | + const workspacePython = path.resolve('workspace-env', 'python'); |
| 324 | + const config = { program: programPath }; |
| 325 | + when(interpreterService.getActiveInterpreter(anything(), anything())).thenResolve(undefined); |
| 326 | + when(interpreterService.getActiveInterpreter(anything())).thenResolve({ |
| 327 | + path: workspacePython, |
| 328 | + } as PythonEnvironment); |
| 329 | + |
| 330 | + await resolver.resolveAndUpdatePythonPath(workspaceUri, config as LaunchRequestArguments); |
| 331 | + |
| 332 | + expect(config).to.have.property('python', workspacePython); |
| 333 | + expect(config).to.not.have.property('__pythonIsProgramInterpreter'); |
| 334 | + verify(interpreterService.getActiveInterpreter(anything(), anything())).once(); |
| 335 | + verify(interpreterService.getActiveInterpreter(anything())).once(); |
| 336 | + }); |
| 337 | + |
| 338 | + test('resolves a named workspace-folder program before exact interpreter lookup', async () => { |
| 339 | + const launchWorkspaceUri = Uri.file(path.resolve('workspace-a')); |
| 340 | + const programWorkspaceUri = Uri.file(path.resolve('workspace-b')); |
| 341 | + const programPath = path.join(programWorkspaceUri.fsPath, 'script.py'); |
| 342 | + const workspacePython = path.resolve('workspace-env', 'python'); |
| 343 | + const programPython = path.resolve('program-env', 'python'); |
| 344 | + const config = { program: path.join('${workspaceFolder:program-root}', 'script.py') }; |
| 345 | + getWorkspaceFoldersStub.returns([ |
| 346 | + { uri: launchWorkspaceUri, name: 'launch-root', index: 0 }, |
| 347 | + { uri: programWorkspaceUri, name: 'program-root', index: 1 }, |
| 348 | + ]); |
| 349 | + when(interpreterService.getActiveInterpreter(anything(), anything())).thenCall(async (resource) => |
| 350 | + resource?.fsPath === Uri.file(programPath).fsPath |
| 351 | + ? ({ path: programPython } as PythonEnvironment) |
| 352 | + : ({ path: workspacePython } as PythonEnvironment), |
| 353 | + ); |
| 354 | + |
| 355 | + await resolver.resolveAndUpdatePythonPath(launchWorkspaceUri, config as LaunchRequestArguments); |
| 356 | + |
| 357 | + expect(config).to.have.property('python', programPython); |
| 358 | + const [resource] = capture(interpreterService.getActiveInterpreter).first(); |
| 359 | + expect(resource?.fsPath).to.equal(Uri.file(programPath).fsPath); |
| 360 | + }); |
| 361 | + |
| 362 | + test('does not mark a program interpreter that matches the workspace interpreter', async () => { |
| 363 | + const workspaceUri = Uri.file(path.resolve('workspace')); |
| 364 | + const programPath = path.join(workspaceUri.fsPath, 'script.py'); |
| 365 | + const pythonPath = path.resolve('env', 'python'); |
| 366 | + const config = { program: programPath }; |
| 367 | + when(interpreterService.getActiveInterpreter(anything(), anything())).thenResolve({ |
| 368 | + path: pythonPath, |
| 369 | + } as PythonEnvironment); |
| 370 | + |
| 371 | + await resolver.resolveAndUpdatePythonPath(workspaceUri, config as LaunchRequestArguments); |
| 372 | + |
| 373 | + expect(config).to.have.property('python', pythonPath); |
| 374 | + expect(config).to.not.have.property('__pythonIsProgramInterpreter'); |
| 375 | + }); |
| 376 | + |
292 | 377 | const localHostTestMatrix: Record<string, boolean> = { |
293 | 378 | localhost: true, |
294 | 379 | '127.0.0.1': true, |
|
0 commit comments