Skip to content

Commit 347094f

Browse files
author
Kartik Raj
authored
Cherry fixes for point release (#19996)
1 parent 456ca37 commit 347094f

File tree

4 files changed

+50
-29
lines changed

4 files changed

+50
-29
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "python",
33
"displayName": "Python",
44
"description": "IntelliSense (Pylance), Linting, Debugging (multi-threaded, remote), Jupyter Notebooks, code formatting, refactoring, unit tests, and more.",
5-
"version": "2022.16.0",
5+
"version": "2022.16.1",
66
"featureFlags": {
77
"usingNewInterpreterStorage": true
88
},

src/client/interpreter/activation/service.ts

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { sleep } from '../../common/utils/async';
1616
import { InMemoryCache } from '../../common/utils/cacheUtils';
1717
import { OSType } from '../../common/utils/platform';
1818
import { IEnvironmentVariablesProvider } from '../../common/variables/types';
19-
import { PythonEnvironment } from '../../pythonEnvironments/info';
19+
import { EnvironmentType, PythonEnvironment } from '../../pythonEnvironments/info';
2020
import { captureTelemetry, sendTelemetryEvent } from '../../telemetry';
2121
import { EventName } from '../../telemetry/constants';
2222
import { IInterpreterService } from '../contracts';
@@ -30,6 +30,7 @@ import {
3030
traceVerbose,
3131
traceWarn,
3232
} from '../../logging';
33+
import { Conda } from '../../pythonEnvironments/common/environmentManagers/conda';
3334

3435
const ENVIRONMENT_PREFIX = 'e8b39361-0157-4923-80e1-22d70d46dee6';
3536
const CACHE_DURATION = 10 * 60 * 1000;
@@ -169,20 +170,41 @@ export class EnvironmentActivationService implements IEnvironmentActivationServi
169170
if (!shellInfo) {
170171
return;
171172
}
172-
let isPossiblyCondaEnv = false;
173173
try {
174-
const activationCommands = await this.helper.getEnvironmentActivationShellCommands(
175-
resource,
176-
shellInfo.shellType,
177-
interpreter,
178-
);
179-
traceVerbose(`Activation Commands received ${activationCommands} for shell ${shellInfo.shell}`);
180-
if (!activationCommands || !Array.isArray(activationCommands) || activationCommands.length === 0) {
181-
return;
174+
let command: string | undefined;
175+
let [args, parse] = internalScripts.printEnvVariables();
176+
args.forEach((arg, i) => {
177+
args[i] = arg.toCommandArgumentForPythonExt();
178+
});
179+
interpreter = interpreter ?? (await this.interpreterService.getActiveInterpreter(resource));
180+
if (interpreter?.envType === EnvironmentType.Conda) {
181+
const conda = await Conda.getConda();
182+
const pythonArgv = await conda?.getRunPythonArgs({
183+
name: interpreter.envName,
184+
prefix: interpreter.envPath ?? '',
185+
});
186+
if (pythonArgv) {
187+
// Using environment prefix isn't needed as the marker script already takes care of it.
188+
command = [...pythonArgv, ...args].map((arg) => arg.toCommandArgumentForPythonExt()).join(' ');
189+
}
190+
}
191+
if (!command) {
192+
const activationCommands = await this.helper.getEnvironmentActivationShellCommands(
193+
resource,
194+
shellInfo.shellType,
195+
interpreter,
196+
);
197+
traceVerbose(`Activation Commands received ${activationCommands} for shell ${shellInfo.shell}`);
198+
if (!activationCommands || !Array.isArray(activationCommands) || activationCommands.length === 0) {
199+
return;
200+
}
201+
// Run the activate command collect the environment from it.
202+
const activationCommand = this.fixActivationCommands(activationCommands).join(' && ');
203+
// In order to make sure we know where the environment output is,
204+
// put in a dummy echo we can look for
205+
command = `${activationCommand} && echo '${ENVIRONMENT_PREFIX}' && python ${args.join(' ')}`;
182206
}
183-
isPossiblyCondaEnv = activationCommands.join(' ').toLowerCase().includes('conda');
184-
// Run the activate command collect the environment from it.
185-
const activationCommand = this.fixActivationCommands(activationCommands).join(' && ');
207+
186208
const processService = await this.processServiceFactory.create(resource);
187209
const customEnvVars = await this.envVarsService.getEnvironmentVariables(resource);
188210
const hasCustomEnvVars = Object.keys(customEnvVars).length;
@@ -194,14 +216,6 @@ export class EnvironmentActivationService implements IEnvironmentActivationServi
194216
env[PYTHON_WARNINGS] = 'ignore';
195217

196218
traceVerbose(`${hasCustomEnvVars ? 'Has' : 'No'} Custom Env Vars`);
197-
198-
// In order to make sure we know where the environment output is,
199-
// put in a dummy echo we can look for
200-
const [args, parse] = internalScripts.printEnvVariables();
201-
args.forEach((arg, i) => {
202-
args[i] = arg.toCommandArgumentForPythonExt();
203-
});
204-
const command = `${activationCommand} && echo '${ENVIRONMENT_PREFIX}' && python ${args.join(' ')}`;
205219
traceVerbose(`Activating Environment to capture Environment variables, ${command}`);
206220

207221
// Do some wrapping of the call. For two reasons:
@@ -219,7 +233,10 @@ export class EnvironmentActivationService implements IEnvironmentActivationServi
219233
result = await processService.shellExec(command, {
220234
env,
221235
shell: shellInfo.shell,
222-
timeout: isPossiblyCondaEnv ? CONDA_ENVIRONMENT_TIMEOUT : ENVIRONMENT_TIMEOUT,
236+
timeout:
237+
interpreter?.envType === EnvironmentType.Conda
238+
? CONDA_ENVIRONMENT_TIMEOUT
239+
: ENVIRONMENT_TIMEOUT,
223240
maxBuffer: 1000 * 1000,
224241
throwOnStdErr: false,
225242
});
@@ -265,7 +282,7 @@ export class EnvironmentActivationService implements IEnvironmentActivationServi
265282
} catch (e) {
266283
traceError('getActivatedEnvironmentVariables', e);
267284
sendTelemetryEvent(EventName.ACTIVATE_ENV_TO_GET_ENV_VARS_FAILED, undefined, {
268-
isPossiblyCondaEnv,
285+
isPossiblyCondaEnv: interpreter?.envType === EnvironmentType.Conda,
269286
terminal: shellInfo.shellType,
270287
});
271288

@@ -283,6 +300,9 @@ export class EnvironmentActivationService implements IEnvironmentActivationServi
283300
@traceDecoratorError('Failed to parse Environment variables')
284301
@traceDecoratorVerbose('parseEnvironmentOutput', TraceOptions.None)
285302
protected parseEnvironmentOutput(output: string, parse: (out: string) => NodeJS.ProcessEnv | undefined) {
303+
if (output.indexOf(ENVIRONMENT_PREFIX) === -1) {
304+
return parse(output);
305+
}
286306
output = output.substring(output.indexOf(ENVIRONMENT_PREFIX) + ENVIRONMENT_PREFIX.length);
287307
const js = output.substring(output.indexOf('{')).trim();
288308
return parse(js);

src/test/interpreters/activation/service.unit.test.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ suite('Interpreters Activation - Python Environment Variables', () => {
5858
architecture: Architecture.x64,
5959
};
6060

61-
function initSetup() {
61+
function initSetup(interpreter: PythonEnvironment | undefined) {
6262
helper = mock(TerminalHelper);
6363
platform = mock(PlatformService);
6464
processServiceFactory = mock(ProcessServiceFactory);
@@ -71,6 +71,7 @@ suite('Interpreters Activation - Python Environment Variables', () => {
7171
onDidChangeInterpreter = new EventEmitter<void>();
7272
when(envVarsService.onDidEnvironmentVariablesChange).thenReturn(onDidChangeEnvVariables.event);
7373
when(interpreterService.onDidChangeInterpreter).thenReturn(onDidChangeInterpreter.event);
74+
when(interpreterService.getActiveInterpreter(anything())).thenResolve(interpreter);
7475
service = new EnvironmentActivationService(
7576
instance(helper),
7677
instance(platform),
@@ -89,7 +90,7 @@ suite('Interpreters Activation - Python Environment Variables', () => {
8990
[undefined, Uri.parse('a')].forEach((resource) =>
9091
[undefined, pythonInterpreter].forEach((interpreter) => {
9192
suite(title(resource, interpreter), () => {
92-
setup(initSetup);
93+
setup(() => initSetup(interpreter));
9394
test('Unknown os will return empty variables', async () => {
9495
when(platform.osType).thenReturn(OSType.Unknown);
9596
const env = await service.getActivatedEnvironmentVariables(resource);
@@ -102,7 +103,7 @@ suite('Interpreters Activation - Python Environment Variables', () => {
102103

103104
osTypes.forEach((osType) => {
104105
suite(osType.name, () => {
105-
setup(initSetup);
106+
setup(() => initSetup(interpreter));
106107
test('getEnvironmentActivationShellCommands will be invoked', async () => {
107108
when(platform.osType).thenReturn(osType.value);
108109
when(

0 commit comments

Comments
 (0)