From bdcfb12ef20a206cf5f45965ea5dccff58f314b3 Mon Sep 17 00:00:00 2001 From: Ryan Tam Date: Sat, 17 Jun 2023 14:30:56 +0100 Subject: [PATCH] Add suppress error iff auto formatting on save config --- CHANGELOG.md | 1 + docs/changelog.md | 1 + schema/settings.json | 10 ++++ src/formatter.ts | 70 ++++++++++++++++------- src/index.ts | 12 +++- test_snippets/test_with_errors.ipynb | 83 ++++++++++++++++++++++++++++ 6 files changed, 154 insertions(+), 23 deletions(-) create mode 100644 test_snippets/test_with_errors.ipynb diff --git a/CHANGELOG.md b/CHANGELOG.md index 49c74d8..4601a89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ **Jupyterlab extension** - Add "Go to cell" option in dialog when formatting fails; +- Add "suppressFormatterErrorsIFFAutoFormatOnSave" config; ## 2.2.1 2023-05-21 diff --git a/docs/changelog.md b/docs/changelog.md index 49c74d8..4601a89 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -5,6 +5,7 @@ **Jupyterlab extension** - Add "Go to cell" option in dialog when formatting fails; +- Add "suppressFormatterErrorsIFFAutoFormatOnSave" config; ## 2.2.1 2023-05-21 diff --git a/schema/settings.json b/schema/settings.json index 7af5657..f5d3c03 100644 --- a/schema/settings.json +++ b/schema/settings.json @@ -313,6 +313,10 @@ "suppressFormatterErrors": { "additionalProperties": false, "type": "boolean" + }, + "suppressFormatterErrorsIFFAutoFormatOnSave": { + "additionalProperties": false, + "type": "boolean" } }, "properties": { @@ -415,6 +419,12 @@ "description": "Whether to suppress all errors reported by formatter while formatting. Useful when you have format on save mode on.", "$ref": "#/definitions/suppressFormatterErrors", "default": false + }, + "suppressFormatterErrorsIFFAutoFormatOnSave": { + "title": "Suppress formatter errors if and only if auto saving.", + "description": "Whether to suppress all errors reported by formatter while formatting (if and only if auto saving). Useful when you have format on save mode on and still want to see error when manually formatting.", + "$ref": "#/definitions/suppressFormatterErrorsIFFAutoFormatOnSave", + "default": false } }, "additionalProperties": false, diff --git a/src/formatter.ts b/src/formatter.ts index bfaa0c8..9c5ba28 100644 --- a/src/formatter.ts +++ b/src/formatter.ts @@ -5,6 +5,10 @@ import { IEditorTracker } from '@jupyterlab/fileeditor'; import { Widget } from '@lumino/widgets'; import { showErrorMessage, Dialog, showDialog } from '@jupyterlab/apputils'; +type Context = { + saving: boolean; +}; + class JupyterlabCodeFormatter { working = false; protected client: JupyterlabCodeFormatterClient; @@ -46,7 +50,7 @@ export class JupyterlabNotebookCodeFormatter extends JupyterlabCodeFormatter { } public async formatAction(config: any, formatter?: string) { - return this.formatCells(true, config, formatter); + return this.formatCells(true, config, { saving: false }, formatter); } public async formatSelectedCodeCells( @@ -54,15 +58,22 @@ export class JupyterlabNotebookCodeFormatter extends JupyterlabCodeFormatter { formatter?: string, notebook?: Notebook ) { - return this.formatCells(true, config, formatter, notebook); + return this.formatCells( + true, + config, + { saving: false }, + formatter, + notebook + ); } public async formatAllCodeCells( config: any, + context: Context, formatter?: string, notebook?: Notebook ) { - return this.formatCells(false, config, formatter, notebook); + return this.formatCells(false, config, context, formatter, notebook); } private getCodeCells(selectedOnly = true, notebook?: Notebook): CodeCell[] { @@ -87,7 +98,7 @@ export class JupyterlabNotebookCodeFormatter extends JupyterlabCodeFormatter { } const metadata = - this.notebookTracker.currentWidget.content.model!.sharedModel.metadata;; + this.notebookTracker.currentWidget.content.model!.sharedModel.metadata; if (!metadata) { return null; @@ -142,13 +153,16 @@ export class JupyterlabNotebookCodeFormatter extends JupyterlabCodeFormatter { private async applyFormatters( selectedCells: CodeCell[], formattersToUse: string[], - config: any + config: any, + context: Context ) { for (const formatterToUse of formattersToUse) { if (formatterToUse === 'noop' || formatterToUse === 'skip') { continue; } - const currentTexts = selectedCells.map(cell => cell.model.sharedModel.source); + const currentTexts = selectedCells.map( + cell => cell.model.sharedModel.source + ); const formattedTexts = await this.formatCode( currentTexts, formatterToUse, @@ -156,29 +170,37 @@ export class JupyterlabNotebookCodeFormatter extends JupyterlabCodeFormatter { true, config.cacheFormatters ); + console.log(config.suppressFormatterErrorsIFFAutoFormatOnSave, context.saving); - const showErrors = !(config.suppressFormatterErrors ?? false); + const showErrors = + !(config.suppressFormatterErrors ?? false) && + !( + (config.suppressFormatterErrorsIFFAutoFormatOnSave ?? false) && + context.saving + ); for (let i = 0; i < selectedCells.length; ++i) { const cell = selectedCells[i]; const currentText = currentTexts[i]; const formattedText = formattedTexts.code[i]; - const cellValueHasNotChanged = cell.model.sharedModel.source === currentText; + const cellValueHasNotChanged = + cell.model.sharedModel.source === currentText; if (cellValueHasNotChanged) { if (formattedText.error) { if (showErrors) { - const result = await showDialog( - { - title: 'Jupyterlab Code Formatter Error', - body: formattedText.error, - buttons: [ - Dialog.createButton({label: 'Go to cell', actions: ['revealError']}), - Dialog.okButton({ label: 'Dismiss' }), - ] - } - ) + const result = await showDialog({ + title: 'Jupyterlab Code Formatter Error', + body: formattedText.error, + buttons: [ + Dialog.createButton({ + label: 'Go to cell', + actions: ['revealError'] + }), + Dialog.okButton({ label: 'Dismiss' }) + ] + }); if (result.button.actions.indexOf('revealError') !== -1) { - this.notebookTracker.currentWidget!.content.scrollToCell(cell) - break + this.notebookTracker.currentWidget!.content.scrollToCell(cell); + break; } } } else { @@ -199,6 +221,7 @@ export class JupyterlabNotebookCodeFormatter extends JupyterlabCodeFormatter { private async formatCells( selectedOnly: boolean, config: any, + context: Context, formatter?: string, notebook?: Notebook ) { @@ -214,7 +237,12 @@ export class JupyterlabNotebookCodeFormatter extends JupyterlabCodeFormatter { } const formattersToUse = await this.getFormattersToUse(config, formatter); - await this.applyFormatters(selectedCells, formattersToUse, config); + await this.applyFormatters( + selectedCells, + formattersToUse, + config, + context + ); } catch (error) { await showErrorMessage('Jupyterlab Code Formatter Error', error); } diff --git a/src/index.ts b/src/index.ts index a409983..bed1838 100644 --- a/src/index.ts +++ b/src/index.ts @@ -80,6 +80,7 @@ class JupyterLabCodeFormatter onClick: async () => { await this.notebookCodeFormatter.formatAllCodeCells( this.config, + { saving: false }, undefined, nb.content ); @@ -103,7 +104,12 @@ class JupyterLabCodeFormatter state: DocumentRegistry.SaveState ) { if (state === 'started' && this.config.formatOnSave) { - await this.notebookCodeFormatter.formatAllCodeCells(this.config); + await this.notebookCodeFormatter.formatAllCodeCells( + this.config, + { saving: true }, + undefined, + undefined + ); } } @@ -143,7 +149,9 @@ class JupyterLabCodeFormatter }); this.app.commands.addCommand(Constants.FORMAT_ALL_COMMAND, { execute: async () => { - await this.notebookCodeFormatter.formatAllCodeCells(this.config); + await this.notebookCodeFormatter.formatAllCodeCells(this.config, { + saving: false + }); }, iconClass: Constants.ICON_FORMAT_ALL, iconLabel: 'Format notebook' diff --git a/test_snippets/test_with_errors.ipynb b/test_snippets/test_with_errors.ipynb new file mode 100644 index 0000000..04dad4a --- /dev/null +++ b/test_snippets/test_with_errors.ipynb @@ -0,0 +1,83 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "95cc4d6e-9fa2-493c-af98-83b1b88df0c6", + "metadata": {}, + "outputs": [], + "source": [ + "ddd =" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4e6159ec-e287-4a22-b76e-9fc5f012a6d4", + "metadata": {}, + "outputs": [], + "source": [ + "hello = 42" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "41a699a0-0480-4d36-ae81-d06a6cc074b4", + "metadata": {}, + "outputs": [], + "source": [ + "fff =" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "804c67fe-6c33-4590-9616-57db0497b1eb", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "411369a5-160e-472f-befa-25c82b836a61", + "metadata": {}, + "outputs": [], + "source": [ + "hello = 42" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2c20f1d6-7b8b-4083-819d-d0daef945d23", + "metadata": {}, + "outputs": [], + "source": [ + "fff2 =" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}