Skip to content

Commit 84bbff9

Browse files
authored
add cwd for debugging (#21668)
fixes #21648 (comment)
1 parent ef16727 commit 84bbff9

File tree

4 files changed

+107
-2
lines changed

4 files changed

+107
-2
lines changed

src/client/testing/common/debugLauncher.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { getWorkspaceFolder, getWorkspaceFolders } from '../../common/vscodeApis
1717
import { showErrorMessage } from '../../common/vscodeApis/windowApis';
1818
import { createDeferred } from '../../common/utils/async';
1919
import { pythonTestAdapterRewriteEnabled } from '../testController/common/utils';
20+
import { addPathToPythonpath } from './helpers';
2021

2122
@injectable()
2223
export class DebugLauncher implements ITestDebugLauncher {
@@ -223,8 +224,19 @@ export class DebugLauncher implements ITestDebugLauncher {
223224
`Missing value for debug setup, both port and uuid need to be defined. port: "${options.pytestPort}" uuid: "${options.pytestUUID}"`,
224225
);
225226
}
226-
const pluginPath = path.join(EXTENSION_ROOT_DIR, 'pythonFiles');
227-
launchArgs.env.PYTHONPATH = pluginPath;
227+
}
228+
const pluginPath = path.join(EXTENSION_ROOT_DIR, 'pythonFiles');
229+
// check if PYTHONPATH is already set in the environment variables
230+
if (launchArgs.env) {
231+
const additionalPythonPath = [pluginPath];
232+
if (launchArgs.cwd) {
233+
additionalPythonPath.push(launchArgs.cwd);
234+
} else if (options.cwd) {
235+
additionalPythonPath.push(options.cwd);
236+
}
237+
// add the plugin path or cwd to PYTHONPATH if it is not already there using the following function
238+
// this function will handle if PYTHONPATH is undefined
239+
addPathToPythonpath(additionalPythonPath, launchArgs.env.PYTHONPATH);
228240
}
229241

230242
// Clear out purpose so we can detect if the configuration was used to

src/client/testing/common/helpers.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import * as path from 'path';
2+
3+
/**
4+
* This function normalizes the provided paths and the existing paths in PYTHONPATH,
5+
* adds the provided paths to PYTHONPATH if they're not already present,
6+
* and then returns the updated PYTHONPATH.
7+
*
8+
* @param newPaths - An array of paths to be added to PYTHONPATH
9+
* @param launchPythonPath - The initial PYTHONPATH
10+
* @returns The updated PYTHONPATH
11+
*/
12+
export function addPathToPythonpath(newPaths: string[], launchPythonPath: string | undefined): string {
13+
// Split PYTHONPATH into array of paths if it exists
14+
let paths: string[];
15+
if (!launchPythonPath) {
16+
paths = [];
17+
} else {
18+
paths = launchPythonPath.split(path.delimiter);
19+
}
20+
21+
// Normalize each path in the existing PYTHONPATH
22+
paths = paths.map((p) => path.normalize(p));
23+
24+
// Normalize each new path and add it to PYTHONPATH if it's not already present
25+
newPaths.forEach((newPath) => {
26+
const normalizedNewPath: string = path.normalize(newPath);
27+
28+
if (!paths.includes(normalizedNewPath)) {
29+
paths.push(normalizedNewPath);
30+
}
31+
});
32+
33+
// Join the paths with ':' to create the updated PYTHONPATH
34+
const updatedPythonPath: string = paths.join(path.delimiter);
35+
36+
return updatedPythonPath;
37+
}

src/test/testing/common/debugLauncher.unit.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,9 @@ suite('Unit Tests - Debug Launcher', () => {
215215
if (!expected.cwd) {
216216
expected.cwd = workspaceFolders[0].uri.fsPath;
217217
}
218+
const pluginPath = path.join(EXTENSION_ROOT_DIR, 'pythonFiles');
219+
const pythonPath = `${pluginPath}${path.delimiter}${expected.cwd}`;
220+
expected.env.PYTHONPATH = pythonPath;
218221

219222
// added by LaunchConfigurationResolver:
220223
if (!expected.python) {
@@ -342,6 +345,10 @@ suite('Unit Tests - Debug Launcher', () => {
342345
};
343346
const expected = getDefaultDebugConfig();
344347
expected.cwd = 'path/to/settings/cwd';
348+
const pluginPath = path.join(EXTENSION_ROOT_DIR, 'pythonFiles');
349+
const pythonPath = `${pluginPath}${path.delimiter}${expected.cwd}`;
350+
expected.env.PYTHONPATH = pythonPath;
351+
345352
setupSuccess(options, 'unittest', expected);
346353
await debugLauncher.launchDebugger(options);
347354

@@ -366,6 +373,7 @@ suite('Unit Tests - Debug Launcher', () => {
366373
console: 'integratedTerminal',
367374
cwd: 'some/dir',
368375
env: {
376+
PYTHONPATH: 'one/two/three',
369377
SPAM: 'EGGS',
370378
},
371379
envFile: 'some/dir/.env',
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import * as path from 'path';
2+
import * as assert from 'assert';
3+
import { addPathToPythonpath } from '../../../client/testing/common/helpers';
4+
5+
suite('Unit Tests - Test Helpers', () => {
6+
const newPaths = [path.join('path', 'to', 'new')];
7+
test('addPathToPythonpath handles undefined path', async () => {
8+
const launchPythonPath = undefined;
9+
const actualPath = addPathToPythonpath(newPaths, launchPythonPath);
10+
assert.equal(actualPath, path.join('path', 'to', 'new'));
11+
});
12+
test('addPathToPythonpath adds path if it does not exist in the python path', async () => {
13+
const launchPythonPath = path.join('random', 'existing', 'pythonpath');
14+
const actualPath = addPathToPythonpath(newPaths, launchPythonPath);
15+
const expectedPath =
16+
path.join('random', 'existing', 'pythonpath') + path.delimiter + path.join('path', 'to', 'new');
17+
assert.equal(actualPath, expectedPath);
18+
});
19+
test('addPathToPythonpath does not add to python path if the given python path already contains the path', async () => {
20+
const launchPythonPath = path.join('path', 'to', 'new');
21+
const actualPath = addPathToPythonpath(newPaths, launchPythonPath);
22+
const expectedPath = path.join('path', 'to', 'new');
23+
assert.equal(actualPath, expectedPath);
24+
});
25+
test('addPathToPythonpath correctly normalizes both existing and new paths', async () => {
26+
const newerPaths = [path.join('path', 'to', '/', 'new')];
27+
const launchPythonPath = path.join('path', 'to', '..', 'old');
28+
const actualPath = addPathToPythonpath(newerPaths, launchPythonPath);
29+
const expectedPath = path.join('path', 'old') + path.delimiter + path.join('path', 'to', 'new');
30+
assert.equal(actualPath, expectedPath);
31+
});
32+
test('addPathToPythonpath splits pythonpath then rejoins it', async () => {
33+
const launchPythonPath =
34+
path.join('path', 'to', 'new') +
35+
path.delimiter +
36+
path.join('path', 'to', 'old') +
37+
path.delimiter +
38+
path.join('path', 'to', 'random');
39+
const actualPath = addPathToPythonpath(newPaths, launchPythonPath);
40+
const expectedPath =
41+
path.join('path', 'to', 'new') +
42+
path.delimiter +
43+
path.join('path', 'to', 'old') +
44+
path.delimiter +
45+
path.join('path', 'to', 'random');
46+
assert.equal(actualPath, expectedPath);
47+
});
48+
});

0 commit comments

Comments
 (0)