Skip to content

Commit aa49f6d

Browse files
author
Kartik Raj
authored
Intercept output of interpreterInfo.py script to filter out stdout (#18281)
* Intercept output of interpreterInfo.py script to filter out stdout * News
1 parent dd76d9d commit aa49f6d

File tree

9 files changed

+26
-26
lines changed

9 files changed

+26
-26
lines changed

news/2 Fixes/18234.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Ensures interpreters are discovered even when running `interpreterInfo.py` script prints more than just the script output.

pythonFiles/conda_run_script.py renamed to pythonFiles/get_output_via_markers.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
import runpy
55
import sys
66

7-
# Activating conda can print out stuff before the actual output is
8-
# printed. Hence, printing out markers to make it more resilient to
9-
# pull the output.
10-
print(">>>CONDA-RUN-OUTPUT", end="")
7+
# Sometimes executing scripts can print out stuff before the actual output is
8+
# printed. For eg. when activating conda. Hence, printing out markers to make
9+
# it more resilient to pull the output.
10+
print(">>>PYTHON-EXEC-OUTPUT", end="")
1111

1212
module = sys.argv[1]
1313
if module == "-c":
@@ -21,4 +21,4 @@
2121
else:
2222
runpy.run_module(module, run_name="__main__", alter_sys=True)
2323

24-
print("<<<CONDA-RUN-OUTPUT", end="")
24+
print("<<<PYTHON-EXEC-OUTPUT", end="")

src/client/common/process/internal/scripts/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ export type InterpreterInfoJson = {
4141
is64Bit: boolean;
4242
};
4343

44+
export const OUTPUT_MARKER_SCRIPT = path.join(_SCRIPTS_DIR, 'get_output_via_markers.py');
45+
4446
export function interpreterInfo(): [string[], (out: string) => InterpreterInfoJson | undefined] {
4547
const script = path.join(SCRIPTS_DIR, 'interpreterInfo.py');
4648
const args = [script];

src/client/common/process/rawProcessApis.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,16 +160,17 @@ export function plainExec(
160160
}
161161

162162
function filterOutputUsingCondaRunMarkers(stdout: string) {
163-
// These markers are added if conda run is used, see `conda_run_script.py`.
164-
const regex = />>>CONDA-RUN-OUTPUT([\s\S]*)<<<CONDA-RUN-OUTPUT/;
163+
// These markers are added if conda run is used or `interpreterInfo.py` is
164+
// run, see `get_output_via_markers.py`.
165+
const regex = />>>PYTHON-EXEC-OUTPUT([\s\S]*)<<<PYTHON-EXEC-OUTPUT/;
165166
const match = stdout.match(regex);
166167
const filteredOut = match !== null && match.length >= 2 ? match[1] : '';
167168
return filteredOut.length ? filteredOut : stdout;
168169
}
169170

170171
function removeCondaRunMarkers(out: string) {
171-
out = out.replace('>>>CONDA-RUN-OUTPUT', '');
172-
return out.replace('<<<CONDA-RUN-OUTPUT', '');
172+
out = out.replace('>>>PYTHON-EXEC-OUTPUT', '');
173+
return out.replace('<<<PYTHON-EXEC-OUTPUT', '');
173174
}
174175

175176
export function execObservable(

src/client/pythonEnvironments/base/info/environmentInfoService.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { traceError, traceInfo } from '../../../logging';
1010
import { Conda, CONDA_ACTIVATION_TIMEOUT, isCondaEnvironment } from '../../common/environmentManagers/conda';
1111
import { PythonEnvInfo, PythonEnvKind } from '.';
1212
import { normCasePath } from '../../common/externalDependencies';
13+
import { OUTPUT_MARKER_SCRIPT } from '../../../common/process/internal/scripts';
1314

1415
export enum EnvironmentInfoServiceQueuePriority {
1516
Default,
@@ -24,7 +25,7 @@ export interface IEnvironmentInfoService {
2425
}
2526

2627
async function buildEnvironmentInfo(env: PythonEnvInfo): Promise<InterpreterInformation | undefined> {
27-
const python = [env.executable.filename];
28+
const python = [env.executable.filename, OUTPUT_MARKER_SCRIPT];
2829
const interpreterInfo = await getInterpreterInfo(buildPythonExecInfo(python, undefined, env.executable.filename));
2930
return interpreterInfo;
3031
}

src/client/pythonEnvironments/common/environmentManagers/conda.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { EnvironmentType, PythonEnvironment } from '../../info';
1212
import { cache } from '../../../common/utils/decorators';
1313
import { isTestExecution } from '../../../common/constants';
1414
import { traceError, traceVerbose } from '../../../logging';
15-
import { _SCRIPTS_DIR } from '../../../common/process/internal/scripts/constants';
15+
import { OUTPUT_MARKER_SCRIPT } from '../../../common/process/internal/scripts';
1616

1717
export const AnacondaCompanyName = 'Anaconda, Inc.';
1818

@@ -205,8 +205,6 @@ export const CONDA_RUN_VERSION = '4.9.0';
205205
export const CONDA_ACTIVATION_TIMEOUT = 45000;
206206
const CONDA_GENERAL_TIMEOUT = 50000;
207207

208-
export const CONDA_RUN_SCRIPT = path.join(_SCRIPTS_DIR, 'conda_run_script.py');
209-
210208
/** Wraps the "conda" utility, and exposes its functionality.
211209
*/
212210
export class Conda {
@@ -418,7 +416,7 @@ export class Conda {
418416
} else {
419417
args.push('-p', env.prefix);
420418
}
421-
return [this.command, 'run', ...args, '--no-capture-output', 'python', CONDA_RUN_SCRIPT];
419+
return [this.command, 'run', ...args, '--no-capture-output', 'python', OUTPUT_MARKER_SCRIPT];
422420
}
423421

424422
/**

src/test/common/process/proc.exec.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ suite('ProcessService Observable', () => {
135135
this.timeout(7000);
136136
const procService = new ProcessService(new BufferDecoder());
137137
const pythonCode = [
138-
'print(">>>CONDA-RUN-OUTPUT")',
138+
'print(">>>PYTHON-EXEC-OUTPUT")',
139139
'import sys',
140140
'import time',
141141
'print("1")',
@@ -155,7 +155,7 @@ suite('ProcessService Observable', () => {
155155
'time.sleep(1)',
156156
'sys.stderr.write("c")',
157157
'sys.stderr.flush()',
158-
'print("<<<CONDA-RUN-OUTPUT")',
158+
'print("<<<PYTHON-EXEC-OUTPUT")',
159159
];
160160
const result = await procService.exec(pythonPath, ['-c', pythonCode.join(';')]);
161161
const expectedStdout = ['1', '2', '3'];
@@ -235,7 +235,7 @@ suite('ProcessService Observable', () => {
235235
const procService = new ProcessService(new BufferDecoder());
236236
const printOutput = '1234';
237237
const result = await procService.shellExec(
238-
`"${pythonPath}" -c "print('>>>CONDA-RUN-OUTPUT');print('${printOutput}');print('<<<CONDA-RUN-OUTPUT')"`,
238+
`"${pythonPath}" -c "print('>>>PYTHON-EXEC-OUTPUT');print('${printOutput}');print('<<<PYTHON-EXEC-OUTPUT')"`,
239239
);
240240

241241
expect(result).not.to.be.an('undefined', 'result is undefined');

src/test/common/process/proc.observable.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ suite('ProcessService', () => {
199199
this.timeout(20000);
200200
const procService = new ProcessService(new BufferDecoder());
201201
const pythonCode = [
202-
'print(">>>CONDA-RUN-OUTPUT")',
202+
'print(">>>PYTHON-EXEC-OUTPUT")',
203203
'import sys',
204204
'import time',
205205
'print("1")',
@@ -220,7 +220,7 @@ suite('ProcessService', () => {
220220
'sys.stderr.write("c")',
221221
'sys.stderr.flush()',
222222
'time.sleep(2)',
223-
'print("<<<CONDA-RUN-OUTPUT")',
223+
'print("<<<PYTHON-EXEC-OUTPUT")',
224224
];
225225
const result = procService.execObservable(pythonPath, ['-c', pythonCode.join(';')]);
226226
const outputs = [

src/test/pythonEnvironments/common/environmentManagers/conda.unit.test.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,11 @@ import { PythonEnvKind } from '../../../../client/pythonEnvironments/base/info';
1010
import { getEnvs } from '../../../../client/pythonEnvironments/base/locatorUtils';
1111
import * as externalDependencies from '../../../../client/pythonEnvironments/common/externalDependencies';
1212
import * as windowsUtils from '../../../../client/pythonEnvironments/common/windowsUtils';
13-
import {
14-
Conda,
15-
CondaInfo,
16-
CONDA_RUN_SCRIPT,
17-
} from '../../../../client/pythonEnvironments/common/environmentManagers/conda';
13+
import { Conda, CondaInfo } from '../../../../client/pythonEnvironments/common/environmentManagers/conda';
1814
import { CondaEnvironmentLocator } from '../../../../client/pythonEnvironments/base/locators/lowLevel/condaLocator';
1915
import { createBasicEnv } from '../../base/common';
2016
import { assertBasicEnvsEqual } from '../../base/locators/envTestUtils';
17+
import { OUTPUT_MARKER_SCRIPT } from '../../../../client/common/process/internal/scripts';
2118

2219
suite('Conda and its environments are located correctly', () => {
2320
// getOSType() is stubbed to return this.
@@ -484,14 +481,14 @@ suite('Conda and its environments are located correctly', () => {
484481
expect(args).to.not.equal(undefined);
485482
assert.deepStrictEqual(
486483
args,
487-
['conda', 'run', '-n', 'envName', '--no-capture-output', 'python', CONDA_RUN_SCRIPT],
484+
['conda', 'run', '-n', 'envName', '--no-capture-output', 'python', OUTPUT_MARKER_SCRIPT],
488485
'Incorrect args for case 1',
489486
);
490487

491488
args = await conda?.getRunPythonArgs({ name: '', prefix: 'envPrefix' });
492489
assert.deepStrictEqual(
493490
args,
494-
['conda', 'run', '-p', 'envPrefix', '--no-capture-output', 'python', CONDA_RUN_SCRIPT],
491+
['conda', 'run', '-p', 'envPrefix', '--no-capture-output', 'python', OUTPUT_MARKER_SCRIPT],
495492
'Incorrect args for case 2',
496493
);
497494
});

0 commit comments

Comments
 (0)