Skip to content

Commit 28be0f4

Browse files
Add user settings in issue template (microsoft#16492)
* Add user settings in issue template * Fix tests * Add placeholder for path settings * Fix user settings json values * Fix tests Co-authored-by: Karthik Nadig <kanadig@microsoft.com>
1 parent 284b5d5 commit 28be0f4

5 files changed

Lines changed: 229 additions & 4 deletions

File tree

resources/report_issue_template.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
[**NOTE**: If you suspect that your issue is related to the Microsoft Python Language Server (`python.languageServer: 'Microsoft'`), please download our new language server [Pylance](https://marketplace.visualstudio.com/items?itemName=ms-python.vscode-pylance) from the VS Code marketplace to see if that fixes your issue]
88

9-
109
## Expected
1110

1211
XXX
@@ -39,9 +38,23 @@ You can attach such things **after** you create your issue on GitHub.
3938
<p>
4039

4140
<!-- Run the "Python: Show Output" command to see the requested output. --->
41+
4242
```
4343
{3}
4444
```
4545

4646
</p>
4747
</details>
48+
49+
<details>
50+
51+
<summary>User Settings</summary>
52+
53+
<p>
54+
55+
```
56+
{4}
57+
```
58+
59+
</p>
60+
</details>
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
{
2+
"initialize": false,
3+
"pythonPath": "placeholder",
4+
"onDidChange": false,
5+
"defaultInterpreterPath": "placeholder",
6+
"defaultLS": true,
7+
"showStartPage": true,
8+
"downloadLanguageServer": true,
9+
"jediPath": false,
10+
"jediMemoryLimit": false,
11+
"envFile": "placeholder",
12+
"venvPath": "placeholder",
13+
"venvFolders": "placeholder",
14+
"condaPath": "placeholder",
15+
"pipenvPath": "placeholder",
16+
"poetryPath": "placeholder",
17+
"devOptions": false,
18+
"disableInstallationChecks": false,
19+
"globalModuleInstallation": false,
20+
"autoUpdateLanguageServer": false,
21+
"languageServer": true,
22+
"languageServerIsDefault": false,
23+
"logging": true,
24+
"useIsolation": false,
25+
"changed": false,
26+
"_pythonPath": false,
27+
"_defaultInterpreterPath": false,
28+
"workspace": false,
29+
"workspaceRoot": false,
30+
"linting": {
31+
"enabled": true,
32+
"cwd": "placeholder",
33+
"Flake8Args": "placeholder",
34+
"flake8CategorySeverity": false,
35+
"flake8Enabled": true,
36+
"flake8Path": "placeholder",
37+
"ignorePatterns": false,
38+
"lintOnSave": true,
39+
"maxNumberOfProblems": false,
40+
"banditArgs": "placeholder",
41+
"banditEnabled" : true,
42+
"banditPath": "placeholder",
43+
"mypyArgs": "placeholder",
44+
"mypyCategorySeverity": false,
45+
"mypyEnabled": true,
46+
"mypyPath": "placeholder",
47+
"pycodestyleArgs": "placeholder",
48+
"pycodestyleCategorySeverity": false,
49+
"pycodestyleEnabled": true,
50+
"pycodestylePath": "placeholder",
51+
"prospectorArgs": "placeholder",
52+
"prospectorEnabled": true,
53+
"prospectorPath": "placeholder",
54+
"pydocstyleArgs": "placeholder",
55+
"pydocstyleEnabled": true,
56+
"pydocstylePath": "placeholder",
57+
"pylamaArgs": "placeholder",
58+
"pylamaEnabled": true,
59+
"pylamaPath": "placeholder",
60+
"pylintArgs": "placeholder",
61+
"pylintCategorySeverity": false,
62+
"pylintEnabled": true,
63+
"pylintPath": "placeholder",
64+
"pylintUseMinimalCheckers": true
65+
},
66+
"analysis": {
67+
"completeFunctionParens": true,
68+
"autoImportCompletions": true,
69+
"autoSearchPaths": "placeholder",
70+
"stubPath": "placeholder",
71+
"diagnosticMode": true,
72+
"extraPaths": "placeholder",
73+
"useLibraryCodeForTypes": true,
74+
"typeCheckingMode": true,
75+
"diagnosticSeverityOverrides": false,
76+
"diagnosticPublishDelay": false,
77+
"errors": true,
78+
"warnings": true,
79+
"information": true,
80+
"disabled": true,
81+
"typeshedPaths": "placeholder",
82+
"cacheFolderPath": "placeholder",
83+
"memory": true,
84+
"logLevel": true,
85+
"symbolsHierarchyDepthLimit": false
86+
},
87+
"sortImports": {
88+
"args": "placeholder",
89+
"path": "placeholder"
90+
},
91+
"formatting": {
92+
"autopep8Args": "placeholder",
93+
"autopep8Path": "placeholder",
94+
"provider": true,
95+
"blackArgs": "placeholder",
96+
"blackPath": "placeholder",
97+
"yapfArgs": "placeholder",
98+
"yapfPath": "placeholder"
99+
},
100+
"autoComplete": {
101+
"addBrackets": true,
102+
"extraPaths": "placeholder",
103+
"showAdvancedMembers": true,
104+
"typeshedPaths": "placeholder"
105+
},
106+
"workspaceSymbols": {
107+
"ctagsPath":"placeholder",
108+
"enabled": true,
109+
"exclusionPatterns": true,
110+
"rebuildOnFileSave": true,
111+
"rebuildOnStart": true,
112+
"tagFilePath": "placeholder"
113+
},
114+
"testing": {
115+
"cwd": "placeholder",
116+
"debugPort": true,
117+
"nosetestArgs": "placeholder",
118+
"nosetestsEnabled": true,
119+
"nosetestPath": "placeholder",
120+
"promptToConfigure": true,
121+
"pytestArgs": "placeholder",
122+
"pytestEnabled": true,
123+
"pytestPath": "placeholder",
124+
"unittestArgs": "placeholder",
125+
"unittestEnabled": true,
126+
"autoTestDiscoverOnSaveEnabled": true
127+
},
128+
"terminal": {
129+
"activateEnvironment": true,
130+
"executeInFileDir": "placeholder",
131+
"launchArgs": "placeholder",
132+
"activateEnvInCurrentTerminal": false
133+
},
134+
"tensorBoard": {
135+
"logDirectory": "placeholder"
136+
},
137+
"experiments": {
138+
"enabled": true,
139+
"optInto": true,
140+
"optOutFrom": true
141+
},
142+
"insidersChannel": true
143+
}

src/client/common/application/commands/reportIssueCommand.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
'use strict';
55

66
import * as fs from 'fs-extra';
7+
import * as os from 'os';
78
import * as path from 'path';
89
import { inject, injectable } from 'inversify';
910
import { IExtensionSingleActivationService } from '../../../activation/types';
@@ -13,6 +14,7 @@ import { IInterpreterService, IInterpreterVersionService } from '../../../interp
1314
import { identifyEnvironment } from '../../../pythonEnvironments/common/environmentIdentifier';
1415
import { getPythonOutputChannelContent } from '../../../logging';
1516
import { Commands } from '../../constants';
17+
import { IConfigurationService, IPythonSettings } from '../../types';
1618

1719
/**
1820
* Allows the user to report an issue related to the Python extension using our template.
@@ -24,15 +26,43 @@ export class ReportIssueCommandHandler implements IExtensionSingleActivationServ
2426
@inject(IWorkspaceService) private readonly workspaceService: IWorkspaceService,
2527
@inject(IInterpreterService) private readonly interpreterService: IInterpreterService,
2628
@inject(IInterpreterVersionService) private readonly interpreterVersionService: IInterpreterVersionService,
29+
@inject(IConfigurationService) protected readonly configurationService: IConfigurationService,
2730
) {}
2831

2932
public async activate(): Promise<void> {
3033
this.commandManager.registerCommand(Commands.ReportIssue, this.openReportIssue, this);
3134
}
3235

36+
private argSettingsPath = path.join(EXTENSION_ROOT_DIR, 'resources', 'report_issue_user_settings.json');
37+
3338
private templatePath = path.join(EXTENSION_ROOT_DIR, 'resources', 'report_issue_template.md');
3439

3540
public async openReportIssue(): Promise<void> {
41+
const settings: IPythonSettings = this.configurationService.getSettings();
42+
const argSettings = JSON.parse(await fs.readFile(this.argSettingsPath, 'utf8'));
43+
let userSettings = '';
44+
const keys: [keyof IPythonSettings] = Object.keys(settings) as [keyof IPythonSettings];
45+
keys.forEach((property) => {
46+
const argSetting = argSettings[property];
47+
if (argSetting) {
48+
if (typeof argSetting === 'object') {
49+
userSettings = userSettings.concat(os.EOL, property, os.EOL);
50+
const argSettingsDict = (settings[property] as unknown) as Record<string, unknown>;
51+
if (typeof argSettingsDict === 'object') {
52+
Object.keys(argSetting).forEach((item) => {
53+
const prop = argSetting[item];
54+
if (prop) {
55+
const value = prop === true ? JSON.stringify(argSettingsDict[item]) : '"<placeholder>"';
56+
userSettings = userSettings.concat('• ', item, ': ', value, os.EOL);
57+
}
58+
});
59+
}
60+
} else {
61+
const value = argSetting === true ? JSON.stringify(settings[property]) : '"<placeholder>"';
62+
userSettings = userSettings.concat(os.EOL, property, ': ', value, os.EOL);
63+
}
64+
}
65+
});
3666
const pythonLogs = await getPythonOutputChannelContent();
3767
const template = await fs.readFile(this.templatePath, 'utf8');
3868
const interpreterPath = (await this.interpreterService.getActiveInterpreter())?.path || 'not-selected';
@@ -43,7 +73,7 @@ export class ReportIssueCommandHandler implements IExtensionSingleActivationServ
4373

4474
this.commandManager.executeCommand('workbench.action.openIssueReporter', {
4575
extensionId: 'ms-python.python',
46-
issueBody: template.format(pythonVersion, virtualEnv, languageServer, pythonLogs),
76+
issueBody: template.format(pythonVersion, virtualEnv, languageServer, pythonLogs, userSettings),
4777
});
4878
}
4979
}

src/test/common/application/commands/issueTemplateVenv1.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
[**NOTE**: If you suspect that your issue is related to the Microsoft Python Language Server (`python.languageServer: 'Microsoft'`), please download our new language server [Pylance](https://marketplace.visualstudio.com/items?itemName=ms-python.vscode-pylance) from the VS Code marketplace to see if that fixes your issue]
88

9-
109
## Expected
1110

1211
XXX
@@ -39,9 +38,32 @@ You can attach such things **after** you create your issue on GitHub.
3938
<p>
4039

4140
<!-- Run the "Python: Show Output" command to see the requested output. --->
41+
4242
```
4343
Python Output
4444
```
4545

4646
</p>
4747
</details>
48+
49+
<details>
50+
51+
<summary>User Settings</summary>
52+
53+
<p>
54+
55+
```
56+
57+
experiments
58+
• enabled: true
59+
• optInto: []
60+
• optOutFrom: []
61+
62+
insidersChannel: "off"
63+
64+
venvPath: "<placeholder>"
65+
66+
```
67+
68+
</p>
69+
</details>

src/test/common/application/commands/reportIssueCommand.unit.test.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,16 @@ import { InterpreterService } from '../../../../client/interpreter/interpreterSe
2323
import * as Logging from '../../../../client/logging/_global';
2424
import { Commands } from '../../../../client/common/constants';
2525
import { AllCommands } from '../../../../client/common/application/commands';
26+
import { ConfigurationService } from '../../../../client/common/configuration/service';
27+
import { IConfigurationService } from '../../../../client/common/types';
2628

2729
suite('Report Issue Command', () => {
2830
let reportIssueCommandHandler: ReportIssueCommandHandler;
2931
let cmdManager: ICommandManager;
3032
let workspaceService: IWorkspaceService;
3133
let interpreterVersionService: IInterpreterVersionService;
3234
let interpreterService: IInterpreterService;
35+
let configurationService: IConfigurationService;
3336
let identifyEnvironmentStub: sinon.SinonStub;
3437
let getPythonOutputContentStub: sinon.SinonStub;
3538

@@ -38,6 +41,7 @@ suite('Report Issue Command', () => {
3841
workspaceService = mock(WorkspaceService);
3942
cmdManager = mock(CommandManager);
4043
interpreterService = mock(InterpreterService);
44+
configurationService = mock(ConfigurationService);
4145

4246
when(cmdManager.executeCommand('workbench.action.openIssueReporter', anything())).thenResolve();
4347
when(interpreterVersionService.getVersion(anything(), anything())).thenResolve('3.9.0');
@@ -47,6 +51,17 @@ suite('Report Issue Command', () => {
4751
}),
4852
);
4953
when(interpreterService.getActiveInterpreter(anything())).thenResolve(undefined);
54+
when(configurationService.getSettings()).thenReturn({
55+
experiments: {
56+
enabled: true,
57+
optInto: [],
58+
optOutFrom: [],
59+
},
60+
insidersChannel: 'off',
61+
initialize: true,
62+
venvPath: 'path',
63+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
64+
} as any);
5065
identifyEnvironmentStub = sinon.stub(EnvIdentifier, 'identifyEnvironment');
5166
identifyEnvironmentStub.resolves(PythonEnvKind.Venv);
5267

@@ -59,6 +74,7 @@ suite('Report Issue Command', () => {
5974
instance(workspaceService),
6075
instance(interpreterService),
6176
instance(interpreterVersionService),
77+
instance(configurationService),
6278
);
6379
await reportIssueCommandHandler.activate();
6480
});
@@ -90,6 +106,7 @@ suite('Report Issue Command', () => {
90106
verify(cmdManager.registerCommand(Commands.ReportIssue, anything(), anything())).once();
91107
verify(cmdManager.executeCommand('workbench.action.openIssueReporter', anything())).once();
92108
expect(args[0]).to.be.equal('workbench.action.openIssueReporter');
93-
expect(args[1].issueBody).to.be.equal(expectedIssueBody);
109+
const actual = args[1].issueBody;
110+
expect(actual).to.be.equal(expectedIssueBody);
94111
});
95112
});

0 commit comments

Comments
 (0)