From 58e21eee75a0591ecf2aaf6568b1c931d402ac71 Mon Sep 17 00:00:00 2001 From: Alina Lobastova Date: Sun, 17 Mar 2019 17:00:09 -0700 Subject: [PATCH 1/3] Add ignore button to the MacInterpreterSelectedAndNoOtherInterpretersDiagnostic diagnostic message to provide the ability to opt out of the warning. (Fixing related issue #4448) --- .../checks/macPythonInterpreter.ts | 11 ++++- .../checks/macPythonInterpreter.unit.test.ts | 45 +++++++++++++++++-- 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/client/application/diagnostics/checks/macPythonInterpreter.ts b/src/client/application/diagnostics/checks/macPythonInterpreter.ts index f5d97ae2542f..0e7c4f50b1bb 100644 --- a/src/client/application/diagnostics/checks/macPythonInterpreter.ts +++ b/src/client/application/diagnostics/checks/macPythonInterpreter.ts @@ -106,7 +106,9 @@ export class InvalidMacPythonInterpreterService extends BaseDiagnosticsService { ); await Promise.all( diagnostics.map(async diagnostic => { - if (!this.canHandle(diagnostic)) { + const canHandle = await this.canHandle(diagnostic); + const shouldIgnore = await this.filterService.shouldIgnoreDiagnostic(diagnostic.code); + if (!canHandle || shouldIgnore) { return; } const commandPrompts = this.getCommandPrompts(diagnostic); @@ -169,6 +171,13 @@ export class InvalidMacPythonInterpreterService extends BaseDiagnosticsService { type: 'launch', options: 'https://www.python.org/downloads' }) + }, + { + prompt: 'Do not show again', + command: commandFactory.createCommand(diagnostic, { + type: 'ignore', + options: DiagnosticScope.Global + }) } ]; } diff --git a/src/test/application/diagnostics/checks/macPythonInterpreter.unit.test.ts b/src/test/application/diagnostics/checks/macPythonInterpreter.unit.test.ts index 829b169f8ed4..f6ff9eef898a 100644 --- a/src/test/application/diagnostics/checks/macPythonInterpreter.unit.test.ts +++ b/src/test/application/diagnostics/checks/macPythonInterpreter.unit.test.ts @@ -8,11 +8,12 @@ import { expect } from 'chai'; import * as typemoq from 'typemoq'; import { ConfigurationChangeEvent } from 'vscode'; +import { BaseDiagnosticsService } from '../../../../client/application/diagnostics/base'; import { InvalidMacPythonInterpreterDiagnostic, InvalidMacPythonInterpreterService } from '../../../../client/application/diagnostics/checks/macPythonInterpreter'; import { CommandOption, IDiagnosticsCommandFactory } from '../../../../client/application/diagnostics/commands/types'; import { DiagnosticCodes } from '../../../../client/application/diagnostics/constants'; import { DiagnosticCommandPromptHandlerServiceId, MessageCommandPrompt } from '../../../../client/application/diagnostics/promptHandler'; -import { IDiagnostic, IDiagnosticCommand, IDiagnosticHandlerService, IDiagnosticsService } from '../../../../client/application/diagnostics/types'; +import { DiagnosticScope, IDiagnostic, IDiagnosticCommand, IDiagnosticFilterService, IDiagnosticHandlerService, IDiagnosticsService } from '../../../../client/application/diagnostics/types'; import { CommandsWithoutArgs } from '../../../../client/common/application/commands'; import { IWorkspaceService } from '../../../../client/common/application/types'; import { IPlatformService } from '../../../../client/common/platform/types'; @@ -30,6 +31,7 @@ suite('Application Diagnostics - Checks Python Interpreter', () => { let interpreterService: typemoq.IMock; let platformService: typemoq.IMock; let helper: typemoq.IMock; + let filterService: typemoq.IMock; const pythonPath = 'My Python Path in Settings'; let serviceContainer: typemoq.IMock; function createContainer() { @@ -57,6 +59,9 @@ suite('Application Diagnostics - Checks Python Interpreter', () => { .returns(() => helper.object); serviceContainer.setup(s => s.get(typemoq.It.isValue(IDisposableRegistry))) .returns(() => []); + filterService = typemoq.Mock.ofType(); + serviceContainer.setup(s => s.get(typemoq.It.isValue(IDiagnosticFilterService))) + .returns(() => filterService.object); platformService .setup(p => p.isMac) @@ -67,8 +72,14 @@ suite('Application Diagnostics - Checks Python Interpreter', () => { suite('Diagnostics', () => { setup(() => { diagnosticService = new class extends InvalidMacPythonInterpreterService { + public _clear() { + while (BaseDiagnosticsService.handledDiagnosticCodeKeys.length > 0) { + BaseDiagnosticsService.handledDiagnosticCodeKeys.shift(); + } + } protected addPythonPathChangedHandler() { noop(); } }(createContainer(), interpreterService.object, platformService.object, helper.object); + (diagnosticService as any)._clear(); }); test('Can handle InvalidPythonPathInterpreter diagnostics', async () => { @@ -96,7 +107,7 @@ suite('Application Diagnostics - Checks Python Interpreter', () => { expect(canHandle).to.be.equal(false, 'Invalid value'); diagnostic.verifyAll(); }); - test('Should return empty diagnostics if not a Macc', async () => { + test('Should return empty diagnostics if not a Mac', async () => { platformService.reset(); platformService .setup(p => p.isMac) @@ -270,10 +281,11 @@ suite('Application Diagnostics - Checks Python Interpreter', () => { expect(messagePrompt).not.be.equal(undefined, 'Message prompt not set'); expect(messagePrompt!.commandPrompts).to.be.deep.equal([{ prompt: 'Select Python Interpreter', command: cmd }]); }); - test('Handling no interpreters diagnostisc should return download and learn links', async () => { + test('Handling no interpreters diagnostisc should return 3 commands', async () => { const diagnostic = new InvalidMacPythonInterpreterDiagnostic(DiagnosticCodes.MacInterpreterSelectedAndNoOtherInterpretersDiagnostic, undefined); const cmdDownload = {} as any as IDiagnosticCommand; const cmdLearn = {} as any as IDiagnosticCommand; + const cmdIgnore = {} as any as IDiagnosticCommand; let messagePrompt: MessageCommandPrompt | undefined; messageHandler .setup(i => i.handle(typemoq.It.isValue(diagnostic), typemoq.It.isAny())) @@ -288,13 +300,38 @@ suite('Application Diagnostics - Checks Python Interpreter', () => { typemoq.It.isObjectWith>({ type: 'launch', options: 'https://www.python.org/downloads' }))) .returns(() => cmdDownload) .verifiable(typemoq.Times.once()); + commandFactory.setup(f => f.createCommand(typemoq.It.isAny(), + typemoq.It.isObjectWith>({ type: 'ignore', options: DiagnosticScope.Global }))) + .returns(() => cmdIgnore) + .verifiable(typemoq.Times.once()); await diagnosticService.handle([diagnostic]); messageHandler.verifyAll(); commandFactory.verifyAll(); expect(messagePrompt).not.be.equal(undefined, 'Message prompt not set'); - expect(messagePrompt!.commandPrompts).to.be.deep.equal([{ prompt: 'Learn more', command: cmdLearn }, { prompt: 'Download', command: cmdDownload }]); + expect(messagePrompt!.commandPrompts).to.be.deep.equal([ + { prompt: 'Learn more', command: cmdLearn }, + { prompt: 'Download', command: cmdDownload }, + { prompt: 'Do not show again', command: cmdIgnore } + ]); + }); + test('Should not display a message if No Interpreters diagnostic has been ignored', async () => { + const diagnostic = new InvalidMacPythonInterpreterDiagnostic(DiagnosticCodes.MacInterpreterSelectedAndNoOtherInterpretersDiagnostic, undefined); + + filterService.setup(f => f.shouldIgnoreDiagnostic(typemoq.It.isValue(DiagnosticCodes.MacInterpreterSelectedAndNoOtherInterpretersDiagnostic))) + .returns(() => Promise.resolve(true)) + .verifiable(typemoq.Times.once()); + commandFactory.setup(f => f.createCommand(typemoq.It.isAny(), typemoq.It.isAny())) + .verifiable(typemoq.Times.never()); + messageHandler.setup(f => f.handle(typemoq.It.isAny(), typemoq.It.isAny())) + .verifiable(typemoq.Times.never()); + + await diagnosticService.handle([diagnostic]); + + messageHandler.verifyAll(); + filterService.verifyAll(); + commandFactory.verifyAll(); }); }); From 07ca967390b35cf9ded452e9762929b14c657d4c Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Mon, 18 Mar 2019 16:26:33 -0700 Subject: [PATCH 2/3] Create 4448.md --- news/1 Enhancements/4448.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 news/1 Enhancements/4448.md diff --git a/news/1 Enhancements/4448.md b/news/1 Enhancements/4448.md new file mode 100644 index 000000000000..da0911cbba19 --- /dev/null +++ b/news/1 Enhancements/4448.md @@ -0,0 +1,2 @@ +Add button to ignore the message warning about the use of the macOS system install of Python. +(thanks [Alina Lobastova](https://github.com/alina7091)) From df5996df6e2c381f6f25f04c9b0b713bcfb94852 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Wed, 20 Mar 2019 10:11:28 -0700 Subject: [PATCH 3/3] Added ignore to another prompt --- .../diagnostics/checks/macPythonInterpreter.ts | 7 +++++++ .../checks/macPythonInterpreter.unit.test.ts | 12 ++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/client/application/diagnostics/checks/macPythonInterpreter.ts b/src/client/application/diagnostics/checks/macPythonInterpreter.ts index 0e7c4f50b1bb..aa910bdd773d 100644 --- a/src/client/application/diagnostics/checks/macPythonInterpreter.ts +++ b/src/client/application/diagnostics/checks/macPythonInterpreter.ts @@ -153,6 +153,13 @@ export class InvalidMacPythonInterpreterService extends BaseDiagnosticsService { type: 'executeVSCCommand', options: 'python.setInterpreter' }) + }, + { + prompt: 'Do not show again', + command: commandFactory.createCommand(diagnostic, { + type: 'ignore', + options: DiagnosticScope.Global + }) } ]; } diff --git a/src/test/application/diagnostics/checks/macPythonInterpreter.unit.test.ts b/src/test/application/diagnostics/checks/macPythonInterpreter.unit.test.ts index f6ff9eef898a..2e770486f48d 100644 --- a/src/test/application/diagnostics/checks/macPythonInterpreter.unit.test.ts +++ b/src/test/application/diagnostics/checks/macPythonInterpreter.unit.test.ts @@ -263,6 +263,7 @@ suite('Application Diagnostics - Checks Python Interpreter', () => { test('Handling no interpreters diagnostic should return select interpreter cmd', async () => { const diagnostic = new InvalidMacPythonInterpreterDiagnostic(DiagnosticCodes.MacInterpreterSelectedAndHaveOtherInterpretersDiagnostic, undefined); const cmd = {} as any as IDiagnosticCommand; + const cmdIgnore = {} as any as IDiagnosticCommand; let messagePrompt: MessageCommandPrompt | undefined; messageHandler .setup(i => i.handle(typemoq.It.isValue(diagnostic), typemoq.It.isAny())) @@ -273,13 +274,20 @@ suite('Application Diagnostics - Checks Python Interpreter', () => { typemoq.It.isObjectWith>({ type: 'executeVSCCommand' }))) .returns(() => cmd) .verifiable(typemoq.Times.once()); + commandFactory.setup(f => f.createCommand(typemoq.It.isAny(), + typemoq.It.isObjectWith>({ type: 'ignore', options: DiagnosticScope.Global }))) + .returns(() => cmdIgnore) + .verifiable(typemoq.Times.once()); await diagnosticService.handle([diagnostic]); messageHandler.verifyAll(); commandFactory.verifyAll(); expect(messagePrompt).not.be.equal(undefined, 'Message prompt not set'); - expect(messagePrompt!.commandPrompts).to.be.deep.equal([{ prompt: 'Select Python Interpreter', command: cmd }]); + expect(messagePrompt!.commandPrompts).to.be.deep.equal([ + { prompt: 'Select Python Interpreter', command: cmd }, + { prompt: 'Do not show again', command: cmdIgnore } + ]); }); test('Handling no interpreters diagnostisc should return 3 commands', async () => { const diagnostic = new InvalidMacPythonInterpreterDiagnostic(DiagnosticCodes.MacInterpreterSelectedAndNoOtherInterpretersDiagnostic, undefined); @@ -347,7 +355,7 @@ suite('Application Diagnostics - Checks Python Interpreter', () => { test('Event Handler is registered and invoked', async () => { let invoked = false; let callbackHandler!: (e: ConfigurationChangeEvent) => Promise; - const workspaceService = { onDidChangeConfiguration: (cb : (e: ConfigurationChangeEvent) => Promise) => callbackHandler = cb } as any; + const workspaceService = { onDidChangeConfiguration: (cb: (e: ConfigurationChangeEvent) => Promise) => callbackHandler = cb } as any; const serviceContainerObject = createContainer(); serviceContainer.setup(s => s.get(typemoq.It.isValue(IWorkspaceService))) .returns(() => workspaceService);