Skip to content

Commit 064b837

Browse files
authored
Add default debug config and fix labels (microsoft#3860)
For microsoft#3321
1 parent f0ba057 commit 064b837

File tree

12 files changed

+157
-122
lines changed

12 files changed

+157
-122
lines changed

resources/default.launch.json

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
[
2+
{
3+
"name": "Python: Current File (Integrated Terminal)",
4+
"type": "python",
5+
"request": "launch",
6+
"program": "${file}",
7+
"console": "integratedTerminal"
8+
},
9+
{
10+
"name": "Python: Attach",
11+
"type": "python",
12+
"request": "attach",
13+
"port": 5678,
14+
"host": "localhost"
15+
},
16+
{
17+
"name": "Python: Module",
18+
"type": "python",
19+
"request": "launch",
20+
"module": "enter-your-module-name-here",
21+
"console": "integratedTerminal"
22+
},
23+
{
24+
"name": "Python: Django",
25+
"type": "python",
26+
"request": "launch",
27+
"program": "${workspaceFolder}/manage.py",
28+
"console": "integratedTerminal",
29+
"args": [
30+
"runserver",
31+
"--noreload",
32+
"--nothreading"
33+
],
34+
"django": true
35+
},
36+
{
37+
"name": "Python: Flask",
38+
"type": "python",
39+
"request": "launch",
40+
"module": "flask",
41+
"env": {
42+
"FLASK_APP": "app.py"
43+
},
44+
"args": [
45+
"run",
46+
"--no-debugger",
47+
"--no-reload"
48+
],
49+
"jinja": true
50+
},
51+
{
52+
"name": "Python: Current File (External Terminal)",
53+
"type": "python",
54+
"request": "launch",
55+
"program": "${file}",
56+
"console": "externalTerminal"
57+
}
58+
]

src/client/common/utils/localize.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -110,38 +110,38 @@ export namespace DebugConfigurationPrompts {
110110
export const selectConfigurationTitle = localize('debug.selectConfigurationTitle', 'Select a debug configuration');
111111
export const selectConfigurationPlaceholder = localize('debug.selectConfigurationPlaceholder', 'Debug Configuration');
112112
export const debugFileConfigurationLabel = localize('debug.debugFileConfigurationLabel', 'Python File');
113-
export const debugFileConfigurationDescription = localize('debug.debugFileConfigurationDescription', 'Debug Python file');
113+
export const debugFileConfigurationDescription = localize('debug.debugFileConfigurationDescription', 'Debug currently active Python file');
114114
export const debugModuleConfigurationLabel = localize('debug.debugModuleConfigurationLabel', 'Module');
115-
export const debugModuleConfigurationDescription = localize('debug.debugModuleConfigurationDescription', 'Debug Python module/package');
115+
export const debugModuleConfigurationDescription = localize('debug.debugModuleConfigurationDescription', 'Debug a python module by invoking it with \'-m\'');
116116
export const remoteAttachConfigurationLabel = localize('debug.remoteAttachConfigurationLabel', 'Remote Attach');
117-
export const remoteAttachConfigurationDescription = localize('debug.remoteAttachConfigurationDescription', 'Debug a remote Python program');
117+
export const remoteAttachConfigurationDescription = localize('debug.remoteAttachConfigurationDescription', 'Attach to a remote ptsvd debug server');
118118
export const debugDjangoConfigurationLabel = localize('debug.debugDjangoConfigurationLabel', 'Django');
119-
export const debugDjangoConfigurationDescription = localize('debug.debugDjangoConfigurationDescription', 'Web Application');
119+
export const debugDjangoConfigurationDescription = localize('debug.debugDjangoConfigurationDescription', 'Launch and debug a Django web application');
120120
export const debugFlaskConfigurationLabel = localize('debug.debugFlaskConfigurationLabel', 'Flask');
121-
export const debugFlaskConfigurationDescription = localize('debug.debugFlaskConfigurationDescription', 'Web Application');
121+
export const debugFlaskConfigurationDescription = localize('debug.debugFlaskConfigurationDescription', 'Launch and debug a Flask web application');
122122
export const debugPyramidConfigurationLabel = localize('debug.debugPyramidConfigurationLabel', 'Pyramid');
123123
export const debugPyramidConfigurationDescription = localize('debug.debugPyramidConfigurationDescription', 'Web Application');
124124
export const djangoEnterManagePyPathTitle = localize('debug.djangoEnterManagePyPathTitle', 'Debug Django');
125125
// tslint:disable-next-line:no-invalid-template-strings
126-
export const djangoEnterManagePyPathPrompt = localize('debug.djangoEnterManagePyPathPrompt', 'Enter path to manage.py (\'${workspaceFolderToken}\' points to the root of the current workspace folder)');
127-
export const djangoEnterManagePyPathInvalidFilePathError = localize('debug.djangoEnterManagePyPathInvalidFilePathError', 'Enter a valid Python file path');
126+
export const djangoEnterManagePyPathPrompt = localize('debug.djangoEnterManagePyPathPrompt', 'Enter path to manage.py (\'${workspaceFolder}\' points to the root of the current workspace folder)');
127+
export const djangoEnterManagePyPathInvalidFilePathError = localize('debug.djangoEnterManagePyPathInvalidFilePathError', 'Enter a valid python file path');
128128
export const flaskEnterAppPathOrNamePathTitle = localize('debug.flaskEnterAppPathOrNamePathTitle', 'Debug Flask');
129129
export const flaskEnterAppPathOrNamePathPrompt = localize('debug.flaskEnterAppPathOrNamePathPrompt', 'Enter path to application, e.g. \'app.py\' or \'app\'');
130130
export const flaskEnterAppPathOrNamePathInvalidNameError = localize('debug.flaskEnterAppPathOrNamePathInvalidNameError', 'Enter a valid name');
131131

132132
export const moduleEnterModuleTitle = localize('debug.moduleEnterModuleTitle', 'Debug Module');
133133
export const moduleEnterModulePrompt = localize('debug.moduleEnterModulePrompt', 'Enter Python module/package name');
134-
export const moduleEnterModuleInvalidNameError = localize('debug.moduleEnterModuleInvalidNameError', 'Enter a valid name');
134+
export const moduleEnterModuleInvalidNameError = localize('debug.moduleEnterModuleInvalidNameError', 'Enter a valid module name');
135135
export const pyramidEnterDevelopmentIniPathTitle = localize('debug.pyramidEnterDevelopmentIniPathTitle', 'Debug Pyramid');
136136
// tslint:disable-next-line:no-invalid-template-strings
137137
export const pyramidEnterDevelopmentIniPathPrompt = localize('debug.pyramidEnterDevelopmentIniPathPrompt', '`Enter path to development.ini (\'${workspaceFolderToken}\' points to the root of the current workspace folder)`');
138138
export const pyramidEnterDevelopmentIniPathInvalidFilePathError = localize('debug.pyramidEnterDevelopmentIniPathInvalidFilePathError', 'Enter a valid file path');
139139
export const attachRemotePortTitle = localize('debug.attachRemotePortTitle', 'Remote Debugging');
140-
export const attachRemotePortPrompt = localize('debug.attachRemotePortPrompt', 'Enter port number');
140+
export const attachRemotePortPrompt = localize('debug.attachRemotePortPrompt', 'Enter the port number that the ptvsd server is listening on');
141141
export const attachRemotePortValidationError = localize('debug.attachRemotePortValidationError', 'Enter a valid port number');
142142
export const attachRemoteHostTitle = localize('debug.attachRemoteHostTitle', 'Remote Debugging');
143-
export const attachRemoteHostPrompt = localize('debug.attachRemoteHostPrompt', 'Enter a host name or IP address');
144-
export const attachRemoteHostValidationError = localize('debug.attachRemoteHostValidationError', 'Enter a valid host name or IP address');
143+
export const attachRemoteHostPrompt = localize('debug.attachRemoteHostPrompt', 'Enter host name');
144+
export const attachRemoteHostValidationError = localize('debug.attachRemoteHostValidationError', 'Enter a host name or IP address');
145145
}
146146

147147
// Skip using vscode-nls and instead just compute our strings based on key values. Key values

src/client/debugger/extension/configuration/debugConfigurationProvider.ts

Lines changed: 0 additions & 23 deletions
This file was deleted.

src/client/debugger/extension/configuration/debugConfigurationService.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@
44
'use strict';
55

66
import { inject, injectable, named } from 'inversify';
7+
import * as path from 'path';
78
import { CancellationToken, DebugConfiguration, QuickPickItem, WorkspaceFolder } from 'vscode';
9+
import { IFileSystem } from '../../../common/platform/types';
810
import { DebugConfigurationPrompts } from '../../../common/utils/localize';
911
import { IMultiStepInput, IMultiStepInputFactory, InputStep, IQuickPickParameters } from '../../../common/utils/multiStepInput';
12+
import { EXTENSION_ROOT_DIR } from '../../../constants';
13+
import { sendTelemetryEvent } from '../../../telemetry';
14+
import { DEBUGGER_CONFIGURATION_PROMPTS } from '../../../telemetry/constants';
1015
import { AttachRequestArguments, DebugConfigurationArguments, LaunchRequestArguments } from '../../types';
1116
import { DebugConfigurationState, DebugConfigurationType, IDebugConfigurationService } from '../types';
1217
import { IDebugConfigurationProviderFactory, IDebugConfigurationResolver } from './types';
@@ -16,14 +21,19 @@ export class PythonDebugConfigurationService implements IDebugConfigurationServi
1621
constructor(@inject(IDebugConfigurationResolver) @named('attach') private readonly attachResolver: IDebugConfigurationResolver<AttachRequestArguments>,
1722
@inject(IDebugConfigurationResolver) @named('launch') private readonly launchResolver: IDebugConfigurationResolver<LaunchRequestArguments>,
1823
@inject(IDebugConfigurationProviderFactory) private readonly providerFactory: IDebugConfigurationProviderFactory,
19-
@inject(IMultiStepInputFactory) private readonly multiStepFactory: IMultiStepInputFactory) {
24+
@inject(IMultiStepInputFactory) private readonly multiStepFactory: IMultiStepInputFactory,
25+
@inject(IFileSystem) private readonly fs: IFileSystem) {
2026
}
21-
public async provideDebugConfigurations?(folder: WorkspaceFolder | undefined, token?: CancellationToken): Promise<DebugConfiguration[] | undefined> {
27+
public async provideDebugConfigurations(folder: WorkspaceFolder | undefined, token?: CancellationToken): Promise<DebugConfiguration[] | undefined> {
2228
const config: Partial<DebugConfigurationArguments> = {};
2329
const state = { config, folder, token };
2430
const multiStep = this.multiStepFactory.create<DebugConfigurationState>();
2531
await multiStep.run((input, s) => this.pickDebugConfiguration(input, s), state);
26-
return state.config as DebugConfiguration[];
32+
if (Object.keys(state.config).length === 0) {
33+
return this.getDefaultDebugConfig();
34+
} else {
35+
return [state.config as DebugConfiguration];
36+
}
2737
}
2838
public async resolveDebugConfiguration(folder: WorkspaceFolder | undefined, debugConfiguration: DebugConfiguration, token?: CancellationToken): Promise<DebugConfiguration | undefined> {
2939
if (debugConfiguration.request === 'attach') {
@@ -32,6 +42,12 @@ export class PythonDebugConfigurationService implements IDebugConfigurationServi
3242
return this.launchResolver.resolveDebugConfiguration(folder, debugConfiguration as LaunchRequestArguments, token);
3343
}
3444
}
45+
protected async getDefaultDebugConfig(): Promise<DebugConfiguration[]> {
46+
sendTelemetryEvent(DEBUGGER_CONFIGURATION_PROMPTS, undefined, { configurationType: DebugConfigurationType.default });
47+
const jsFilePath = path.join(EXTENSION_ROOT_DIR, 'resources', 'default.launch.json');
48+
const jsonStr = await this.fs.readFile(jsFilePath);
49+
return JSON.parse(jsonStr) as DebugConfiguration[];
50+
}
3551
protected async pickDebugConfiguration(input: IMultiStepInput<DebugConfigurationState>, state: DebugConfigurationState): Promise<InputStep<DebugConfigurationState> | void> {
3652
type DebugConfigurationQuickPickItem = QuickPickItem & { type: DebugConfigurationType };
3753
const items: DebugConfigurationQuickPickItem[] = [

src/client/debugger/extension/configuration/providers/moduleLaunch.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ export class ModuleLaunchDebugConfigurationProvider implements IDebugConfigurati
2020
name: localize('python.snippet.launch.module.label', 'Python: Module')(),
2121
type: DebuggerTypeName,
2222
request: 'launch',
23-
module: 'enter-your-module-name-here'
23+
module: 'enter-your-module-name'
2424
};
2525
const selectedModule = await input.showInputBox({
2626
title: DebugConfigurationPrompts.moduleEnterModuleTitle(),
27-
value: config.module || 'enter-your-module-name-here',
27+
value: config.module || 'enter-your-module-name',
2828
prompt: DebugConfigurationPrompts.moduleEnterModulePrompt(),
2929
validate: value => Promise.resolve((value && value.trim().length > 0) ? undefined : DebugConfigurationPrompts.moduleEnterModuleInvalidNameError())
3030
});

src/client/debugger/extension/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export interface IDebugConfigurationProvider {
2121
}
2222

2323
export enum DebugConfigurationType {
24+
default = 'default',
2425
launchFile = 'launchFile',
2526
remoteAttach = 'remoteAttach',
2627
launchDjango = 'launchDjango',

src/test/debugger/attach.ptvsd.test.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ import '../../client/common/extensions';
66
import { ChildProcess, spawn } from 'child_process';
77
import * as getFreePort from 'get-port';
88
import * as path from 'path';
9+
import { instance, mock } from 'ts-mockito';
910
import * as TypeMoq from 'typemoq';
1011
import { DebugConfiguration, Uri } from 'vscode';
1112
import { DebugClient } from 'vscode-debugadapter-testsupport';
1213
import { IDocumentManager, IWorkspaceService } from '../../client/common/application/types';
1314
import { EXTENSION_ROOT_DIR } from '../../client/common/constants';
1415
import { IS_WINDOWS } from '../../client/common/platform/constants';
16+
import { FileSystem } from '../../client/common/platform/fileSystem';
1517
import { IPlatformService } from '../../client/common/platform/types';
1618
import { IConfigurationService } from '../../client/common/types';
1719
import { IMultiStepInputFactory } from '../../client/common/utils/multiStepInput';
@@ -99,7 +101,8 @@ suite('Debugging - Attach Debugger', () => {
99101
const attachResolver = new AttachConfigurationResolver(workspaceService.object, documentManager.object, platformService.object, configurationService.object);
100102
const providerFactory = TypeMoq.Mock.ofType<IDebugConfigurationProviderFactory>().object;
101103
const multiStepIput = TypeMoq.Mock.ofType<IMultiStepInputFactory>().object;
102-
const configProvider = new PythonDebugConfigurationService(attachResolver, launchResolver.object, providerFactory, multiStepIput);
104+
const fs = mock(FileSystem);
105+
const configProvider = new PythonDebugConfigurationService(attachResolver, launchResolver.object, providerFactory, multiStepIput, instance(fs));
103106

104107
await configProvider.resolveDebugConfiguration({ index: 0, name: 'root', uri: Uri.file(localRoot) }, options);
105108
const attachPromise = debugClient.attachRequest(options);

src/test/debugger/extension/configuration/debugConfigurationProvider.unit.test.ts

Lines changed: 0 additions & 68 deletions
This file was deleted.

0 commit comments

Comments
 (0)