Skip to content

Commit 112738b

Browse files
committed
refactor resolveAndUpdatePythonPath
1 parent beae7cb commit 112738b

File tree

1 file changed

+95
-31
lines changed
  • src/extension/debugger/configuration/resolvers

1 file changed

+95
-31
lines changed

src/extension/debugger/configuration/resolvers/base.ts

Lines changed: 95 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,16 @@ export abstract class BaseConfigurationResolver<T extends DebugConfiguration>
8080
return undefined;
8181
}
8282

83+
/**
84+
* Resolves and updates file paths and Python interpreter paths in the debug configuration.
85+
*
86+
* This method performs two main operations:
87+
* 1. Resolves workspace variables in the envFile path (if specified)
88+
* 2. Resolves and updates Python interpreter paths, handling legacy pythonPath deprecation
89+
*
90+
* @param workspaceFolder The workspace folder URI for variable resolution
91+
* @param debugConfiguration The launch configuration to update
92+
*/
8393
protected async resolveAndUpdatePaths(
8494
workspaceFolder: Uri | undefined,
8595
debugConfiguration: LaunchRequestArguments,
@@ -88,76 +98,130 @@ export abstract class BaseConfigurationResolver<T extends DebugConfiguration>
8898
await this.resolveAndUpdatePythonPath(workspaceFolder, debugConfiguration);
8999
}
90100

101+
/**
102+
* Resolves workspace variables in the envFile path.
103+
*
104+
* Expands variables like ${workspaceFolder} in the envFile configuration using the
105+
* workspace folder path or current working directory as the base for resolution.
106+
*
107+
* @param workspaceFolder The workspace folder URI for variable resolution
108+
* @param debugConfiguration The launch configuration containing the envFile path
109+
*/
91110
protected static resolveAndUpdateEnvFilePath(
92111
workspaceFolder: Uri | undefined,
93112
debugConfiguration: LaunchRequestArguments,
94113
): void {
95-
if (!debugConfiguration) {
114+
// Early exit if no configuration or no envFile to resolve
115+
if (!debugConfiguration?.envFile) {
96116
return;
97117
}
98-
if (debugConfiguration.envFile && (workspaceFolder || debugConfiguration.cwd)) {
99-
debugConfiguration.envFile = resolveWorkspaceVariables(
100-
debugConfiguration.envFile,
101-
(workspaceFolder ? workspaceFolder.fsPath : undefined) || debugConfiguration.cwd,
102-
undefined,
103-
);
118+
119+
const basePath = workspaceFolder?.fsPath || debugConfiguration.cwd;
120+
121+
if (basePath) {
122+
// update envFile with resolved variables
123+
debugConfiguration.envFile = resolveWorkspaceVariables(debugConfiguration.envFile, basePath, undefined);
104124
}
105125
}
106126

127+
/**
128+
* Resolves Python interpreter paths and handles the legacy pythonPath deprecation.
129+
*
130+
* @param workspaceFolder The workspace folder URI for variable resolution and interpreter detection
131+
* @param debugConfiguration The launch configuration to update with resolved Python paths
132+
*/
107133
protected async resolveAndUpdatePythonPath(
108134
workspaceFolder: Uri | undefined,
109135
debugConfiguration: LaunchRequestArguments,
110136
): Promise<void> {
111137
if (!debugConfiguration) {
112138
return;
113139
}
140+
141+
// get the interpreter details in the context of the workspace folder
142+
const interpreterDetail = await getInterpreterDetails(workspaceFolder);
143+
const interpreterPath = interpreterDetail?.path ?? (await getSettingsPythonPath(workspaceFolder));
144+
const resolvedInterpreterPath = interpreterPath ? interpreterPath[0] : interpreterPath;
145+
146+
traceLog(
147+
`resolveAndUpdatePythonPath - Initial state: ` +
148+
`pythonPath='${debugConfiguration.pythonPath}', ` +
149+
`python='${debugConfiguration.python}', ` +
150+
`debugAdapterPython='${debugConfiguration.debugAdapterPython}', ` +
151+
`debugLauncherPython='${debugConfiguration.debugLauncherPython}', ` +
152+
`workspaceFolder='${workspaceFolder?.fsPath}'` +
153+
`resolvedInterpreterPath='${resolvedInterpreterPath}'`,
154+
);
155+
156+
// STEP 1: Resolve legacy pythonPath property (DEPRECATED)
157+
// pythonPath will equal user set value, or getInterpreterDetails if undefined or set to command
114158
if (debugConfiguration.pythonPath === '${command:python.interpreterPath}' || !debugConfiguration.pythonPath) {
115-
const interpreterDetail = await getInterpreterDetails(workspaceFolder);
116-
const interpreterPath = interpreterDetail
117-
? interpreterDetail.path
118-
: await getSettingsPythonPath(workspaceFolder);
119-
debugConfiguration.pythonPath = interpreterPath ? interpreterPath[0] : interpreterPath;
159+
this.pythonPathSource = PythonPathSource.settingsJson;
160+
debugConfiguration.pythonPath = resolvedInterpreterPath;
120161
} else {
162+
// User provided explicit pythonPath in launch.json
121163
debugConfiguration.pythonPath = resolveWorkspaceVariables(
122-
debugConfiguration.pythonPath ? debugConfiguration.pythonPath : undefined,
164+
debugConfiguration.pythonPath,
123165
workspaceFolder?.fsPath,
124166
undefined,
125167
);
126168
}
127169

170+
// STEP 2: Resolve current python property (CURRENT STANDARD)
128171
if (debugConfiguration.python === '${command:python.interpreterPath}') {
172+
// if python is set to the command, resolve it
129173
this.pythonPathSource = PythonPathSource.settingsJson;
130-
const interpreterDetail = await getInterpreterDetails(workspaceFolder);
131-
const interpreterPath = interpreterDetail.path
132-
? interpreterDetail.path
133-
: await getSettingsPythonPath(workspaceFolder);
134-
debugConfiguration.python = interpreterPath ? interpreterPath[0] : interpreterPath;
135-
} else if (debugConfiguration.python === undefined) {
136-
this.pythonPathSource = PythonPathSource.settingsJson;
174+
debugConfiguration.python = resolvedInterpreterPath;
175+
} else if (!debugConfiguration.python) {
176+
// fallback to pythonPath if python undefined
137177
debugConfiguration.python = debugConfiguration.pythonPath;
138178
} else {
179+
// User provided explicit python path in launch.json
139180
this.pythonPathSource = PythonPathSource.launchJson;
140181
debugConfiguration.python = resolveWorkspaceVariables(
141-
debugConfiguration.python ?? debugConfiguration.pythonPath,
182+
debugConfiguration.python,
142183
workspaceFolder?.fsPath,
143184
undefined,
144185
);
145186
}
146187

147-
if (
188+
// STEP 3: Set debug adapter and launcher Python paths (backwards compatible)
189+
this.setDebugComponentPythonPaths(debugConfiguration);
190+
191+
// STEP 4: Clean up - remove the deprecated pythonPath property
192+
delete debugConfiguration.pythonPath;
193+
}
194+
195+
/**
196+
* Sets debugAdapterPython and debugLauncherPython with backwards compatibility.
197+
* Prefers pythonPath over python for these internal properties.
198+
*
199+
* @param debugConfiguration The debug configuration to update
200+
*/
201+
private setDebugComponentPythonPaths(debugConfiguration: LaunchRequestArguments): void {
202+
const shouldSetDebugAdapter =
148203
debugConfiguration.debugAdapterPython === '${command:python.interpreterPath}' ||
149-
debugConfiguration.debugAdapterPython === undefined
150-
) {
151-
debugConfiguration.debugAdapterPython = debugConfiguration.pythonPath ?? debugConfiguration.python;
152-
}
153-
if (
204+
debugConfiguration.debugAdapterPython === undefined;
205+
206+
const shouldSetDebugLauncher =
154207
debugConfiguration.debugLauncherPython === '${command:python.interpreterPath}' ||
155-
debugConfiguration.debugLauncherPython === undefined
156-
) {
157-
debugConfiguration.debugLauncherPython = debugConfiguration.pythonPath ?? debugConfiguration.python;
208+
debugConfiguration.debugLauncherPython === undefined;
209+
210+
// Default fallback path (prefer pythonPath for backwards compatibility)
211+
const fallbackPath = debugConfiguration.pythonPath ?? debugConfiguration.python;
212+
213+
if (debugConfiguration.pythonPath !== debugConfiguration.python) {
214+
sendTelemetryEvent(EventName.DEPRECATED_CODE_PATH_USAGE, undefined, {
215+
codePath: 'different_python_paths_in_debug_config',
216+
});
158217
}
159218

160-
delete debugConfiguration.pythonPath;
219+
if (shouldSetDebugAdapter) {
220+
debugConfiguration.debugAdapterPython = fallbackPath;
221+
}
222+
if (shouldSetDebugLauncher) {
223+
debugConfiguration.debugLauncherPython = fallbackPath;
224+
}
161225
}
162226

163227
protected static debugOption(debugOptions: DebugOptions[], debugOption: DebugOptions): void {

0 commit comments

Comments
 (0)