Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions news/2 Fixes/6273.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add error messages if data_rate_limit is exceeded on remote (or local) connection.
3 changes: 1 addition & 2 deletions news/announce.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,7 @@ def complete_news(version, entry, previous_news):
title, _, previous_news = previous_news.partition("\n")
title = title.strip()
previous_news = previous_news.strip()
section_title = (f"## {version} ({datetime.date.today().strftime('%d %B %Y')})"
).replace("(0", "(")
section_title = f"## {version} ({datetime.date.today().strftime('%d %B %Y')})"
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ericsnowcurrently @DonJayamanne I had to back out this change that Eric made. It was failing as soon as the day of the month switched to single digits.

This was causing all of the unit tests to fail
https://dev.azure.com/ms/vscode-python/_build/results?buildId=22894

# TODO: Insert the "Thank you!" section (in monthly releases)?
return f"{title}\n\n{section_title}\n\n{entry.strip()}\n\n\n{previous_news}"

Expand Down
3 changes: 2 additions & 1 deletion package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -277,5 +277,6 @@
"DataScience.imageListLabel": "Image",
"DataScience.exportImageFailed": "Error exporting image: {0}",
"downloading.file": "Downloading {0}...",
"downloading.file.progress": "{0}{1} of {2} KB ({3})"
"downloading.file.progress": "{0}{1} of {2} KB ({3})",
"DataScience.jupyterDataRateExceeded": "Cannot view variable because your data rate is set too low. Please restart your server with a data rate limit like so `--NotebookApp.iopub_data_rate_limit=10000000000.0`"
}
1 change: 1 addition & 0 deletions src/client/common/utils/localize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ export namespace DataScience {
export const selectedImageListLabel = localize('DataScience.selectedImageListLabel', 'Selected Image');
export const imageListLabel = localize('DataScience.imageListLabel', 'Image');
export const exportImageFailed = localize('DataScience.exportImageFailed', 'Error exporting image: {0}');
export const jupyterDataRateExceeded = localize('DataScience.jupyterDataRateExceeded', 'Cannot view variable because your data rate is set too low. Please restart your server with a data rate limit like so `--NotebookApp.iopub_data_rate_limit=10000000000.0`');
}

export namespace DebugConfigStrings {
Expand Down
1 change: 1 addition & 0 deletions src/client/datascience/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ export enum Telemetry {

export namespace HelpLinks {
export const PythonInteractiveHelpLink = 'https://aka.ms/pyaiinstall';
export const JupyterDataRateHelpLink = 'https://aka.ms/AA5ggm0'; // This redirects here: https://jupyter-notebook.readthedocs.io/en/stable/config.html
}

export namespace Settings {
Expand Down
34 changes: 23 additions & 11 deletions src/client/datascience/data-viewing/dataViewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import * as localize from '../../common/utils/localize';
import { noop } from '../../common/utils/misc';
import { StopWatch } from '../../common/utils/stopWatch';
import { sendTelemetryEvent } from '../../telemetry';
import { Telemetry } from '../constants';
import { HelpLinks, Telemetry } from '../constants';
import { JupyterDataRateLimitError } from '../jupyter/jupyterDataRateLimitError';
import { ICodeCssGenerator, IDataViewer, IJupyterVariable, IJupyterVariables, IThemeFinder } from '../types';
import { WebViewHost } from '../webViewHost';
import { DataViewerMessageListener } from './dataViewerMessageListener';
Expand Down Expand Up @@ -107,31 +108,42 @@ export class DataViewer extends WebViewHost<IDataViewerMapping> implements IData
}

private async getAllRows() {
try {
return this.wrapRequest(async () => {
if (this.variable && this.variable.rowCount) {
const allRows = await this.variableManager.getDataFrameRows(this.variable, 0, this.variable.rowCount);
this.pendingRowsCount = 0;
return this.postMessage(DataViewerMessages.GetAllRowsResponse, allRows);
}
} catch (e) {
traceError(e);
this.applicationShell.showErrorMessage(e);
} finally {
this.sendElapsedTimeTelemetry();
}
});
}

private async getRowChunk(request: IGetRowsRequest) {
try {
private getRowChunk(request: IGetRowsRequest) {
return this.wrapRequest(async () => {
if (this.variable && this.variable.rowCount) {
const rows = await this.variableManager.getDataFrameRows(this.variable, request.start, Math.min(request.end, this.variable.rowCount));
return this.postMessage(DataViewerMessages.GetRowsResponse, { rows, start: request.start, end: request.end });
}
});
}

private async wrapRequest(func: () => Promise<void>) {
try {
return await func();
} catch (e) {
if (e instanceof JupyterDataRateLimitError) {
traceError(e);
const actionTitle = localize.DataScience.pythonInteractiveHelpLink();
this.applicationShell.showErrorMessage(e.toString(), actionTitle).then(v => {
// User clicked on the link, open it.
if (v === actionTitle) {
this.applicationShell.openUrl(HelpLinks.JupyterDataRateHelpLink);
}
});
this.dispose();
}
traceError(e);
this.applicationShell.showErrorMessage(e);
} finally {
this.pendingRowsCount = Math.min(0, this.pendingRowsCount - request.end);
this.sendElapsedTimeTelemetry();
}
}
Expand Down
10 changes: 10 additions & 0 deletions src/client/datascience/jupyter/jupyterDataRateLimitError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
'use strict';
import * as localize from '../../common/utils/localize';

export class JupyterDataRateLimitError extends Error {
constructor() {
super(localize.DataScience.jupyterDataRateExceeded());
}
}
12 changes: 12 additions & 0 deletions src/client/datascience/jupyter/jupyterVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import * as localize from '../../common/utils/localize';
import { EXTENSION_ROOT_DIR } from '../../constants';
import { Identifiers } from '../constants';
import { ICell, IInteractiveWindowProvider, IJupyterExecution, IJupyterVariable, IJupyterVariables } from '../types';
import { JupyterDataRateLimitError } from './jupyterDataRateLimitError';

@injectable()
export class JupyterVariables implements IJupyterVariables {
Expand Down Expand Up @@ -142,6 +143,17 @@ export class JupyterVariables implements IJupyterVariables {
const codeCell = cells[0].data as nbformat.ICodeCell;
if (codeCell.outputs.length > 0) {
const codeCellOutput = codeCell.outputs[0] as nbformat.IOutput;
if (codeCellOutput && codeCellOutput.output_type === 'stream' && codeCellOutput.name === 'stderr' && codeCellOutput.hasOwnProperty('text')) {
const resultString = codeCellOutput.text as string;
// See if this the IOPUB data rate limit problem
if (resultString.includes('iopub_data_rate_limit')) {
throw new JupyterDataRateLimitError();
} else {
const error = localize.DataScience.jupyterGetVariablesExecutionError().format(resultString);
traceError(error);
throw new Error(error);
}
}
if (codeCellOutput && codeCellOutput.output_type === 'stream' && codeCellOutput.hasOwnProperty('text')) {
const resultString = codeCellOutput.text as string;
return JSON.parse(resultString) as T;
Expand Down
1 change: 1 addition & 0 deletions src/datascience-ui/react-common/settingsReactSide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ function load() {
codeRegularExpression: '^(#\\s*%%|#\\s*\\<codecell\\>|#\\s*In\\[\\d*?\\]|#\\s*In\\[ \\])',
showJupyterVariableExplorer: true,
variableExplorerExclude: 'module;builtin_function_or_method',
enablePlotViewer: true,
extraSettings: {
editorCursor: 'line',
editorCursorBlink: 'blink',
Expand Down
3 changes: 2 additions & 1 deletion src/test/datascience/color.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ suite('Theme colors', () => {
showJupyterVariableExplorer: true,
variableExplorerExclude: 'module;builtin_function_or_method',
codeRegularExpression: '^(#\\s*%%|#\\s*\\<codecell\\>|#\\s*In\\[\\d*?\\]|#\\s*In\\[ \\])',
markdownRegularExpression: '^(#\\s*%%\\s*\\[markdown\\]|#\\s*\\<markdowncell\\>)'
markdownRegularExpression: '^(#\\s*%%\\s*\\[markdown\\]|#\\s*\\<markdowncell\\>)',
enablePlotViewer: true
};
configService = TypeMoq.Mock.ofType<IConfigurationService>();
configService.setup(x => x.getSettings(TypeMoq.It.isAny())).returns(() => settings);
Expand Down
3 changes: 2 additions & 1 deletion src/test/datascience/dataScienceIocContainer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,8 @@ export class DataScienceIocContainer extends UnitTestIocContainer {
showJupyterVariableExplorer: true,
variableExplorerExclude: 'module;builtin_function_or_method',
liveShareConnectionTimeout: 100,
autoPreviewNotebooksInInteractivePane: true
autoPreviewNotebooksInInteractivePane: true,
enablePlotViewer: true
};

const workspaceConfig: TypeMoq.IMock<WorkspaceConfiguration> = TypeMoq.Mock.ofType<WorkspaceConfiguration>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ suite('DataScience Code Watcher Unit Tests', () => {
variableExplorerExclude: 'module;builtin_function_or_method',
codeRegularExpression: '^(#\\s*%%|#\\s*\\<codecell\\>|#\\s*In\\[\\d*?\\]|#\\s*In\\[ \\])',
markdownRegularExpression: '^(#\\s*%%\\s*\\[markdown\\]|#\\s*\\<markdowncell\\>)',
enableCellCodeLens: true
enableCellCodeLens: true,
enablePlotViewer: true
};

// Setup the service container to return code watchers
Expand Down
3 changes: 2 additions & 1 deletion src/test/datascience/execution.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,8 @@ suite('Jupyter Execution', async () => {
variableExplorerExclude: 'module;builtin_function_or_method',
codeRegularExpression: '^(#\\s*%%|#\\s*\\<codecell\\>|#\\s*In\\[\\d*?\\]|#\\s*In\\[ \\])',
markdownRegularExpression: '^(#\\s*%%\\s*\\[markdown\\]|#\\s*\\<markdowncell\\>)',
allowLiveShare: false
allowLiveShare: false,
enablePlotViewer: true
};

// Service container also needs to generate jupyter servers. However we can't use a mock as that messes up returning
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ suite('Interactive window command listener', async () => {
variableExplorerExclude: 'module;builtin_function_or_method',
codeRegularExpression: '^(#\\s*%%|#\\s*\\<codecell\\>|#\\s*In\\[\\d*?\\]|#\\s*In\\[ \\])',
markdownRegularExpression: '^(#\\s*%%\\s*\\[markdown\\]|#\\s*\\<markdowncell\\>)',
autoPreviewNotebooksInInteractivePane: true
autoPreviewNotebooksInInteractivePane: true,
enablePlotViewer: true
};

when(knownSearchPaths.getSearchPaths()).thenReturn(['/foo/bar']);
Expand Down
3 changes: 2 additions & 1 deletion src/test/datascience/interactiveWindowTestHelpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,8 @@ export function defaultDataScienceSettings(): IDataScienceSettings {
showJupyterVariableExplorer: true,
variableExplorerExclude: 'module;builtin_function_or_method',
codeRegularExpression: '^(#\\s*%%|#\\s*\\<codecell\\>|#\\s*In\\[\\d*?\\]|#\\s*In\\[ \\])',
markdownRegularExpression: '^(#\\s*%%\\s*\\[markdown\\]|#\\s*\\<markdowncell\\>)'
markdownRegularExpression: '^(#\\s*%%\\s*\\[markdown\\]|#\\s*\\<markdowncell\\>)',
enablePlotViewer: true
};
}

Expand Down
1 change: 1 addition & 0 deletions src/test/datascience/mockJupyterManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export class MockJupyterManager implements IJupyterSessionManager {
this.kernelSpecs.push({name: '0e8519db-0895-416c-96df-fa80131ecea0', dir: 'C:\\Users\\rchiodo\\AppData\\Roaming\\jupyter\\kernels\\0e8519db-0895-416c-96df-fa80131ecea0'});

// Setup our default cells that happen for everything
this.addCell(CodeSnippits.MatplotLibInitSvg);
this.addCell(CodeSnippits.MatplotLibInitPng);
this.addCell('matplotlib.style.use(\'dark_background\')');
this.addCell(`matplotlib.rcParams.update(${Identifiers.MatplotLibDefaultParams})`);
Expand Down