Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit faf37e2

Browse files
authored
Fix) Prevent keyboard interrupt for Python3.13 REPL non-Windows (#24555)
Further resolves: #24422 Prevent keyboard interrupt for Mac and Linux when using Python3.13 Having Python3.13 as interpreter choice and then enabling shell integration where it is normally supported (we disabled temporarily for Python3.13 due to python/cpython#126131), lead to edge case. So although we don't override user's PS1 in Python side after checking Python3.13 is selected, we were not aware of this in typescript side, leading to wrongly using executeCommand inside Python terminal REPL (Python3.13 IDLE), instead of sendText.
1 parent b8cc93d commit faf37e2

File tree

2 files changed

+22
-3
lines changed

2 files changed

+22
-3
lines changed

src/client/common/terminal/service.ts

+12-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
import { traceVerbose } from '../../logging';
2323
import { getConfiguration } from '../vscodeApis/workspaceApis';
2424
import { isWindows } from '../utils/platform';
25+
import { getActiveInterpreter } from '../../repl/replUtils';
2526

2627
@injectable()
2728
export class TerminalService implements ITerminalService, Disposable {
@@ -102,10 +103,19 @@ export class TerminalService implements ITerminalService, Disposable {
102103
});
103104
await promise;
104105
}
105-
106106
const config = getConfiguration('python');
107107
const pythonrcSetting = config.get<boolean>('terminal.shellIntegration.enabled');
108-
if ((isPythonShell && !pythonrcSetting) || (isPythonShell && isWindows())) {
108+
109+
let isPython313 = false;
110+
if (this.options && this.options.resource) {
111+
const pythonVersion = await getActiveInterpreter(
112+
this.options.resource,
113+
this.serviceContainer.get<IInterpreterService>(IInterpreterService),
114+
);
115+
pythonVersion?.sysVersion?.startsWith('3.13');
116+
}
117+
118+
if (isPythonShell && (!pythonrcSetting || isWindows() || isPython313)) {
109119
// If user has explicitly disabled SI for Python, use sendText for inside Terminal REPL.
110120
terminal.sendText(commandLine);
111121
return undefined;

src/test/common/terminals/service.unit.test.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import { ITerminalAutoActivation } from '../../../client/terminals/types';
2525
import { createPythonInterpreter } from '../../utils/interpreters';
2626
import * as workspaceApis from '../../../client/common/vscodeApis/workspaceApis';
2727
import * as platform from '../../../client/common/utils/platform';
28+
import { IInterpreterService } from '../../../client/interpreter/contracts';
29+
import { PythonEnvironment } from '../../../client/pythonEnvironments/info';
2830

2931
suite('Terminal Service', () => {
3032
let service: TerminalService;
@@ -44,6 +46,7 @@ suite('Terminal Service', () => {
4446
let pythonConfig: TypeMoq.IMock<WorkspaceConfiguration>;
4547
let editorConfig: TypeMoq.IMock<WorkspaceConfiguration>;
4648
let isWindowsStub: sinon.SinonStub;
49+
let interpreterService: TypeMoq.IMock<IInterpreterService>;
4750

4851
setup(() => {
4952
terminal = TypeMoq.Mock.ofType<VSCodeTerminal>();
@@ -87,6 +90,10 @@ suite('Terminal Service', () => {
8790
disposables = [];
8891

8992
mockServiceContainer = TypeMoq.Mock.ofType<IServiceContainer>();
93+
interpreterService = TypeMoq.Mock.ofType<IInterpreterService>();
94+
interpreterService
95+
.setup((i) => i.getActiveInterpreter(TypeMoq.It.isAny()))
96+
.returns(() => Promise.resolve(({ path: 'ps' } as unknown) as PythonEnvironment));
9097

9198
mockServiceContainer.setup((c) => c.get(ITerminalManager)).returns(() => terminalManager.object);
9299
mockServiceContainer.setup((c) => c.get(ITerminalHelper)).returns(() => terminalHelper.object);
@@ -95,6 +102,8 @@ suite('Terminal Service', () => {
95102
mockServiceContainer.setup((c) => c.get(IWorkspaceService)).returns(() => workspaceService.object);
96103
mockServiceContainer.setup((c) => c.get(ITerminalActivator)).returns(() => terminalActivator.object);
97104
mockServiceContainer.setup((c) => c.get(ITerminalAutoActivation)).returns(() => terminalAutoActivator.object);
105+
mockServiceContainer.setup((c) => c.get(IInterpreterService)).returns(() => interpreterService.object);
106+
98107
getConfigurationStub = sinon.stub(workspaceApis, 'getConfiguration');
99108
isWindowsStub = sinon.stub(platform, 'isWindows');
100109
pythonConfig = TypeMoq.Mock.ofType<WorkspaceConfiguration>();
@@ -234,7 +243,7 @@ suite('Terminal Service', () => {
234243
terminal.verify((t) => t.sendText(TypeMoq.It.isValue(textToSend)), TypeMoq.Times.exactly(1));
235244
});
236245

237-
test('Ensure sendText is NOT called when Python shell integration and terminal shell integration are both enabled - Mac, Linux', async () => {
246+
test('Ensure sendText is NOT called when Python shell integration and terminal shell integration are both enabled - Mac, Linux - !Python3.13', async () => {
238247
isWindowsStub.returns(false);
239248
pythonConfig
240249
.setup((p) => p.get('terminal.shellIntegration.enabled'))

0 commit comments

Comments
 (0)