From f7ad067f28b3eadb880bd48d3047963439edde5f Mon Sep 17 00:00:00 2001 From: David Kutugata Date: Tue, 4 Feb 2020 10:54:18 -0800 Subject: [PATCH 01/30] Davidkutu/ds interactive window focus fix (#9895) * Fixed the focus on the interactive window when pressing ctrl +2 * the new prop 'focusPending' needs to change in order to give focus * added functional test * In test: force focus to buttons to take it away from * finished the functional test * updated changelog * deleted bug#.md --- CHANGELOG.md | 2 + .../history-react/interactiveCell.tsx | 2 + .../history-react/interactivePanel.tsx | 2 + .../interactive-common/cellInput.tsx | 2 + .../interactive-common/code.tsx | 7 +++ .../native-editor/nativeCell.tsx | 2 + .../native-editor/nativeEditor.tsx | 1 + .../datascience/dataScienceIocContainer.ts | 22 ++++----- .../interactiveWindow.functional.test.tsx | 46 ++++++++++++++++++- src/test/datascience/testHelpers.tsx | 2 +- 10 files changed, 75 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d4db6e73ea4..37d7cb8328bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,8 @@ ### Fixes +1. Fixed the focus on the interactive window when pressing ctrl + 1/ ctrl + 2 + ([#9693](https://github.com/microsoft/vscode-python/issues/9693)) 1. Fix variable explorer in Interactive and Notebook editors from interfering with execution. ([#5980](https://github.com/Microsoft/vscode-python/issues/5980)) 1. Fix a crash when using pytest to discover doctests with unknown line number. diff --git a/src/datascience-ui/history-react/interactiveCell.tsx b/src/datascience-ui/history-react/interactiveCell.tsx index 8329fcf7867a..a32cfb087634 100644 --- a/src/datascience-ui/history-react/interactiveCell.tsx +++ b/src/datascience-ui/history-react/interactiveCell.tsx @@ -40,6 +40,7 @@ interface IInteractiveCellBaseProps { editorMeasureClassName?: string; font: IFont; settings: IDataScienceExtraSettings; + focusPending: number; } type IInteractiveCellProps = IInteractiveCellBaseProps & typeof actionCreators; @@ -266,6 +267,7 @@ export class InteractiveCell extends React.Component { keyDown={this.isEditCell() ? this.onEditCellKeyDown : undefined} showLineNumbers={this.props.cellVM.showLineNumbers} font={this.props.font} + focusPending={this.props.focusPending} /> ); } diff --git a/src/datascience-ui/history-react/interactivePanel.tsx b/src/datascience-ui/history-react/interactivePanel.tsx index 7ce18dd0759d..6c7aa04b3f5f 100644 --- a/src/datascience-ui/history-react/interactivePanel.tsx +++ b/src/datascience-ui/history-react/interactivePanel.tsx @@ -216,6 +216,7 @@ export class InteractivePanel extends React.Component { monacoTheme={this.props.monacoTheme} font={this.props.font} settings={this.props.settings} + focusPending={this.props.activateCount} /> @@ -279,6 +280,7 @@ export class InteractivePanel extends React.Component { monacoTheme={this.props.monacoTheme} font={this.props.font} settings={this.props.settings} + focusPending={this.props.activateCount} /> diff --git a/src/datascience-ui/interactive-common/cellInput.tsx b/src/datascience-ui/interactive-common/cellInput.tsx index 5ff000057b6f..744fba7dcde6 100644 --- a/src/datascience-ui/interactive-common/cellInput.tsx +++ b/src/datascience-ui/interactive-common/cellInput.tsx @@ -26,6 +26,7 @@ interface ICellInputProps { editorMeasureClassName?: string; showLineNumbers?: boolean; font: IFont; + focusPending: number; onCodeChange(changes: monacoEditor.editor.IModelContentChange[], cellId: string, modelId: string): void; onCodeCreated(code: string, file: string, cellId: string, modelId: string): void; openLink(uri: monacoEditor.Uri): void; @@ -110,6 +111,7 @@ export class CellInput extends React.Component { showLineNumbers={this.props.showLineNumbers} useQuickEdit={this.props.cellVM.useQuickEdit} font={this.props.font} + focusPending={this.props.focusPending} /> ); diff --git a/src/datascience-ui/interactive-common/code.tsx b/src/datascience-ui/interactive-common/code.tsx index 2159047cb11a..4294a22fa343 100644 --- a/src/datascience-ui/interactive-common/code.tsx +++ b/src/datascience-ui/interactive-common/code.tsx @@ -26,6 +26,7 @@ export interface ICodeProps { font: IFont; hasFocus: boolean; cursorPos: CursorPos; + focusPending: number; onCreated(code: string, modelId: string): void; onChange(changes: monacoEditor.editor.IModelContentChange[], modelId: string): void; openLink(uri: monacoEditor.Uri): void; @@ -46,6 +47,12 @@ export class Code extends React.Component { this.state = { allowWatermark: true }; } + public componentDidUpdate(prevProps: ICodeProps) { + if (prevProps.focusPending !== this.props.focusPending) { + this.giveFocus(CursorPos.Current); + } + } + public render() { const readOnly = this.props.readOnly; const waterMarkClass = this.props.showWatermark && this.state.allowWatermark && !readOnly ? 'code-watermark' : 'hide'; diff --git a/src/datascience-ui/native-editor/nativeCell.tsx b/src/datascience-ui/native-editor/nativeCell.tsx index c3158de886b9..9414c2c8b3e9 100644 --- a/src/datascience-ui/native-editor/nativeCell.tsx +++ b/src/datascience-ui/native-editor/nativeCell.tsx @@ -42,6 +42,7 @@ interface INativeCellBaseProps { enableGather: boolean | undefined; editorOptions: monacoEditor.editor.IEditorOptions; themeMatplotlibPlots: boolean | undefined; + focusPending: number; } type INativeCellProps = INativeCellBaseProps & typeof actionCreators; @@ -597,6 +598,7 @@ export class NativeCell extends React.Component { keyDown={this.keyDownInput} showLineNumbers={this.props.cellVM.showLineNumbers} font={this.props.font} + focusPending={this.props.focusPending} /> ); diff --git a/src/datascience-ui/native-editor/nativeEditor.tsx b/src/datascience-ui/native-editor/nativeEditor.tsx index d099dc1136e1..f57998de1d8b 100644 --- a/src/datascience-ui/native-editor/nativeEditor.tsx +++ b/src/datascience-ui/native-editor/nativeEditor.tsx @@ -396,6 +396,7 @@ export class NativeEditor extends React.Component { editorOptions={this.props.editorOptions} enableGather={this.props.settings.enableGather} themeMatplotlibPlots={this.props.settings.themeMatplotlibPlots} + focusPending={this.props.activateCount} /> {lastLine} diff --git a/src/test/datascience/dataScienceIocContainer.ts b/src/test/datascience/dataScienceIocContainer.ts index 203ca7b6a742..ff30d3e10c2e 100644 --- a/src/test/datascience/dataScienceIocContainer.ts +++ b/src/test/datascience/dataScienceIocContainer.ts @@ -898,17 +898,7 @@ export class DataScienceIocContainer extends UnitTestIocContainer { } } - private findPythonPath(): string { - try { - // Give preference to the CI test python (could also be set in launch.json for debugging). - const output = child_process.execFileSync(process.env.CI_PYTHON_PATH || 'python', ['-c', 'import sys;print(sys.executable)'], { encoding: 'utf8' }); - return output.replace(/\r?\n/g, ''); - } catch (ex) { - return 'python'; - } - } - - private postMessageToWebPanel(msg: any) { + public postMessageToWebPanel(msg: any) { if (this.webPanelListener) { this.webPanelListener.onMessage(msg.type, msg.payload); } else { @@ -923,6 +913,16 @@ export class DataScienceIocContainer extends UnitTestIocContainer { } } + private findPythonPath(): string { + try { + // Give preference to the CI test python (could also be set in launch.json for debugging). + const output = child_process.execFileSync(process.env.CI_PYTHON_PATH || 'python', ['-c', 'import sys;print(sys.executable)'], { encoding: 'utf8' }); + return output.replace(/\r?\n/g, ''); + } catch (ex) { + return 'python'; + } + } + private mountReactControl(mount: () => ReactWrapper, React.Component>) { // This is a remount (or first time). Clear out messages that were sent // by the last mount diff --git a/src/test/datascience/interactiveWindow.functional.test.tsx b/src/test/datascience/interactiveWindow.functional.test.tsx index 6eb58ef0d44d..eaa78876de64 100644 --- a/src/test/datascience/interactiveWindow.functional.test.tsx +++ b/src/test/datascience/interactiveWindow.functional.test.tsx @@ -26,7 +26,7 @@ import { defaultDataScienceSettings } from './helpers'; import { addCode, getInteractiveCellResults, getOrCreateInteractiveWindow, runMountedTest } from './interactiveWindowTestHelpers'; import { MockDocumentManager } from './mockDocumentManager'; import { MockEditor } from './mockTextEditor'; -import { waitForUpdate } from './reactHelpers'; +import { createMessageEvent, waitForUpdate } from './reactHelpers'; import { addContinuousMockData, addInputMockData, @@ -36,9 +36,12 @@ import { enterInput, escapePath, findButton, + getInteractiveEditor, getLastOutputCell, srcDirectory, + submitInput, toggleCellExpansion, + typeCode, verifyHtmlOnCell, verifyLastCellInputState, waitForMessage, @@ -143,6 +146,47 @@ suite('DataScience Interactive Window output tests', () => { } ); + runMountedTest( + 'Ctrl + 1/Ctrl + 2', + async wrapper => { + // Create an interactive window so that it listens to the results. + const interactiveWindow = await getOrCreateInteractiveWindow(ioc); + await interactiveWindow.show(); + + // Type in the input box + const editor = getInteractiveEditor(wrapper); + typeCode(editor, 'a=1\na'); + + // Give focus to a random div + const reactDiv = wrapper + .find('div') + .first() + .getDOMNode(); + + const domDiv = reactDiv.querySelector('div'); + + if (domDiv && ioc.postMessage) { + domDiv.tabIndex = -1; + domDiv.focus(); + + // send the ctrl + 1/2 message, this should put focus back on the input box + const message = createMessageEvent({ type: InteractiveWindowMessages.Activate, payload: undefined }); + ioc.postMessage(message); + + // Then enter press shift + enter on the active element + const activeElement = document.activeElement; + if (activeElement) { + await submitInput(ioc, activeElement as HTMLTextAreaElement); + } + } + + verifyHtmlOnCell(wrapper, 'InteractiveCell', '1', CellPosition.Last); + }, + () => { + return ioc; + } + ); + runMountedTest( 'Collapse / expand cell', async wrapper => { diff --git a/src/test/datascience/testHelpers.tsx b/src/test/datascience/testHelpers.tsx index 805e8d2a5745..3ba826d55c8a 100644 --- a/src/test/datascience/testHelpers.tsx +++ b/src/test/datascience/testHelpers.tsx @@ -471,7 +471,7 @@ export function simulateKey(domNode: HTMLTextAreaElement, key: string, shiftDown } } -async function submitInput(ioc: DataScienceIocContainer, textArea: HTMLTextAreaElement): Promise { +export async function submitInput(ioc: DataScienceIocContainer, textArea: HTMLTextAreaElement): Promise { // Get a render promise with the expected number of renders (how many updates a the shift + enter will cause) // Should be 6 - 1 for the shift+enter and 5 for the new cell. const renderPromise = waitForMessage(ioc, InteractiveWindowMessages.ExecutionRendered); From 15d40c453cf1971c362d556fa581b2a3032882dd Mon Sep 17 00:00:00 2001 From: Rich Chiodo Date: Tue, 4 Feb 2020 14:18:58 -0800 Subject: [PATCH 02/30] Fix variables on mac and linux (#9897) (#9903) * Fix regexes to work on other platforms * Fix data frame viewer * Fix linter problems Co-authored-by: Don Jayamanne Co-authored-by: Don Jayamanne --- .../datascience/jupyter/jupyterVariables.ts | 12 +++---- .../data-explorer/globalJQueryImports.ts | 24 ++++++++++++++ .../data-explorer/reactSlickGrid.tsx | 31 ++++++++++++------- 3 files changed, 50 insertions(+), 17 deletions(-) create mode 100644 src/datascience-ui/data-explorer/globalJQueryImports.ts diff --git a/src/client/datascience/jupyter/jupyterVariables.ts b/src/client/datascience/jupyter/jupyterVariables.ts index 5f199e175f7d..cff731c78e20 100644 --- a/src/client/datascience/jupyter/jupyterVariables.ts +++ b/src/client/datascience/jupyter/jupyterVariables.ts @@ -23,11 +23,11 @@ import { JupyterDataRateLimitError } from './jupyterDataRateLimitError'; // Regexes for parsing data from Python kernel. Not sure yet if other // kernels will add the ansi encoding. -const TypeRegex = /\u001b\[1;31mType:\u001b\[0m\s+(\w+)/; -const ValueRegex = /\u001b\[1;31mValue:\u001b\[0m\s+(.*)/; -const StringFormRegex = /\u001b\[1;31mString form:\u001b\[0m\s+([\s\S]+?)\n\u001b\[1/; -const DocStringRegex = /\u001b\[1;31mDocstring:\u001b\[0m\s+(.*)/; -const CountRegex = /\u001b\[1;31mLength:\u001b\[0m\s+(.*)/; +const TypeRegex = /.*?\[.*?;31mType:.*?\[0m\s+(\w+)/; +const ValueRegex = /.*?\[.*?;31mValue:.*?\[0m\s+(.*)/; +const StringFormRegex = /.*?\[.*?;31mString form:.*?\[0m\s+([\s\S]+?)\n.*?\[.*?/; +const DocStringRegex = /.*?\[.*?;31mDocstring:.*?\[0m\s+(.*)/; +const CountRegex = /.*?\[.*?;31mLength:.*?\[0m\s+(.*)/; const ShapeRegex = /^\s+\[(\d+) rows x (\d+) columns\]/m; const DataViewableTypes: Set = new Set(['DataFrame', 'list', 'dict', 'np.array', 'Series']); @@ -99,7 +99,7 @@ export class JupyterVariables implements IJupyterVariables { } // Prep our targetVariable to send over - const variableString = JSON.stringify(targetVariable).replace('\\n', '\\\\n'); + const variableString = JSON.stringify(targetVariable).replace(/\\n/g, '\\\\n'); // Setup a regex const regexPattern = extraReplacements.length === 0 ? '_VSCode_JupyterTestValue' : ['_VSCode_JupyterTestValue', ...extraReplacements.map(v => v.key)].join('|'); diff --git a/src/datascience-ui/data-explorer/globalJQueryImports.ts b/src/datascience-ui/data-explorer/globalJQueryImports.ts new file mode 100644 index 000000000000..d3bfae0a054b --- /dev/null +++ b/src/datascience-ui/data-explorer/globalJQueryImports.ts @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +'use strict'; + +/* +This file exists for the sole purpose of ensuring jQuery and slickgrid load in the right sequence. +We need to first load jquery into window.jQuery. +After that we need to load slickgrid, and then the jQuery plugin from slickgrid event.drag. +*/ + +// Slickgrid requires jquery to be defined. Globally. So we do some hacks here. +// We need to manipulate the grid with the same jquery that it uses +// use slickgridJQ instead of the usual $ to make it clear that we need that JQ and not +// the one currently in node-modules + +// tslint:disable-next-line: no-var-requires no-require-imports +require('expose-loader?jQuery!slickgrid/lib/jquery-1.11.2.min'); + +// tslint:disable-next-line: no-var-requires no-require-imports +require('slickgrid/lib/jquery-1.11.2.min'); + +// tslint:disable-next-line: no-var-requires no-require-imports +require('expose-loader?jQuery.fn.drag!slickgrid/lib/jquery.event.drag-2.3.0'); diff --git a/src/datascience-ui/data-explorer/reactSlickGrid.tsx b/src/datascience-ui/data-explorer/reactSlickGrid.tsx index 9f839a1d0f96..15f3d3a84cd6 100644 --- a/src/datascience-ui/data-explorer/reactSlickGrid.tsx +++ b/src/datascience-ui/data-explorer/reactSlickGrid.tsx @@ -7,29 +7,38 @@ import * as ReactDOM from 'react-dom'; import { MaxStringCompare } from '../../client/datascience/data-viewing/types'; import { KeyCodes } from '../react-common/constants'; import { measureText } from '../react-common/textMeasure'; +import './globalJQueryImports'; import { ReactSlickGridFilterBox } from './reactSlickGridFilterBox'; -// Slickgrid requires jquery to be defined. Globally. So we do some hacks here. -// We need to manipulate the grid with the same jquery that it uses -// use slickgridJQ instead of the usual $ to make it clear that we need that JQ and not -// the one currently in node-modules -// tslint:disable-next-line: no-var-requires no-require-imports -require('expose-loader?jQuery!slickgrid/lib/jquery-1.11.2.min'); +/* +WARNING: Do not change the order of these imports. +Slick grid MUST be imported after we load jQuery and other stuff from `./globalJQueryImports` +*/ // tslint:disable-next-line: no-var-requires no-require-imports const slickgridJQ = require('slickgrid/lib/jquery-1.11.2.min'); -// tslint:disable-next-line: no-var-requires no-require-imports -require('expose-loader?jQuery.fn.drag!slickgrid/lib/jquery.event.drag-2.3.0'); +// Adding comments to ensure order of imports does not change due to auto formatters. +// tslint:disable-next-line: ordered-imports import 'slickgrid/slick.core'; +// Adding comments to ensure order of imports does not change due to auto formatters. +// tslint:disable-next-line: ordered-imports import 'slickgrid/slick.dataview'; +// Adding comments to ensure order of imports does not change due to auto formatters. +// tslint:disable-next-line: ordered-imports import 'slickgrid/slick.grid'; - +// Adding comments to ensure order of imports does not change due to auto formatters. +// tslint:disable-next-line: ordered-imports import 'slickgrid/plugins/slick.autotooltips'; - +// Adding comments to ensure order of imports does not change due to auto formatters. +// tslint:disable-next-line: ordered-imports import 'slickgrid/slick.grid.css'; - // Make sure our css comes after the slick grid css. We override some of its styles. +// tslint:disable-next-line: ordered-imports import './reactSlickGrid.css'; +/* +WARNING: Do not change the order of these imports. +Slick grid MUST be imported after we load jQuery and other stuff from `./globalJQueryImports` +*/ const MinColumnWidth = 70; const MaxColumnWidth = 500; From 20e5ee25e1ae00d309293633366b1308b06e4eb6 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Wed, 5 Feb 2020 08:34:54 -0800 Subject: [PATCH 03/30] Fix focusing of cells when navigating cells using up/down arrow (#9885) (#9908) For #9884 --- .../native-editor/redux/reducers/effects.ts | 14 +++++++---- .../native-editor/redux/reducers/execution.ts | 23 +++++++++++-------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/datascience-ui/native-editor/redux/reducers/effects.ts b/src/datascience-ui/native-editor/redux/reducers/effects.ts index 65d35324431a..ba0c901ba81b 100644 --- a/src/datascience-ui/native-editor/redux/reducers/effects.ts +++ b/src/datascience-ui/native-editor/redux/reducers/effects.ts @@ -126,12 +126,18 @@ export namespace Effects { return arg.prevState; } - export function selectCell(arg: NativeEditorReducerArg): IMainState { + /** + * Select a cell. + * + * @param {boolean} [shouldFocusCell] If provided, then will control the focus behavior of the cell. (defaults to focus state of previously selected cell). + */ + export function selectCell(arg: NativeEditorReducerArg, shouldFocusCell?: boolean): IMainState { // Skip doing anything if already selected. if (arg.payload.cellId !== arg.prevState.selectedCellId) { let prevState = arg.prevState; const addIndex = prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.cellId); - + const anotherCellWasFocusedAndSelected = typeof prevState.focusedCellId === 'string' && prevState.focusedCellId === prevState.selectedCellId; + const shouldSetFocusToCell = typeof shouldFocusCell === 'boolean' ? shouldFocusCell : anotherCellWasFocusedAndSelected; // First find the old focused cell and unfocus it let removeFocusIndex = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.prevState.focusedCellId); if (removeFocusIndex < 0) { @@ -149,7 +155,7 @@ export namespace Effects { if (addIndex >= 0 && arg.payload.cellId !== prevState.selectedCellId) { newVMs[addIndex] = { ...newVMs[addIndex], - focused: prevState.focusedCellId !== undefined && prevState.focusedCellId === prevState.selectedCellId, + focused: shouldSetFocusToCell, selected: true, cursorPos: arg.payload.cursorPos }; @@ -158,7 +164,7 @@ export namespace Effects { return { ...prevState, cellVMs: newVMs, - focusedCellId: prevState.focusedCellId !== undefined ? arg.payload.cellId : undefined, + focusedCellId: shouldSetFocusToCell ? arg.payload.cellId : undefined, selectedCellId: arg.payload.cellId }; } diff --git a/src/datascience-ui/native-editor/redux/reducers/execution.ts b/src/datascience-ui/native-editor/redux/reducers/execution.ts index 86be83ac613a..0accb65b8923 100644 --- a/src/datascience-ui/native-editor/redux/reducers/execution.ts +++ b/src/datascience-ui/native-editor/redux/reducers/execution.ts @@ -77,17 +77,20 @@ export namespace Execution { case 'select': // Select the cell below this one, but don't focus it if (index < arg.prevState.cellVMs.length - 1) { - return Effects.selectCell({ - ...arg, - prevState: { - ...executeResult + return Effects.selectCell( + { + ...arg, + prevState: { + ...executeResult + }, + payload: { + ...arg.payload, + cellId: arg.prevState.cellVMs[index + 1].cell.id, + cursorPos: CursorPos.Current + } }, - payload: { - ...arg.payload, - cellId: arg.prevState.cellVMs[index + 1].cell.id, - cursorPos: CursorPos.Current - } - }); + false + ); } return executeResult; From d2b3f153ae5670b61ba648cbf9c00644c115d7df Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Wed, 5 Feb 2020 08:35:15 -0800 Subject: [PATCH 04/30] Disable webHostNotebook experiment and fix name of exp (#9894) (#9907) Disable an experiment Fix name of an existing experiment --- experiments.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/experiments.json b/experiments.json index 6c221fae003b..d894c4e3d239 100644 --- a/experiments.json +++ b/experiments.json @@ -79,7 +79,7 @@ "max": 24 }, { - "name": "UseTerminalToGetActivatedEnvVars - enabled", + "name": "UseTerminalToGetActivatedEnvVars - experiment", "salt": "UseTerminalToGetActivatedEnvVars", "min": 0, "max": 20 @@ -105,13 +105,13 @@ { "name": "WebHostNotebook - experiment", "salt": "WebHostNotebook", - "max": 20, + "max": 0, "min": 0 }, { "name": "WebHostNotebook - control", "salt": "WebHostNotebook", - "min": 80, + "min": 0, "max": 100 } ] From 9f5ac3f519406ad644684e1cd63671cd796819aa Mon Sep 17 00:00:00 2001 From: David Kutugata Date: Wed, 5 Feb 2020 10:04:02 -0800 Subject: [PATCH 05/30] Davidkutu/ds scrapbook render fix (#9912) * check if we support mimetypes before loading html to avoid crashing * Silently skip rendering of the scapbook mime types * added news file * updated changelog and deleted news file --- CHANGELOG.md | 3 +++ src/datascience-ui/interactive-common/cellOutput.tsx | 7 +++++-- src/datascience-ui/interactive-common/transforms.tsx | 5 +++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37d7cb8328bf..bcdbb6a4e472 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,9 @@ ### Fixes +1. Removed unnecessary warning when executing cells that use Scrapbook, + Fix an html crash when using not supported mime types + ([#9796](https://github.com/microsoft/vscode-python/issues/9796)) 1. Fixed the focus on the interactive window when pressing ctrl + 1/ ctrl + 2 ([#9693](https://github.com/microsoft/vscode-python/issues/9693)) 1. Fix variable explorer in Interactive and Notebook editors from interfering with execution. diff --git a/src/datascience-ui/interactive-common/cellOutput.tsx b/src/datascience-ui/interactive-common/cellOutput.tsx index 046d28999d54..d3236bc8e394 100644 --- a/src/datascience-ui/interactive-common/cellOutput.tsx +++ b/src/datascience-ui/interactive-common/cellOutput.tsx @@ -14,7 +14,7 @@ import { ImageButton } from '../react-common/imageButton'; import { getLocString } from '../react-common/locReactSide'; import { fixLatexEquations } from './latexManipulation'; import { ICellViewModel } from './mainState'; -import { getRichestMimetype, getTransform } from './transforms'; +import { getRichestMimetype, getTransform, isMimeTypeSupported } from './transforms'; // tslint:disable-next-line: no-var-requires no-require-imports const ansiToHtml = require('ansi-to-html'); @@ -380,7 +380,7 @@ export class CellOutput extends React.Component { let mimetype = transformed.mimeType; // If that worked, use the transform - if (mimetype) { + if (mimetype && isMimeTypeSupported(mimetype)) { // Get the matching React.Component for that mimetype const Transform = getTransform(mimetype); @@ -405,6 +405,9 @@ export class CellOutput extends React.Component { ); } + } else if (mimetype.startsWith('application/scrapbook.scrap.')) { + // Silently skip rendering of these mime types, render an empty div so the user sees the cell was executed. + buffer.push(
); } else { if (transformed.data) { const keys = Object.keys(transformed.data); diff --git a/src/datascience-ui/interactive-common/transforms.tsx b/src/datascience-ui/interactive-common/transforms.tsx index 2dc7cc51c33b..d4b3a86d511a 100644 --- a/src/datascience-ui/interactive-common/transforms.tsx +++ b/src/datascience-ui/interactive-common/transforms.tsx @@ -151,3 +151,8 @@ export async function forceLoad() { // Used for tests to make sure we don't end up with 'Loading ...' anywhere in a test await Promise.all(mimeTypeToImport.map(m => m.getComponent())); } + +export function isMimeTypeSupported(mimeType: string): Boolean { + const match = mimeTypeToImport.find(m => m.mimeType === mimeType); + return match ? true : false; +} From 8d7636ef5b0f66c334592200d0eb4c09358feef3 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Wed, 5 Feb 2020 16:27:37 -0800 Subject: [PATCH 06/30] Disable the terminal activation experiment (#9937) Disable until next release of VSC (for hidden terminals). Disabled because a terminal gets displayed to the user and then hidden (doesn't happen in insiders, we will need to wait for their new API to hide terms) --- experiments.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/experiments.json b/experiments.json index d894c4e3d239..3a079c054049 100644 --- a/experiments.json +++ b/experiments.json @@ -82,12 +82,12 @@ "name": "UseTerminalToGetActivatedEnvVars - experiment", "salt": "UseTerminalToGetActivatedEnvVars", "min": 0, - "max": 20 + "max": 0 }, { "name": "UseTerminalToGetActivatedEnvVars - control", "salt": "UseTerminalToGetActivatedEnvVars", - "min": 20, + "min": 0, "max": 100 }, { From 88052769782b541deb44620aecc1c78c30aad7ac Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Wed, 5 Feb 2020 16:32:35 -0800 Subject: [PATCH 07/30] Notebook should use kernel from metadata (#9936) For #9927 * Notebook should use kernel from metadata * Fix formatting --- .../interactive-common/interactiveBase.ts | 4 +-- .../interactive-ipynb/nativeEditor.ts | 3 +++ .../datascience/jupyter/jupyterServer.ts | 8 +++--- .../jupyter/jupyterServerWrapper.ts | 11 +++++--- .../jupyter/liveshare/hostJupyterServer.ts | 27 ++++++++++++++++--- src/client/datascience/types.ts | 2 +- 6 files changed, 43 insertions(+), 12 deletions(-) diff --git a/src/client/datascience/interactive-common/interactiveBase.ts b/src/client/datascience/interactive-common/interactiveBase.ts index f50e5986d325..7c89937cefb9 100644 --- a/src/client/datascience/interactive-common/interactiveBase.ts +++ b/src/client/datascience/interactive-common/interactiveBase.ts @@ -972,9 +972,9 @@ export abstract class InteractiveBase extends WebViewHost { // Create a new notebook if we need to. if (!this._notebook) { - this._notebook = await server.createNotebook(await this.getNotebookIdentity()); + const [uri, options] = await Promise.all([this.getNotebookIdentity(), this.getNotebookOptions()]); + this._notebook = await server.createNotebook(uri, options.metadata); if (this._notebook) { - const uri: Uri = await this.getNotebookIdentity(); this.postMessage(InteractiveWindowMessages.NotebookExecutionActivated, uri.toString()).ignoreErrors(); const statusChangeHandler = async (status: ServerStatus) => { diff --git a/src/client/datascience/interactive-ipynb/nativeEditor.ts b/src/client/datascience/interactive-ipynb/nativeEditor.ts index 1dc8d4de8b63..79bf289b00cd 100644 --- a/src/client/datascience/interactive-ipynb/nativeEditor.ts +++ b/src/client/datascience/interactive-ipynb/nativeEditor.ts @@ -84,6 +84,7 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor { private savedEvent: EventEmitter = new EventEmitter(); private metadataUpdatedEvent: EventEmitter = new EventEmitter(); private loadedPromise: Deferred = createDeferred(); + private contentsLoadedPromise: Deferred = createDeferred(); private _file: Uri = Uri.file(''); private _dirty: boolean = false; private isPromptingToSaveToDisc: boolean = false; @@ -299,6 +300,7 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor { public async getNotebookOptions(): Promise { const options = await this.ipynbProvider.getNotebookOptions(); + await this.contentsLoadedPromise.promise; const metadata = this.notebookJson.metadata; return { ...options, @@ -587,6 +589,7 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor { if (json) { this.notebookJson = json; } + this.contentsLoadedPromise.resolve(); // Extract cells from the json const cells = contents ? (json.cells as (nbformat.ICodeCell | nbformat.IRawCell | nbformat.IMarkdownCell)[]) : []; diff --git a/src/client/datascience/jupyter/jupyterServer.ts b/src/client/datascience/jupyter/jupyterServer.ts index 2bff18b24a28..df0621010fe5 100644 --- a/src/client/datascience/jupyter/jupyterServer.ts +++ b/src/client/datascience/jupyter/jupyterServer.ts @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. 'use strict'; +import { nbformat } from '@jupyterlab/coreutils'; import * as uuid from 'uuid/v4'; import { Disposable, Uri } from 'vscode'; import { CancellationToken } from 'vscode-jsonrpc'; @@ -39,7 +40,7 @@ export class JupyterServerBase implements INotebookServer { _liveShare: ILiveShareApi, private asyncRegistry: IAsyncDisposableRegistry, private disposableRegistry: IDisposableRegistry, - private configService: IConfigurationService, + protected readonly configService: IConfigurationService, private sessionManagerFactory: IJupyterSessionManagerFactory, private loggers: INotebookExecutionLogger[] ) { @@ -77,7 +78,7 @@ export class JupyterServerBase implements INotebookServer { this.savedSession = session; } - public createNotebook(resource: Uri, cancelToken?: CancellationToken): Promise { + public createNotebook(resource: Uri, notebookMetadata?: nbformat.INotebookMetadata, cancelToken?: CancellationToken): Promise { if (!this.sessionManager) { throw new Error(localize.DataScience.sessionDisposed()); } @@ -86,7 +87,7 @@ export class JupyterServerBase implements INotebookServer { this.savedSession = undefined; // Create a notebook and return it. - return this.createNotebookInstance(resource, this.sessionManager, savedSession, this.disposableRegistry, this.configService, this.loggers, cancelToken); + return this.createNotebookInstance(resource, this.sessionManager, savedSession, this.disposableRegistry, this.configService, this.loggers, notebookMetadata, cancelToken); } public async shutdown(): Promise { @@ -187,6 +188,7 @@ export class JupyterServerBase implements INotebookServer { _disposableRegistry: IDisposableRegistry, _configService: IConfigurationService, _loggers: INotebookExecutionLogger[], + _notebookMetadata?: nbformat.INotebookMetadata, _cancelToken?: CancellationToken ): Promise { throw new Error('You forgot to override createNotebookInstance'); diff --git a/src/client/datascience/jupyter/jupyterServerWrapper.ts b/src/client/datascience/jupyter/jupyterServerWrapper.ts index 7a0d7efb3b40..eb0347801cf1 100644 --- a/src/client/datascience/jupyter/jupyterServerWrapper.ts +++ b/src/client/datascience/jupyter/jupyterServerWrapper.ts @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. 'use strict'; +import { nbformat } from '@jupyterlab/coreutils'; import { inject, injectable, multiInject, optional } from 'inversify'; import * as uuid from 'uuid/v4'; import { Uri } from 'vscode'; @@ -12,6 +13,7 @@ import { IFileSystem } from '../../common/platform/types'; import { IAsyncDisposableRegistry, IConfigurationService, IDisposableRegistry } from '../../common/types'; import { IInterpreterService } from '../../interpreter/contracts'; import { IConnection, IDataScience, IJupyterSessionManagerFactory, INotebook, INotebookExecutionLogger, INotebookServer, INotebookServerLaunchInfo } from '../types'; +import { KernelSelector } from './kernels/kernelSelector'; import { GuestJupyterServer } from './liveshare/guestJupyterServer'; import { HostJupyterServer } from './liveshare/hostJupyterServer'; import { IRoleBasedObject, RoleBasedFactory } from './liveshare/roleBasedFactory'; @@ -32,6 +34,7 @@ type JupyterServerClassType = { loggers: INotebookExecutionLogger[], appShell: IApplicationShell, fs: IFileSystem, + kernelSelector: KernelSelector, interpreterService: IInterpreterService ): IJupyterServerInterface; }; @@ -57,7 +60,8 @@ export class JupyterServerWrapper implements INotebookServer, ILiveShareHasRole @multiInject(INotebookExecutionLogger) @optional() loggers: INotebookExecutionLogger[] | undefined, @inject(IApplicationShell) appShell: IApplicationShell, @inject(IFileSystem) fs: IFileSystem, - @inject(IInterpreterService) interpreterService: IInterpreterService + @inject(IInterpreterService) interpreterService: IInterpreterService, + @inject(KernelSelector) kernelSelector: KernelSelector ) { // The server factory will create the appropriate HostJupyterServer or GuestJupyterServer based on // the liveshare state. @@ -75,6 +79,7 @@ export class JupyterServerWrapper implements INotebookServer, ILiveShareHasRole loggers ? loggers : [], appShell, fs, + kernelSelector, interpreterService ); } @@ -93,9 +98,9 @@ export class JupyterServerWrapper implements INotebookServer, ILiveShareHasRole return server.connect(launchInfo, cancelToken); } - public async createNotebook(resource: Uri): Promise { + public async createNotebook(resource: Uri, notebookMetadata?: nbformat.INotebookMetadata, cancelToken?: CancellationToken): Promise { const server = await this.serverFactory.get(); - return server.createNotebook(resource); + return server.createNotebook(resource, notebookMetadata, cancelToken); } public async shutdown(): Promise { diff --git a/src/client/datascience/jupyter/liveshare/hostJupyterServer.ts b/src/client/datascience/jupyter/liveshare/hostJupyterServer.ts index e4e1cfc79d8e..cec3de412ca8 100644 --- a/src/client/datascience/jupyter/liveshare/hostJupyterServer.ts +++ b/src/client/datascience/jupyter/liveshare/hostJupyterServer.ts @@ -8,6 +8,7 @@ import * as vscode from 'vscode'; import { CancellationToken } from 'vscode-jsonrpc'; import * as vsls from 'vsls/vscode'; +import { nbformat } from '@jupyterlab/coreutils'; import { IApplicationShell, ILiveShareApi, IWorkspaceService } from '../../../common/application/types'; import { traceInfo } from '../../../common/logger'; import { IFileSystem } from '../../../common/platform/types'; @@ -25,6 +26,7 @@ import { INotebookServerLaunchInfo } from '../../types'; import { JupyterServerBase } from '../jupyterServer'; +import { KernelSelector } from '../kernels/kernelSelector'; import { HostJupyterNotebook } from './hostJupyterNotebook'; import { LiveShareParticipantHost } from './liveShareParticipantMixin'; import { IRoleBasedObject } from './roleBasedFactory'; @@ -46,7 +48,8 @@ export class HostJupyterServer extends LiveShareParticipantHost(JupyterServerBas private workspaceService: IWorkspaceService, loggers: INotebookExecutionLogger[], private appService: IApplicationShell, - private fs: IFileSystem + private fs: IFileSystem, + private readonly kernelSelector: KernelSelector ) { super(liveShare, asyncRegistry, disposableRegistry, configService, sessionManager, loggers); } @@ -86,7 +89,7 @@ export class HostJupyterServer extends LiveShareParticipantHost(JupyterServerBas const uri = vscode.Uri.parse(args[0]); const resource = uri.scheme && uri.scheme !== Identifiers.InteractiveWindowIdentityScheme ? this.finishedApi!.convertSharedUriToLocal(uri) : uri; // Don't return the notebook. We don't want it to be serialized. We just want its live share server to be started. - const notebook = (await this.createNotebook(resource, cancellation)) as HostJupyterNotebook; + const notebook = (await this.createNotebook(resource, undefined, cancellation)) as HostJupyterNotebook; await notebook.onAttach(api); }); @@ -137,6 +140,7 @@ export class HostJupyterServer extends LiveShareParticipantHost(JupyterServerBas disposableRegistry: IDisposableRegistry, configService: IConfigurationService, loggers: INotebookExecutionLogger[], + notebookMetadata?: nbformat.INotebookMetadata, cancelToken?: CancellationToken ): Promise { // See if already exists. @@ -159,8 +163,25 @@ export class HostJupyterServer extends LiveShareParticipantHost(JupyterServerBas throw this.getDisposedError(); } + // Find a kernel that can be used. + // Do this only if kernel information has been provided in the metadata, else use the default. + let defaultKernelInfoToUse = launchInfo.kernelSpec; + if (notebookMetadata?.kernelspec) { + const kernelInfo = await (launchInfo.connectionInfo.localLaunch + ? this.kernelSelector.getKernelForLocalConnection(sessionManager, notebookMetadata, false, cancelToken) + : this.kernelSelector.getKernelForRemoteConnection(sessionManager, notebookMetadata, cancelToken)); + + const kernelInfoToUse = kernelInfo?.kernelSpec || kernelInfo?.kernelModel; + if (kernelInfoToUse) { + defaultKernelInfoToUse = kernelInfoToUse; + } + if (possibleSession && kernelInfoToUse) { + await possibleSession.changeKernel(kernelInfoToUse, this.configService.getSettings().datascience.jupyterLaunchTimeout); + } + launchInfo.kernelSpec = defaultKernelInfoToUse; + } // Start a session (or use the existing one) - const session = possibleSession || (await sessionManager.startNew(launchInfo.kernelSpec, cancelToken)); + const session = possibleSession || (await sessionManager.startNew(defaultKernelInfoToUse, cancelToken)); traceInfo(`Started session ${this.id}`); if (session) { diff --git a/src/client/datascience/types.ts b/src/client/datascience/types.ts index 8a6c0f4d883b..86eb0c0fd185 100644 --- a/src/client/datascience/types.ts +++ b/src/client/datascience/types.ts @@ -81,7 +81,7 @@ export interface INotebookCompletion { export const INotebookServer = Symbol('INotebookServer'); export interface INotebookServer extends IAsyncDisposable { readonly id: string; - createNotebook(resource: Uri, cancelToken?: CancellationToken): Promise; + createNotebook(resource: Uri, notebookMetadata?: nbformat.INotebookMetadata, cancelToken?: CancellationToken): Promise; getNotebook(resource: Uri): Promise; connect(launchInfo: INotebookServerLaunchInfo, cancelToken?: CancellationToken): Promise; getConnectionInfo(): IConnection | undefined; From d022524fe3bbb60f97c22a8b0919fd1f138a0531 Mon Sep 17 00:00:00 2001 From: Ian Huff Date: Thu, 6 Feb 2020 03:13:44 -0800 Subject: [PATCH 08/30] Port server cache fix to release (#9932) --- CHANGELOG.md | 2 ++ .../datascience/jupyter/liveshare/serverCache.ts | 11 +++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bcdbb6a4e472..8efcb06c40ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,8 @@ ### Fixes +1. Use the autoStart server when available. + ([#9926](https://github.com/Microsoft/vscode-python/issues/9926)) 1. Removed unnecessary warning when executing cells that use Scrapbook, Fix an html crash when using not supported mime types ([#9796](https://github.com/microsoft/vscode-python/issues/9796)) diff --git a/src/client/datascience/jupyter/liveshare/serverCache.ts b/src/client/datascience/jupyter/liveshare/serverCache.ts index 663452536af5..b9390fd6d311 100644 --- a/src/client/datascience/jupyter/liveshare/serverCache.ts +++ b/src/client/datascience/jupyter/liveshare/serverCache.ts @@ -17,6 +17,7 @@ interface IServerData { options: INotebookServerOptions; promise: Promise; cancelSource: CancellationTokenSource; + resolved: boolean; } export class ServerCache implements IAsyncDisposable { @@ -43,7 +44,7 @@ export class ServerCache implements IAsyncDisposable { // See if the old options had the same UI setting. If not, // cancel the old - if (data && data.options.disableUI !== fixedOptions.disableUI) { + if (data && !data.resolved && data.options.disableUI !== fixedOptions.disableUI) { traceInfo('Cancelling server create as UI state has changed'); data.cancelSource.cancel(); data = undefined; @@ -55,7 +56,8 @@ export class ServerCache implements IAsyncDisposable { data = { promise: createFunction(options, cancelSource.token), options: fixedOptions, - cancelSource + cancelSource, + resolved: false }; this.cache.set(key, data); } @@ -75,6 +77,11 @@ export class ServerCache implements IAsyncDisposable { return oldDispose(); }; + // We've resolved the promise at this point + if (data) { + data.resolved = true; + } + return server; }) .catch(e => { From ed09569e6a307cf76b7b0c016933d5d0c5ec180a Mon Sep 17 00:00:00 2001 From: Rich Chiodo Date: Thu, 6 Feb 2020 08:17:11 -0800 Subject: [PATCH 09/30] Port variable restart fix (#9938) * Fix variable explorer when restarting a kernel (#9931) * Make sure to clear variable list on reset * Add news entry * Update changelog * Update changelog --- CHANGELOG.md | 4 +++- .../interactive-common/redux/reducers/variables.ts | 9 +++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8efcb06c40ac..c7888ea74c9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,8 @@ ### Fixes +1. Make sure to clear variable list on restart kernel. + ([#9740](https://github.com/Microsoft/vscode-python/issues/9740)) 1. Use the autoStart server when available. ([#9926](https://github.com/Microsoft/vscode-python/issues/9926)) 1. Removed unnecessary warning when executing cells that use Scrapbook, @@ -4966,4 +4968,4 @@ the following people who contributed code: * Added ability to view global variables, arguments, add and remove break points ## Version 0.0.3 -* Added support for debugging using PDB +* Added support for debugging using PDB \ No newline at end of file diff --git a/src/datascience-ui/interactive-common/redux/reducers/variables.ts b/src/datascience-ui/interactive-common/redux/reducers/variables.ts index f48cf215b90a..caeb3e76006d 100644 --- a/src/datascience-ui/interactive-common/redux/reducers/variables.ts +++ b/src/datascience-ui/interactive-common/redux/reducers/variables.ts @@ -22,7 +22,7 @@ type VariableReducerFunc = ReducerFunc = ReducerArg; function handleRequest(arg: VariableReducerArg): IVariableState { - const newExecutionCount = arg.payload.executionCount ? arg.payload.executionCount : arg.prevState.currentExecutionCount; + const newExecutionCount = arg.payload.executionCount !== undefined ? arg.payload.executionCount : arg.prevState.currentExecutionCount; arg.queueAction( createPostableAction(InteractiveWindowMessages.GetVariablesRequest, { executionCount: newExecutionCount, @@ -108,7 +108,12 @@ function handleResponse(arg: VariableReducerArg): IVa function handleRestarted(arg: VariableReducerArg): IVariableState { // If the variables are visible, refresh them if (arg.prevState.visible) { - return handleRequest({ ...arg, payload: { executionCount: 0, sortColumn: 'name', sortAscending: true, startIndex: 0, pageSize: arg.prevState.pageSize } }); + const result = handleRequest({ ...arg, payload: { executionCount: 0, sortColumn: 'name', sortAscending: true, startIndex: 0, pageSize: arg.prevState.pageSize } }); + return { + ...result, + currentExecutionCount: 0, + variables: [] + }; } return arg.prevState; } From 415cab44371b6758dc88ed92ac199a11a60bc17a Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 6 Feb 2020 12:40:16 -0800 Subject: [PATCH 10/30] Do not override kernels info in other notebooks (#9958) For #9951, #9950, #9949 * Do not override kernels info in other notebooks * Fixes --- .../datascience/jupyter/liveshare/hostJupyterServer.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/client/datascience/jupyter/liveshare/hostJupyterServer.ts b/src/client/datascience/jupyter/liveshare/hostJupyterServer.ts index cec3de412ca8..e893f12a0c90 100644 --- a/src/client/datascience/jupyter/liveshare/hostJupyterServer.ts +++ b/src/client/datascience/jupyter/liveshare/hostJupyterServer.ts @@ -158,10 +158,16 @@ export class HostJupyterServer extends LiveShareParticipantHost(JupyterServerBas // Otherwise create a new notebook. // First we need our launch information so we can start a new session (that's what our notebook is really) - const launchInfo = await this.waitForConnect(); + let launchInfo = await this.waitForConnect(); if (!launchInfo) { throw this.getDisposedError(); } + // Create a copy of launch info, cuz we're modifying it here. + // This launch info contains the server connection info (that could be shared across other nbs). + // However the kernel info is different. The kernel info is stored as a property of this, hence create a separate instance for each nb. + launchInfo = { + ...launchInfo + }; // Find a kernel that can be used. // Do this only if kernel information has been provided in the metadata, else use the default. From abb5d1400254c6d2ce761c6f1bc5954d9437a9e8 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 6 Feb 2020 16:03:07 -0800 Subject: [PATCH 11/30] Disables the use of a terminal to activate an environment (#9967) * Disables the use of a terminal to activate an environment * Fix tests * Fix linter --- src/client/interpreter/activation/service.ts | 10 +++++++++- src/client/interpreter/serviceRegistry.ts | 3 +-- src/test/interpreters/activation/service.unit.test.ts | 5 ++++- src/test/interpreters/serviceRegistry.unit.test.ts | 3 +-- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/client/interpreter/activation/service.ts b/src/client/interpreter/activation/service.ts index d034cf860a71..8311f329c6cf 100644 --- a/src/client/interpreter/activation/service.ts +++ b/src/client/interpreter/activation/service.ts @@ -12,6 +12,7 @@ import { IPlatformService } from '../../common/platform/types'; import { IProcessServiceFactory } from '../../common/process/types'; import { ITerminalHelper, TerminalShellType } from '../../common/terminal/types'; import { ICurrentProcess, IDisposable, Resource } from '../../common/types'; +import { cacheResourceSpecificInterpreterData, clearCachedResourceSpecificIngterpreterData } from '../../common/utils/decorators'; import { OSType } from '../../common/utils/platform'; import { IEnvironmentVariablesProvider } from '../../common/variables/types'; import { EXTENSION_ROOT_DIR } from '../../constants'; @@ -21,6 +22,7 @@ import { PythonInterpreter } from '../contracts'; import { IEnvironmentActivationService } from './types'; const getEnvironmentPrefix = 'e8b39361-0157-4923-80e1-22d70d46dee6'; +const cacheDuration = 10 * 60 * 1000; export const getEnvironmentTimeout = 30000; // The shell under which we'll execute activation scripts. @@ -40,13 +42,16 @@ export class EnvironmentActivationService implements IEnvironmentActivationServi @inject(IProcessServiceFactory) private processServiceFactory: IProcessServiceFactory, @inject(ICurrentProcess) private currentProcess: ICurrentProcess, @inject(IEnvironmentVariablesProvider) private readonly envVarsService: IEnvironmentVariablesProvider - ) {} + ) { + this.envVarsService.onDidEnvironmentVariablesChange(this.onDidEnvironmentVariablesChange, this, this.disposables); + } public dispose(): void { this.disposables.forEach(d => d.dispose()); } @traceDecorators.verbose('getActivatedEnvironmentVariables', LogOptions.Arguments) @captureTelemetry(EventName.PYTHON_INTERPRETER_ACTIVATION_ENVIRONMENT_VARIABLES, { failed: false }, true) + @cacheResourceSpecificInterpreterData('ActivatedEnvironmentVariables', cacheDuration) public async getActivatedEnvironmentVariables(resource: Resource, interpreter?: PythonInterpreter, allowExceptions?: boolean): Promise { const shellInfo = defaultShells[this.platform.osType]; if (!shellInfo) { @@ -110,6 +115,9 @@ export class EnvironmentActivationService implements IEnvironmentActivationServi } } } + protected onDidEnvironmentVariablesChange(affectedResource: Resource) { + clearCachedResourceSpecificIngterpreterData('ActivatedEnvironmentVariables', affectedResource); + } protected fixActivationCommands(commands: string[]): string[] { // Replace 'source ' with '. ' as that works in shell exec return commands.map(cmd => cmd.replace(/^source\s+/, '. ')); diff --git a/src/client/interpreter/serviceRegistry.ts b/src/client/interpreter/serviceRegistry.ts index 71c029716122..cb98ed4484f9 100644 --- a/src/client/interpreter/serviceRegistry.ts +++ b/src/client/interpreter/serviceRegistry.ts @@ -9,7 +9,6 @@ import { PreWarmActivatedEnvironmentVariables } from './activation/preWarmVariab import { EnvironmentActivationService } from './activation/service'; import { TerminalEnvironmentActivationService } from './activation/terminalEnvironmentActivationService'; import { IEnvironmentActivationService } from './activation/types'; -import { WrapperEnvironmentActivationService } from './activation/wrapperEnvironmentActivationService'; import { InterpreterAutoSelectionService } from './autoSelection/index'; import { InterpreterAutoSeletionProxyService } from './autoSelection/proxy'; import { CachedInterpretersAutoSelectionRule } from './autoSelection/rules/cached'; @@ -155,5 +154,5 @@ export function registerTypes(serviceManager: IServiceManager) { serviceManager.addSingleton(IInterpreterAutoSeletionProxyService, InterpreterAutoSeletionProxyService); serviceManager.addSingleton(EnvironmentActivationService, EnvironmentActivationService); serviceManager.addSingleton(TerminalEnvironmentActivationService, TerminalEnvironmentActivationService); - serviceManager.addSingleton(IEnvironmentActivationService, WrapperEnvironmentActivationService); + serviceManager.addSingleton(IEnvironmentActivationService, EnvironmentActivationService); } diff --git a/src/test/interpreters/activation/service.unit.test.ts b/src/test/interpreters/activation/service.unit.test.ts index 293d510c7af6..d01db1f13565 100644 --- a/src/test/interpreters/activation/service.unit.test.ts +++ b/src/test/interpreters/activation/service.unit.test.ts @@ -8,7 +8,7 @@ import * as path from 'path'; import { SemVer } from 'semver'; import { anything, capture, instance, mock, verify, when } from 'ts-mockito'; import * as typemoq from 'typemoq'; -import { Uri, workspace as workspaceType, WorkspaceConfiguration } from 'vscode'; +import { EventEmitter, Uri, workspace as workspaceType, WorkspaceConfiguration } from 'vscode'; import { PlatformService } from '../../../client/common/platform/platformService'; import { IPlatformService } from '../../../client/common/platform/types'; import { CurrentProcess } from '../../../client/common/process/currentProcess'; @@ -18,6 +18,7 @@ import { IProcessService, IProcessServiceFactory } from '../../../client/common/ import { TerminalHelper } from '../../../client/common/terminal/helper'; import { ITerminalHelper } from '../../../client/common/terminal/types'; import { ICurrentProcess } from '../../../client/common/types'; +import { clearCache } from '../../../client/common/utils/cacheUtils'; import { getNamesAndValues } from '../../../client/common/utils/enum'; import { Architecture, OSType } from '../../../client/common/utils/platform'; import { EnvironmentVariablesProvider } from '../../../client/common/variables/environmentVariablesProvider'; @@ -63,6 +64,7 @@ suite('Interpreters Activation - Python Environment Variables', () => { currentProcess = mock(CurrentProcess); envVarsService = mock(EnvironmentVariablesProvider); workspace = mockedVSCodeNamespaces.workspace!; + when(envVarsService.onDidEnvironmentVariablesChange).thenReturn(new EventEmitter().event); service = new EnvironmentActivationService(instance(helper), instance(platform), instance(processServiceFactory), instance(currentProcess), instance(envVarsService)); const cfg = typemoq.Mock.ofType(); @@ -71,6 +73,7 @@ suite('Interpreters Activation - Python Environment Variables', () => { cfg.setup(c => c.inspect(typemoq.It.isValue('pythonPath'))).returns(() => { return { globalValue: 'GlobalValuepython' } as any; }); + clearCache(); } teardown(() => { mockedVSCodeNamespaces.workspace!.reset(); diff --git a/src/test/interpreters/serviceRegistry.unit.test.ts b/src/test/interpreters/serviceRegistry.unit.test.ts index ce9216a4f8db..3380aca6b296 100644 --- a/src/test/interpreters/serviceRegistry.unit.test.ts +++ b/src/test/interpreters/serviceRegistry.unit.test.ts @@ -10,7 +10,6 @@ import { IExtensionActivationService, IExtensionSingleActivationService } from ' import { EnvironmentActivationService } from '../../client/interpreter/activation/service'; import { TerminalEnvironmentActivationService } from '../../client/interpreter/activation/terminalEnvironmentActivationService'; import { IEnvironmentActivationService } from '../../client/interpreter/activation/types'; -import { WrapperEnvironmentActivationService } from '../../client/interpreter/activation/wrapperEnvironmentActivationService'; import { InterpreterAutoSelectionService } from '../../client/interpreter/autoSelection'; import { InterpreterAutoSeletionProxyService } from '../../client/interpreter/autoSelection/proxy'; import { CachedInterpretersAutoSelectionRule } from '../../client/interpreter/autoSelection/rules/cached'; @@ -146,7 +145,7 @@ suite('Interpreters - Service Registry', () => { [EnvironmentActivationService, EnvironmentActivationService], [TerminalEnvironmentActivationService, TerminalEnvironmentActivationService], - [IEnvironmentActivationService, WrapperEnvironmentActivationService], + [IEnvironmentActivationService, EnvironmentActivationService], [IExtensionActivationService, CondaInheritEnvPrompt], [WindowsStoreInterpreter, WindowsStoreInterpreter], From 3976296a648c85abb6b339ecda1fd5144e032d53 Mon Sep 17 00:00:00 2001 From: Ian Huff Date: Thu, 6 Feb 2020 16:58:22 -0800 Subject: [PATCH 12/30] Port server name fix to release (#9970) --- CHANGELOG.md | 3 ++- package.nls.json | 1 + src/client/common/utils/localize.ts | 1 + .../interactive-common/kernelSelection.tsx | 27 ++++++++++++++----- .../interactive-common/redux/store.ts | 4 +-- 5 files changed, 26 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c7888ea74c9b..0ac937fbe82e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,7 +46,8 @@ ([#9701](https://github.com/Microsoft/vscode-python/issues/9701)) ### Fixes - +1. Correct the server and kernel text for when not connected to a server. + ([#9933](https://github.com/Microsoft/vscode-python/issues/9933)) 1. Make sure to clear variable list on restart kernel. ([#9740](https://github.com/Microsoft/vscode-python/issues/9740)) 1. Use the autoStart server when available. diff --git a/package.nls.json b/package.nls.json index 8eb3ccb1584b..a70fc4d71a7d 100644 --- a/package.nls.json +++ b/package.nls.json @@ -307,6 +307,7 @@ "DataScience.noRowsInDataViewer": "No rows match current filter", "DataScience.jupyterServer": "Jupyter Server", "DataScience.noKernel": "No Kernel", + "DataScience.serverNotStarted": "Not Started", "DataScience.localJupyterServer": "local", "DataScience.pandasTooOldForViewingFormat": "Python package 'pandas' is version {0}. Version 0.20 or greater is required for viewing data.", "DataScience.pandasRequiredForViewing": "Python package 'pandas' is required for viewing data.", diff --git a/src/client/common/utils/localize.ts b/src/client/common/utils/localize.ts index 427551a6bd55..56d85b0211bc 100644 --- a/src/client/common/utils/localize.ts +++ b/src/client/common/utils/localize.ts @@ -336,6 +336,7 @@ export namespace DataScience { export const noRowsInDataViewer = localize('DataScience.noRowsInDataViewer', 'No rows match current filter'); export const jupyterServer = localize('DataScience.jupyterServer', 'Jupyter Server'); export const noKernel = localize('DataScience.noKernel', 'No Kernel'); + export const serverNotStarted = localize('DataScience.serverNotStarted', 'Not Started'); export const selectKernel = localize('DataScience.selectKernel', 'Select a Kernel'); export const selectDifferentKernel = localize('DataScience.selectDifferentKernel', 'Select a different Kernel'); export const selectDifferentJupyterInterpreter = localize('DataScience.selectDifferentJupyterInterpreter', 'Select a different Interpreter'); diff --git a/src/datascience-ui/interactive-common/kernelSelection.tsx b/src/datascience-ui/interactive-common/kernelSelection.tsx index 374cbd6bc34f..066ca42c8b29 100644 --- a/src/datascience-ui/interactive-common/kernelSelection.tsx +++ b/src/datascience-ui/interactive-common/kernelSelection.tsx @@ -41,9 +41,7 @@ export class KernelSelection extends React.Component { const displayNameTextWidth: React.CSSProperties = { maxWidth: this.getMaxWidth(displayNameTextSize) }; - const kernelSelectionClass = this.isKernelSelectionAllowed - ? 'kernel-status-section kernel-status-section-hoverable kernel-status-status' - : 'kernel-status-section kernel-status-status'; + return (
@@ -53,19 +51,34 @@ export class KernelSelection extends React.Component {
-
- {this.props.kernel.displayName}: {this.props.kernel.jupyterServerStatus} -
+ {this.renderKernelStatus(displayNameTextWidth)}
); } + + private renderKernelStatus(displayNameTextWidth: React.CSSProperties) { + if (this.isKernelSelectionAllowed) { + return ( +
+ {this.props.kernel.displayName}: {this.props.kernel.jupyterServerStatus} +
+ ); + } else { + return ( +
+ {getLocString('DataScience.noKernel', 'No Kernel')} +
+ ); + } + } + private selectKernel() { if (this.isKernelSelectionAllowed) { this.props.selectKernel(); } } private getIcon(): ImageName { - return this.props.kernel.localizedUri === getLocString('DataScience.noKernel', 'No Kernel') ? ImageName.JupyterServerDisconnected : ImageName.JupyterServerConnected; + return this.props.kernel.jupyterServerStatus === ServerStatus.NotStarted ? ImageName.JupyterServerDisconnected : ImageName.JupyterServerConnected; } private getMaxWidth(charLenght: number): string { diff --git a/src/datascience-ui/interactive-common/redux/store.ts b/src/datascience-ui/interactive-common/redux/store.ts index 4e35c159d567..70737eea68db 100644 --- a/src/datascience-ui/interactive-common/redux/store.ts +++ b/src/datascience-ui/interactive-common/redux/store.ts @@ -46,8 +46,8 @@ function generateDefaultState(skipDefault: boolean, testMode: boolean, baseTheme monacoReady: testMode, // When testing, monaco starts out ready loaded: false, kernel: { - displayName: 'Python', - localizedUri: getLocString('DataScience.noKernel', 'No Kernel'), + displayName: getLocString('DataScience.noKernel', 'No Kernel'), + localizedUri: getLocString('DataScience.serverNotStarted', 'Not Started'), jupyterServerStatus: ServerStatus.NotStarted }, settings: testMode ? getDefaultSettings() : undefined, // When testing, we don't send (or wait) for the real settings. From 4946e5c8df9d40d398fc71b191ee3ca0699242a8 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 6 Feb 2020 17:26:03 -0800 Subject: [PATCH 13/30] When starting Jupyter activate conda env (#9972) * If interpreter is provided use that to check if is conda environment * Fix tests For #9973 Currently conda isn't getting activated when auto starting Jupyter server. --- src/client/common/terminal/helper.ts | 2 +- src/test/common/terminals/helper.unit.test.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/client/common/terminal/helper.ts b/src/client/common/terminal/helper.ts index b353ce76ecf7..6404711551eb 100644 --- a/src/client/common/terminal/helper.ts +++ b/src/client/common/terminal/helper.ts @@ -93,7 +93,7 @@ export class TerminalHelper implements ITerminalHelper { } // If we have a conda environment, then use that. - const isCondaEnvironment = await this.condaService.isCondaEnvironment(settings.pythonPath); + const isCondaEnvironment = interpreter ? interpreter.type === InterpreterType.Conda : await this.condaService.isCondaEnvironment(settings.pythonPath); if (isCondaEnvironment) { const activationCommands = interpreter ? await this.conda.getActivationCommandsForInterpreter(interpreter.path, terminalShellType) diff --git a/src/test/common/terminals/helper.unit.test.ts b/src/test/common/terminals/helper.unit.test.ts index 6e6a64126a0a..23740deb68cb 100644 --- a/src/test/common/terminals/helper.unit.test.ts +++ b/src/test/common/terminals/helper.unit.test.ts @@ -327,8 +327,8 @@ suite('Terminal Service helpers', () => { expect(cmd).to.equal(undefined, 'Command must be undefined'); verify(pythonSettings.terminal).once(); - verify(pythonSettings.pythonPath).once(); - verify(condaService.isCondaEnvironment(pythonPath)).once(); + verify(pythonSettings.pythonPath).times(interpreter ? 0 : 1); + verify(condaService.isCondaEnvironment(pythonPath)).times(interpreter ? 0 : 1); verify(bashActivationProvider.isShellSupported(shellToExpect)).atLeast(1); verify(pyenvActivationProvider.isShellSupported(anything())).never(); verify(pipenvActivationProvider.isShellSupported(anything())).never(); From 3be03b0a460a673d66fa7fc8d5ffdb28d2e58917 Mon Sep 17 00:00:00 2001 From: Ian Huff Date: Fri, 7 Feb 2020 13:59:43 -0800 Subject: [PATCH 14/30] Porting K8 fix to release (#9987) --- CHANGELOG.md | 2 ++ src/client/datascience/jupyter/notebookStarter.ts | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ac937fbe82e..2c877d964761 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,8 @@ ([#9701](https://github.com/Microsoft/vscode-python/issues/9701)) ### Fixes +1. add --ip=127.0.0.1 argument of jupyter server when running in k8s container + ([#9976](https://github.com/Microsoft/vscode-python/issues/9976)) 1. Correct the server and kernel text for when not connected to a server. ([#9933](https://github.com/Microsoft/vscode-python/issues/9933)) 1. Make sure to clear variable list on restart kernel. diff --git a/src/client/datascience/jupyter/notebookStarter.ts b/src/client/datascience/jupyter/notebookStarter.ts index 3cf3ddad5727..66f98d28fcd1 100644 --- a/src/client/datascience/jupyter/notebookStarter.ts +++ b/src/client/datascience/jupyter/notebookStarter.ts @@ -211,7 +211,7 @@ export class NotebookStarter implements Disposable { // Check for a docker situation. try { const cgroup = await this.fileSystem.readFile('/proc/self/cgroup').catch(() => ''); - if (!cgroup.includes('docker')) { + if (!cgroup.includes('docker') && !cgroup.includes('kubepods')) { return args; } // We definitely need an ip address. From 36fee5cf41d0233fdf63b7005cd3e5f782169054 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Mon, 10 Feb 2020 11:32:02 -0800 Subject: [PATCH 15/30] Update version and changelog date for release (#10022) --- CHANGELOG.md | 3034 +++++++++++++++++++++++---------------------- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 1556 insertions(+), 1482 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c877d964761..f4398ffc113b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 2020.2.0-rc (3 February 2020) +## 2020.2.0 (10 February 2020) ### Enhancements @@ -42,10 +42,11 @@ 1. Update Chinese (Traditional) translation. (thanks [pan93412](https://github.com/pan93412)) ([#9548](https://github.com/Microsoft/vscode-python/issues/9548)) -1. Look for Conda interpreters in '~/opt/*conda*/' directory as well. +1. Look for Conda interpreters in '~/opt/_conda_/' directory as well. ([#9701](https://github.com/Microsoft/vscode-python/issues/9701)) ### Fixes + 1. add --ip=127.0.0.1 argument of jupyter server when running in k8s container ([#9976](https://github.com/Microsoft/vscode-python/issues/9976)) 1. Correct the server and kernel text for when not connected to a server. @@ -166,48 +167,50 @@ Thanks to the following projects which we fully rely on to provide some of our features: -- [isort](https://pypi.org/project/isort/) -- [jedi](https://pypi.org/project/jedi/) - and [parso](https://pypi.org/project/parso/) -- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) -- [ptvsd](https://pypi.org/project/ptvsd/) -- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) -- [rope](https://pypi.org/project/rope/) (user-installed) + +- [isort](https://pypi.org/project/isort/) +- [jedi](https://pypi.org/project/jedi/) + and [parso](https://pypi.org/project/parso/) +- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) +- [ptvsd](https://pypi.org/project/ptvsd/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) Also thanks to the various projects we provide integrations with which help make this extension useful: -- Debugging support: - [Django](https://pypi.org/project/Django/), - [Flask](https://pypi.org/project/Flask/), - [gevent](https://pypi.org/project/gevent/), - [Jinja](https://pypi.org/project/Jinja/), - [Pyramid](https://pypi.org/project/pyramid/), - [PySpark](https://pypi.org/project/pyspark/), - [Scrapy](https://pypi.org/project/Scrapy/), - [Watson](https://pypi.org/project/Watson/) -- Formatting: - [autopep8](https://pypi.org/project/autopep8/), - [black](https://pypi.org/project/black/), - [yapf](https://pypi.org/project/yapf/) -- Interpreter support: - [conda](https://conda.io/), - [direnv](https://direnv.net/), - [pipenv](https://pypi.org/project/pipenv/), - [pyenv](https://github.com/pyenv/pyenv), - [venv](https://docs.python.org/3/library/venv.html#module-venv), - [virtualenv](https://pypi.org/project/virtualenv/) -- Linting: - [bandit](https://pypi.org/project/bandit/), - [flake8](https://pypi.org/project/flake8/), - [mypy](https://pypi.org/project/mypy/), - [prospector](https://pypi.org/project/prospector/), - [pylint](https://pypi.org/project/pylint/), - [pydocstyle](https://pypi.org/project/pydocstyle/), - [pylama](https://pypi.org/project/pylama/) -- Testing: - [nose](https://pypi.org/project/nose/), - [pytest](https://pypi.org/project/pytest/), - [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [bandit](https://pypi.org/project/bandit/), + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) And finally thanks to the [Python](https://www.python.org/) development team and community for creating a fantastic programming language and community to be a @@ -281,7 +284,7 @@ part of! ([#7853](https://github.com/Microsoft/vscode-python/issues/7853)) 1. Fix clear_output(True) to work in notebook cells. ([#7970](https://github.com/Microsoft/vscode-python/issues/7970)) -1. Prevented '$0' from appearing inside brackets when using intellisense autocomplete. +1. Prevented '\$0' from appearing inside brackets when using intellisense autocomplete. ([#8101](https://github.com/Microsoft/vscode-python/issues/8101)) 1. Intellisense can sometimes not appear in notebooks or the interactive window, especially when something is a large list. ([#8140](https://github.com/Microsoft/vscode-python/issues/8140)) @@ -376,48 +379,50 @@ part of! Thanks to the following projects which we fully rely on to provide some of our features: -- [isort](https://pypi.org/project/isort/) -- [jedi](https://pypi.org/project/jedi/) - and [parso](https://pypi.org/project/parso/) -- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) -- [ptvsd](https://pypi.org/project/ptvsd/) -- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) -- [rope](https://pypi.org/project/rope/) (user-installed) + +- [isort](https://pypi.org/project/isort/) +- [jedi](https://pypi.org/project/jedi/) + and [parso](https://pypi.org/project/parso/) +- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) +- [ptvsd](https://pypi.org/project/ptvsd/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) Also thanks to the various projects we provide integrations with which help make this extension useful: -- Debugging support: - [Django](https://pypi.org/project/Django/), - [Flask](https://pypi.org/project/Flask/), - [gevent](https://pypi.org/project/gevent/), - [Jinja](https://pypi.org/project/Jinja/), - [Pyramid](https://pypi.org/project/pyramid/), - [PySpark](https://pypi.org/project/pyspark/), - [Scrapy](https://pypi.org/project/Scrapy/), - [Watson](https://pypi.org/project/Watson/) -- Formatting: - [autopep8](https://pypi.org/project/autopep8/), - [black](https://pypi.org/project/black/), - [yapf](https://pypi.org/project/yapf/) -- Interpreter support: - [conda](https://conda.io/), - [direnv](https://direnv.net/), - [pipenv](https://pypi.org/project/pipenv/), - [pyenv](https://github.com/pyenv/pyenv), - [venv](https://docs.python.org/3/library/venv.html#module-venv), - [virtualenv](https://pypi.org/project/virtualenv/) -- Linting: - [bandit](https://pypi.org/project/bandit/), - [flake8](https://pypi.org/project/flake8/), - [mypy](https://pypi.org/project/mypy/), - [prospector](https://pypi.org/project/prospector/), - [pylint](https://pypi.org/project/pylint/), - [pydocstyle](https://pypi.org/project/pydocstyle/), - [pylama](https://pypi.org/project/pylama/) -- Testing: - [nose](https://pypi.org/project/nose/), - [pytest](https://pypi.org/project/pytest/), - [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [bandit](https://pypi.org/project/bandit/), + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) And finally thanks to the [Python](https://www.python.org/) development team and community for creating a fantastic programming language and community to be a @@ -440,48 +445,50 @@ part of! Thanks to the following projects which we fully rely on to provide some of our features: -- [isort](https://pypi.org/project/isort/) -- [jedi](https://pypi.org/project/jedi/) - and [parso](https://pypi.org/project/parso/) -- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) -- [ptvsd](https://pypi.org/project/ptvsd/) -- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) -- [rope](https://pypi.org/project/rope/) (user-installed) + +- [isort](https://pypi.org/project/isort/) +- [jedi](https://pypi.org/project/jedi/) + and [parso](https://pypi.org/project/parso/) +- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) +- [ptvsd](https://pypi.org/project/ptvsd/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) Also thanks to the various projects we provide integrations with which help make this extension useful: -- Debugging support: - [Django](https://pypi.org/project/Django/), - [Flask](https://pypi.org/project/Flask/), - [gevent](https://pypi.org/project/gevent/), - [Jinja](https://pypi.org/project/Jinja/), - [Pyramid](https://pypi.org/project/pyramid/), - [PySpark](https://pypi.org/project/pyspark/), - [Scrapy](https://pypi.org/project/Scrapy/), - [Watson](https://pypi.org/project/Watson/) -- Formatting: - [autopep8](https://pypi.org/project/autopep8/), - [black](https://pypi.org/project/black/), - [yapf](https://pypi.org/project/yapf/) -- Interpreter support: - [conda](https://conda.io/), - [direnv](https://direnv.net/), - [pipenv](https://pypi.org/project/pipenv/), - [pyenv](https://github.com/pyenv/pyenv), - [venv](https://docs.python.org/3/library/venv.html#module-venv), - [virtualenv](https://pypi.org/project/virtualenv/) -- Linting: - [bandit](https://pypi.org/project/bandit/), - [flake8](https://pypi.org/project/flake8/), - [mypy](https://pypi.org/project/mypy/), - [prospector](https://pypi.org/project/prospector/), - [pylint](https://pypi.org/project/pylint/), - [pydocstyle](https://pypi.org/project/pydocstyle/), - [pylama](https://pypi.org/project/pylama/) -- Testing: - [nose](https://pypi.org/project/nose/), - [pytest](https://pypi.org/project/pytest/), - [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [bandit](https://pypi.org/project/bandit/), + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) And finally thanks to the [Python](https://www.python.org/) development team and community for creating a fantastic programming language and community to be a @@ -554,7 +561,7 @@ part of! ([#7873](https://github.com/Microsoft/vscode-python/issues/7873)) 1. When creating a new blank notebook, it has existing text in it already. ([#7980](https://github.com/Microsoft/vscode-python/issues/7980)) -1. Can now include a LaTeX-style equation without surrounding the equation with '$' in a markdown cell. +1. Can now include a LaTeX-style equation without surrounding the equation with '\$' in a markdown cell. ([#7992](https://github.com/Microsoft/vscode-python/issues/7992)) 1. Make a spinner appear during executing a cell. ([#8003](https://github.com/Microsoft/vscode-python/issues/8003)) @@ -652,49 +659,51 @@ part of! Thanks to the following projects which we fully rely on to provide some of our features: -- [isort](https://pypi.org/project/isort/) -- [jedi](https://pypi.org/project/jedi/) - and [parso](https://pypi.org/project/parso/) -- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) -- [ptvsd](https://pypi.org/project/ptvsd/) -- [pyparsing](https://pypi.org/project/pyparsing/) -- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) -- [rope](https://pypi.org/project/rope/) (user-installed) + +- [isort](https://pypi.org/project/isort/) +- [jedi](https://pypi.org/project/jedi/) + and [parso](https://pypi.org/project/parso/) +- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) +- [ptvsd](https://pypi.org/project/ptvsd/) +- [pyparsing](https://pypi.org/project/pyparsing/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) Also thanks to the various projects we provide integrations with which help make this extension useful: -- Debugging support: - [Django](https://pypi.org/project/Django/), - [Flask](https://pypi.org/project/Flask/), - [gevent](https://pypi.org/project/gevent/), - [Jinja](https://pypi.org/project/Jinja/), - [Pyramid](https://pypi.org/project/pyramid/), - [PySpark](https://pypi.org/project/pyspark/), - [Scrapy](https://pypi.org/project/Scrapy/), - [Watson](https://pypi.org/project/Watson/) -- Formatting: - [autopep8](https://pypi.org/project/autopep8/), - [black](https://pypi.org/project/black/), - [yapf](https://pypi.org/project/yapf/) -- Interpreter support: - [conda](https://conda.io/), - [direnv](https://direnv.net/), - [pipenv](https://pypi.org/project/pipenv/), - [pyenv](https://github.com/pyenv/pyenv), - [venv](https://docs.python.org/3/library/venv.html#module-venv), - [virtualenv](https://pypi.org/project/virtualenv/) -- Linting: - [bandit](https://pypi.org/project/bandit/), - [flake8](https://pypi.org/project/flake8/), - [mypy](https://pypi.org/project/mypy/), - [prospector](https://pypi.org/project/prospector/), - [pylint](https://pypi.org/project/pylint/), - [pydocstyle](https://pypi.org/project/pydocstyle/), - [pylama](https://pypi.org/project/pylama/) -- Testing: - [nose](https://pypi.org/project/nose/), - [pytest](https://pypi.org/project/pytest/), - [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [bandit](https://pypi.org/project/bandit/), + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) And finally thanks to the [Python](https://www.python.org/) development team and community for creating a fantastic programming language and community to be a @@ -770,48 +779,50 @@ part of! Thanks to the following projects which we fully rely on to provide some of our features: -- [isort](https://pypi.org/project/isort/) -- [jedi](https://pypi.org/project/jedi/) - and [parso](https://pypi.org/project/parso/) -- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) -- [ptvsd](https://pypi.org/project/ptvsd/) -- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) -- [rope](https://pypi.org/project/rope/) (user-installed) + +- [isort](https://pypi.org/project/isort/) +- [jedi](https://pypi.org/project/jedi/) + and [parso](https://pypi.org/project/parso/) +- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) +- [ptvsd](https://pypi.org/project/ptvsd/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) Also thanks to the various projects we provide integrations with which help make this extension useful: -- Debugging support: - [Django](https://pypi.org/project/Django/), - [Flask](https://pypi.org/project/Flask/), - [gevent](https://pypi.org/project/gevent/), - [Jinja](https://pypi.org/project/Jinja/), - [Pyramid](https://pypi.org/project/pyramid/), - [PySpark](https://pypi.org/project/pyspark/), - [Scrapy](https://pypi.org/project/Scrapy/), - [Watson](https://pypi.org/project/Watson/) -- Formatting: - [autopep8](https://pypi.org/project/autopep8/), - [black](https://pypi.org/project/black/), - [yapf](https://pypi.org/project/yapf/) -- Interpreter support: - [conda](https://conda.io/), - [direnv](https://direnv.net/), - [pipenv](https://pypi.org/project/pipenv/), - [pyenv](https://github.com/pyenv/pyenv), - [venv](https://docs.python.org/3/library/venv.html#module-venv), - [virtualenv](https://pypi.org/project/virtualenv/) -- Linting: - [bandit](https://pypi.org/project/bandit/), - [flake8](https://pypi.org/project/flake8/), - [mypy](https://pypi.org/project/mypy/), - [prospector](https://pypi.org/project/prospector/), - [pylint](https://pypi.org/project/pylint/), - [pydocstyle](https://pypi.org/project/pydocstyle/), - [pylama](https://pypi.org/project/pylama/) -- Testing: - [nose](https://pypi.org/project/nose/), - [pytest](https://pypi.org/project/pytest/), - [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [bandit](https://pypi.org/project/bandit/), + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) And finally thanks to the [Python](https://www.python.org/) development team and community for creating a fantastic programming language and community to be a @@ -861,13 +872,13 @@ part of! 1. Replaced occurrences of `pep8` with `pycodestyle.` All mentions of pep8 have been replaced with pycodestyle. Add script to replace outdated settings with the new ones in user settings.json - * python.linting.pep8Args -> python.linting.pycodestyleArgs - * python.linting.pep8CategorySeverity.E -> python.linting.pycodestyleCategorySeverity.E - * python.linting.pep8CategorySeverity.W -> python.linting.pycodestyleCategorySeverity.W - * python.linting.pep8Enabled -> python.linting.pycodestyleEnabled - * python.linting.pep8Path -> python.linting.pycodestylePath - * (thanks [Marsfan](https://github.com/Marsfan)) - ([#410](https://github.com/Microsoft/vscode-python/issues/410)) + - python.linting.pep8Args -> python.linting.pycodestyleArgs + - python.linting.pep8CategorySeverity.E -> python.linting.pycodestyleCategorySeverity.E + - python.linting.pep8CategorySeverity.W -> python.linting.pycodestyleCategorySeverity.W + - python.linting.pep8Enabled -> python.linting.pycodestyleEnabled + - python.linting.pep8Path -> python.linting.pycodestylePath + - (thanks [Marsfan](https://github.com/Marsfan)) + ([#410](https://github.com/Microsoft/vscode-python/issues/410)) 1. Do not change `foreground` colors in test statusbar. ([#4387](https://github.com/Microsoft/vscode-python/issues/4387)) 1. Set the `__file__` variable whenever running code so that `__file__` usage works in the interactive window. @@ -879,11 +890,11 @@ part of! 1. Changed the way scrolling is treated. Now we only check for the position of the scroll, the size of the cell won't matter. Still the interactive window will snap to the bottom if you already are at the bottom, and will stay in place if you are not. Like a chat window. Tested to work with: - - regular code - - dataframes - - big and regular plots - Turned the check of the scroll at the bottom from checking equal to checking a range to make it work with fractions. - ([#6580](https://github.com/Microsoft/vscode-python/issues/6580)) + - regular code + - dataframes + - big and regular plots + Turned the check of the scroll at the bottom from checking equal to checking a range to make it work with fractions. + ([#6580](https://github.com/Microsoft/vscode-python/issues/6580)) 1. Changed the name of the setting 'Run Magic Commands' to 'Run Startup Commands' to avoid confusion. ([#6842](https://github.com/Microsoft/vscode-python/issues/6842)) 1. Fix the debugger being installed even when available from the VSCode install. @@ -1055,48 +1066,50 @@ part of! Thanks to the following projects which we fully rely on to provide some of our features: -- [isort](https://pypi.org/project/isort/) -- [jedi](https://pypi.org/project/jedi/) - and [parso](https://pypi.org/project/parso/) -- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) -- [ptvsd](https://pypi.org/project/ptvsd/) -- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) -- [rope](https://pypi.org/project/rope/) (user-installed) + +- [isort](https://pypi.org/project/isort/) +- [jedi](https://pypi.org/project/jedi/) + and [parso](https://pypi.org/project/parso/) +- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) +- [ptvsd](https://pypi.org/project/ptvsd/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) Also thanks to the various projects we provide integrations with which help make this extension useful: -- Debugging support: - [Django](https://pypi.org/project/Django/), - [Flask](https://pypi.org/project/Flask/), - [gevent](https://pypi.org/project/gevent/), - [Jinja](https://pypi.org/project/Jinja/), - [Pyramid](https://pypi.org/project/pyramid/), - [PySpark](https://pypi.org/project/pyspark/), - [Scrapy](https://pypi.org/project/Scrapy/), - [Watson](https://pypi.org/project/Watson/) -- Formatting: - [autopep8](https://pypi.org/project/autopep8/), - [black](https://pypi.org/project/black/), - [yapf](https://pypi.org/project/yapf/) -- Interpreter support: - [conda](https://conda.io/), - [direnv](https://direnv.net/), - [pipenv](https://pypi.org/project/pipenv/), - [pyenv](https://github.com/pyenv/pyenv), - [venv](https://docs.python.org/3/library/venv.html#module-venv), - [virtualenv](https://pypi.org/project/virtualenv/) -- Linting: - [bandit](https://pypi.org/project/bandit/), - [flake8](https://pypi.org/project/flake8/), - [mypy](https://pypi.org/project/mypy/), - [prospector](https://pypi.org/project/prospector/), - [pylint](https://pypi.org/project/pylint/), - [pydocstyle](https://pypi.org/project/pydocstyle/), - [pylama](https://pypi.org/project/pylama/) -- Testing: - [nose](https://pypi.org/project/nose/), - [pytest](https://pypi.org/project/pytest/), - [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [bandit](https://pypi.org/project/bandit/), + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) And finally thanks to the [Python](https://www.python.org/) development team and community for creating a fantastic programming language and community to be a @@ -1187,10 +1200,11 @@ part of! ([#6938](https://github.com/Microsoft/vscode-python/issues/6938)) 1. Bump version of [PTVSD](https://pypi.org/project/ptvsd/) to `4.3.2`. - * Fix an issue with Jump to cursor command. [#1667](https://github.com/microsoft/ptvsd/issues/1667) - * Fix "Unable to find threadStateIndex for the current thread" message in terminal. [#1587](https://github.com/microsoft/ptvsd/issues/1587) - * Fixes crash when using python 3.7.4. [#1688](https://github.com/microsoft/ptvsd/issues/1688) - ([#6961](https://github.com/Microsoft/vscode-python/issues/6961)) + - Fix an issue with Jump to cursor command. [#1667](https://github.com/microsoft/ptvsd/issues/1667) + - Fix "Unable to find threadStateIndex for the current thread" message in terminal. [#1587](https://github.com/microsoft/ptvsd/issues/1587) + - Fixes crash when using python 3.7.4. [#1688](https://github.com/microsoft/ptvsd/issues/1688) + ([#6961](https://github.com/Microsoft/vscode-python/issues/6961)) + 1. Move nightly functional tests to use mock jupyter and create a new pipeline for flakey tests which use real jupyter. ([#7066](https://github.com/Microsoft/vscode-python/issues/7066)) 1. Corrected spelling of name for method to be `hasConfigurationFileInWorkspace`. @@ -1202,48 +1216,50 @@ part of! Thanks to the following projects which we fully rely on to provide some of our features: -- [isort](https://pypi.org/project/isort/) -- [jedi](https://pypi.org/project/jedi/) - and [parso](https://pypi.org/project/parso/) -- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) -- [ptvsd](https://pypi.org/project/ptvsd/) -- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) -- [rope](https://pypi.org/project/rope/) (user-installed) + +- [isort](https://pypi.org/project/isort/) +- [jedi](https://pypi.org/project/jedi/) + and [parso](https://pypi.org/project/parso/) +- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) +- [ptvsd](https://pypi.org/project/ptvsd/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) Also thanks to the various projects we provide integrations with which help make this extension useful: -- Debugging support: - [Django](https://pypi.org/project/Django/), - [Flask](https://pypi.org/project/Flask/), - [gevent](https://pypi.org/project/gevent/), - [Jinja](https://pypi.org/project/Jinja/), - [Pyramid](https://pypi.org/project/pyramid/), - [PySpark](https://pypi.org/project/pyspark/), - [Scrapy](https://pypi.org/project/Scrapy/), - [Watson](https://pypi.org/project/Watson/) -- Formatting: - [autopep8](https://pypi.org/project/autopep8/), - [black](https://pypi.org/project/black/), - [yapf](https://pypi.org/project/yapf/) -- Interpreter support: - [conda](https://conda.io/), - [direnv](https://direnv.net/), - [pipenv](https://pypi.org/project/pipenv/), - [pyenv](https://github.com/pyenv/pyenv), - [venv](https://docs.python.org/3/library/venv.html#module-venv), - [virtualenv](https://pypi.org/project/virtualenv/) -- Linting: - [bandit](https://pypi.org/project/bandit/), - [flake8](https://pypi.org/project/flake8/), - [mypy](https://pypi.org/project/mypy/), - [prospector](https://pypi.org/project/prospector/), - [pylint](https://pypi.org/project/pylint/), - [pydocstyle](https://pypi.org/project/pydocstyle/), - [pylama](https://pypi.org/project/pylama/) -- Testing: - [nose](https://pypi.org/project/nose/), - [pytest](https://pypi.org/project/pytest/), - [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [bandit](https://pypi.org/project/bandit/), + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) And finally thanks to the [Python](https://www.python.org/) development team and community for creating a fantastic programming language and community to be a @@ -1340,7 +1356,7 @@ part of! 1. Fix overwriting of cwd in the path list when discovering tests. ([#6417](https://github.com/Microsoft/vscode-python/issues/6417)) 1. Fixes a bug in pytest test discovery. - (thanks Rainer Dreyer) + (thanks Rainer Dreyer) ([#6463](https://github.com/Microsoft/vscode-python/issues/6463)) 1. Fix debugging to work on restarting the jupyter kernel. ([#6502](https://github.com/Microsoft/vscode-python/issues/6502)) @@ -1378,7 +1394,7 @@ part of! ([#6729](https://github.com/Microsoft/vscode-python/issues/6729)) 1. Debugging an untitled file causes an error 'Untitled-1 cannot be opened'. ([#6738](https://github.com/Microsoft/vscode-python/issues/6738)) -1. Eliminate 'History_\' from the problems list when using the interactive panel. +1. Eliminate 'History\_\' from the problems list when using the interactive panel. ([#6748](https://github.com/Microsoft/vscode-python/issues/6748)) ### Code Health @@ -1424,58 +1440,60 @@ part of! ([#6711](https://github.com/Microsoft/vscode-python/issues/6711)) 1. Bump version of [PTVSD](https://pypi.org/project/ptvsd/) to 4.3.0. ([#6771](https://github.com/Microsoft/vscode-python/issues/6771)) - * Support for Jupyter debugging - * Support for ipython cells - * API to enable and disable tracing via ptvsd.tracing - * ptvsd.enable_attach accepts address=('localhost', 0) and returns server port - * Known issue: Unable to find threadStateIndex for the current thread. curPyThread ([#11587](https://github.com/microsoft/ptvsd/issues/1587)) + - Support for Jupyter debugging + - Support for ipython cells + - API to enable and disable tracing via ptvsd.tracing + - ptvsd.enable_attach accepts address=('localhost', 0) and returns server port + - Known issue: Unable to find threadStateIndex for the current thread. curPyThread ([#11587](https://github.com/microsoft/ptvsd/issues/1587)) ### Thanks Thanks to the following projects which we fully rely on to provide some of our features: -- [isort](https://pypi.org/project/isort/) -- [jedi](https://pypi.org/project/jedi/) - and [parso](https://pypi.org/project/parso/) -- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) -- [ptvsd](https://pypi.org/project/ptvsd/) -- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) -- [rope](https://pypi.org/project/rope/) (user-installed) + +- [isort](https://pypi.org/project/isort/) +- [jedi](https://pypi.org/project/jedi/) + and [parso](https://pypi.org/project/parso/) +- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) +- [ptvsd](https://pypi.org/project/ptvsd/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) Also thanks to the various projects we provide integrations with which help make this extension useful: -- Debugging support: - [Django](https://pypi.org/project/Django/), - [Flask](https://pypi.org/project/Flask/), - [gevent](https://pypi.org/project/gevent/), - [Jinja](https://pypi.org/project/Jinja/), - [Pyramid](https://pypi.org/project/pyramid/), - [PySpark](https://pypi.org/project/pyspark/), - [Scrapy](https://pypi.org/project/Scrapy/), - [Watson](https://pypi.org/project/Watson/) -- Formatting: - [autopep8](https://pypi.org/project/autopep8/), - [black](https://pypi.org/project/black/), - [yapf](https://pypi.org/project/yapf/) -- Interpreter support: - [conda](https://conda.io/), - [direnv](https://direnv.net/), - [pipenv](https://pypi.org/project/pipenv/), - [pyenv](https://github.com/pyenv/pyenv), - [venv](https://docs.python.org/3/library/venv.html#module-venv), - [virtualenv](https://pypi.org/project/virtualenv/) -- Linting: - [bandit](https://pypi.org/project/bandit/), - [flake8](https://pypi.org/project/flake8/), - [mypy](https://pypi.org/project/mypy/), - [prospector](https://pypi.org/project/prospector/), - [pylint](https://pypi.org/project/pylint/), - [pydocstyle](https://pypi.org/project/pydocstyle/), - [pylama](https://pypi.org/project/pylama/) -- Testing: - [nose](https://pypi.org/project/nose/), - [pytest](https://pypi.org/project/pytest/), - [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [bandit](https://pypi.org/project/bandit/), + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) And finally thanks to the [Python](https://www.python.org/) development team and community for creating a fantastic programming language and community to be a @@ -1652,48 +1670,50 @@ part of! Thanks to the following projects which we fully rely on to provide some of our features: -- [isort 4.3.20](https://pypi.org/project/isort/4.3.20/) -- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) - and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/) -- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) -- [ptvsd](https://pypi.org/project/ptvsd/) -- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) -- [rope](https://pypi.org/project/rope/) (user-installed) + +- [isort 4.3.20](https://pypi.org/project/isort/4.3.20/) +- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) + and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/) +- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) +- [ptvsd](https://pypi.org/project/ptvsd/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) Also thanks to the various projects we provide integrations with which help make this extension useful: -- Debugging support: - [Django](https://pypi.org/project/Django/), - [Flask](https://pypi.org/project/Flask/), - [gevent](https://pypi.org/project/gevent/), - [Jinja](https://pypi.org/project/Jinja/), - [Pyramid](https://pypi.org/project/pyramid/), - [PySpark](https://pypi.org/project/pyspark/), - [Scrapy](https://pypi.org/project/Scrapy/), - [Watson](https://pypi.org/project/Watson/) -- Formatting: - [autopep8](https://pypi.org/project/autopep8/), - [black](https://pypi.org/project/black/), - [yapf](https://pypi.org/project/yapf/) -- Interpreter support: - [conda](https://conda.io/), - [direnv](https://direnv.net/), - [pipenv](https://pypi.org/project/pipenv/), - [pyenv](https://github.com/pyenv/pyenv), - [venv](https://docs.python.org/3/library/venv.html#module-venv), - [virtualenv](https://pypi.org/project/virtualenv/) -- Linting: - [bandit](https://pypi.org/project/bandit/), - [flake8](https://pypi.org/project/flake8/), - [mypy](https://pypi.org/project/mypy/), - [prospector](https://pypi.org/project/prospector/), - [pylint](https://pypi.org/project/pylint/), - [pydocstyle](https://pypi.org/project/pydocstyle/), - [pylama](https://pypi.org/project/pylama/) -- Testing: - [nose](https://pypi.org/project/nose/), - [pytest](https://pypi.org/project/pytest/), - [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [bandit](https://pypi.org/project/bandit/), + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) And finally thanks to the [Python](https://www.python.org/) development team and community for creating a fantastic programming language and community to be a @@ -1715,7 +1735,6 @@ part of! 1. Fixes to detection of the shell. ([#5916](https://github.com/microsoft/vscode-python/issues/5916)) - ## 2019.5.18875 (6 June 2019) ### Fixes @@ -1746,7 +1765,6 @@ part of! 1. Revert changes related to pathMappings in `launch.json` for `debugging` [#3568](https://github.com/Microsoft/vscode-python/issues/3568) ([#5833](https://github.com/microsoft/vscode-python/issues/5833)) - ## 2019.5.17059 (28 May 2019) ### Enhancements @@ -1846,11 +1864,11 @@ part of! 1. Changed synchronous file system operation into async ([#4895](https://github.com/Microsoft/vscode-python/issues/4895)) 1. Update ptvsd to [4.2.10](https://github.com/Microsoft/ptvsd/releases/tag/v4.2.10). - * No longer switch off getpass on import. - * Fixes a crash on evaluate request. - * Fix a issue with running no-debug. - * Fixes issue with forwarding sys.stdin.read(). - * Remove sys.prefix form library roots. + - No longer switch off getpass on import. + - Fixes a crash on evaluate request. + - Fix a issue with running no-debug. + - Fixes issue with forwarding sys.stdin.read(). + - Remove sys.prefix form library roots. ### Code Health @@ -1874,53 +1892,54 @@ part of! (Thanks [Andrew Blakey](https://github.com/ablakey)) ([#5642](https://github.com/Microsoft/vscode-python/issues/5642)) - ### Thanks Thanks to the following projects which we fully rely on to provide some of our features: -- [isort 4.3.20](https://pypi.org/project/isort/4.3.20/) -- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) - and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/) -- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) -- [ptvsd](https://pypi.org/project/ptvsd/) -- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) -- [rope](https://pypi.org/project/rope/) (user-installed) + +- [isort 4.3.20](https://pypi.org/project/isort/4.3.20/) +- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) + and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/) +- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) +- [ptvsd](https://pypi.org/project/ptvsd/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) Also thanks to the various projects we provide integrations with which help make this extension useful: -- Debugging support: - [Django](https://pypi.org/project/Django/), - [Flask](https://pypi.org/project/Flask/), - [gevent](https://pypi.org/project/gevent/), - [Jinja](https://pypi.org/project/Jinja/), - [Pyramid](https://pypi.org/project/pyramid/), - [PySpark](https://pypi.org/project/pyspark/), - [Scrapy](https://pypi.org/project/Scrapy/), - [Watson](https://pypi.org/project/Watson/) -- Formatting: - [autopep8](https://pypi.org/project/autopep8/), - [black](https://pypi.org/project/black/), - [yapf](https://pypi.org/project/yapf/) -- Interpreter support: - [conda](https://conda.io/), - [direnv](https://direnv.net/), - [pipenv](https://pypi.org/project/pipenv/), - [pyenv](https://github.com/pyenv/pyenv), - [venv](https://docs.python.org/3/library/venv.html#module-venv), - [virtualenv](https://pypi.org/project/virtualenv/) -- Linting: - [bandit](https://pypi.org/project/bandit/), - [flake8](https://pypi.org/project/flake8/), - [mypy](https://pypi.org/project/mypy/), - [prospector](https://pypi.org/project/prospector/), - [pylint](https://pypi.org/project/pylint/), - [pydocstyle](https://pypi.org/project/pydocstyle/), - [pylama](https://pypi.org/project/pylama/) -- Testing: - [nose](https://pypi.org/project/nose/), - [pytest](https://pypi.org/project/pytest/), - [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [bandit](https://pypi.org/project/bandit/), + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) And finally thanks to the [Python](https://www.python.org/) development team and community for creating a fantastic programming language and community to be a @@ -2063,10 +2082,10 @@ part of! 1. Fix error with bad len() values in variable explorer ([#5420](https://github.com/Microsoft/vscode-python/issues/5420)) 1. Update ptvsd to [4.2.8](https://github.com/Microsoft/ptvsd/releases/tag/v4.2.8). - * Path mapping bug fixes. - * Fix for hang when using debug console. - * Fix for set next statement. - * Fix for multi-threading. + - Path mapping bug fixes. + - Fix for hang when using debug console. + - Fix for set next statement. + - Fix for multi-threading. ### Code Health @@ -2145,60 +2164,61 @@ part of! Thanks to the following projects which we fully rely on to provide some of our features: -- [isort 4.3.4](https://pypi.org/project/isort/4.3.4/) -- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) - and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/) -- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) -- [ptvsd](https://pypi.org/project/ptvsd/) -- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) -- [rope](https://pypi.org/project/rope/) (user-installed) + +- [isort 4.3.4](https://pypi.org/project/isort/4.3.4/) +- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) + and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/) +- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) +- [ptvsd](https://pypi.org/project/ptvsd/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) Also thanks to the various projects we provide integrations with which help make this extension useful: -- Debugging support: - [Django](https://pypi.org/project/Django/), - [Flask](https://pypi.org/project/Flask/), - [gevent](https://pypi.org/project/gevent/), - [Jinja](https://pypi.org/project/Jinja/), - [Pyramid](https://pypi.org/project/pyramid/), - [PySpark](https://pypi.org/project/pyspark/), - [Scrapy](https://pypi.org/project/Scrapy/), - [Watson](https://pypi.org/project/Watson/) -- Formatting: - [autopep8](https://pypi.org/project/autopep8/), - [black](https://pypi.org/project/black/), - [yapf](https://pypi.org/project/yapf/) -- Interpreter support: - [conda](https://conda.io/), - [direnv](https://direnv.net/), - [pipenv](https://pypi.org/project/pipenv/), - [pyenv](https://github.com/pyenv/pyenv), - [venv](https://docs.python.org/3/library/venv.html#module-venv), - [virtualenv](https://pypi.org/project/virtualenv/) -- Linting: - [bandit](https://pypi.org/project/bandit/), - [flake8](https://pypi.org/project/flake8/), - [mypy](https://pypi.org/project/mypy/), - [prospector](https://pypi.org/project/prospector/), - [pylint](https://pypi.org/project/pylint/), - [pydocstyle](https://pypi.org/project/pydocstyle/), - [pylama](https://pypi.org/project/pylama/) -- Testing: - [nose](https://pypi.org/project/nose/), - [pytest](https://pypi.org/project/pytest/), - [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [bandit](https://pypi.org/project/bandit/), + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) And finally thanks to the [Python](https://www.python.org/) development team and community for creating a fantastic programming language and community to be a part of! - ## 2019.3.3 (8 April 2019) ### Fixes 1. Update ptvsd to [4.2.7](https://github.com/Microsoft/ptvsd/releases/tag/v4.2.7). - * Fix issues related to debugging Django templates. + - Fix issues related to debugging Django templates. 1. Update the Python language server to 0.2.47. ### Code Health @@ -2206,7 +2226,6 @@ part of! 1. Capture telemetry to track switching to and from the Language Server. ([#5162](https://github.com/Microsoft/vscode-python/issues/5162)) - ## 2019.3.2 (2 April 2019) ### Fixes @@ -2217,15 +2236,14 @@ part of! ([#5064](https://github.com/Microsoft/vscode-python/issues/5064)) 1. Update ptvsd to [4.2.6](https://github.com/Microsoft/ptvsd/releases/tag/v4.2.6). ([#5083](https://github.com/Microsoft/vscode-python/issues/5083)) - * Fix issue with expanding variables in watch window and hover. - * Fix issue with launching a sub-module. + - Fix issue with expanding variables in watch window and hover. + - Fix issue with launching a sub-module. ### Code Health 1. Capture telemetry to track which installer was used when installing packages via the extension. ([#5063](https://github.com/Microsoft/vscode-python/issues/5063)) - ## 2019.3.1 (28 March 2019) ### Enhancements @@ -2334,11 +2352,11 @@ part of! ([#4868](https://github.com/Microsoft/vscode-python/issues/4868)) 1. Update ptvsd to [4.2.5](https://github.com/Microsoft/ptvsd/releases/tag/v4.2.5). ([#4932](https://github.com/Microsoft/vscode-python/issues/4932)) - * Fix issues with django and jinja2 exceptions. - * Detaching sometimes throws ValueError. - * StackTrace request respecting just-my-code. - * Don't give error redirecting output with pythonw. - * Fix for stop on entry issue. + - Fix issues with django and jinja2 exceptions. + - Detaching sometimes throws ValueError. + - StackTrace request respecting just-my-code. + - Don't give error redirecting output with pythonw. + - Fix for stop on entry issue. 1. Update the Python language server to 0.2.31. ### Code Health @@ -2387,48 +2405,50 @@ part of! Thanks to the following projects which we fully rely on to provide some of our features: -- [isort 4.3.4](https://pypi.org/project/isort/4.3.4/) -- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) - and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/) -- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) -- [ptvsd](https://pypi.org/project/ptvsd/) -- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) -- [rope](https://pypi.org/project/rope/) (user-installed) + +- [isort 4.3.4](https://pypi.org/project/isort/4.3.4/) +- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) + and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/) +- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) +- [ptvsd](https://pypi.org/project/ptvsd/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) Also thanks to the various projects we provide integrations with which help make this extension useful: -- Debugging support: - [Django](https://pypi.org/project/Django/), - [Flask](https://pypi.org/project/Flask/), - [gevent](https://pypi.org/project/gevent/), - [Jinja](https://pypi.org/project/Jinja/), - [Pyramid](https://pypi.org/project/pyramid/), - [PySpark](https://pypi.org/project/pyspark/), - [Scrapy](https://pypi.org/project/Scrapy/), - [Watson](https://pypi.org/project/Watson/) -- Formatting: - [autopep8](https://pypi.org/project/autopep8/), - [black](https://pypi.org/project/black/), - [yapf](https://pypi.org/project/yapf/) -- Interpreter support: - [conda](https://conda.io/), - [direnv](https://direnv.net/), - [pipenv](https://pypi.org/project/pipenv/), - [pyenv](https://github.com/pyenv/pyenv), - [venv](https://docs.python.org/3/library/venv.html#module-venv), - [virtualenv](https://pypi.org/project/virtualenv/) -- Linting: - [bandit](https://pypi.org/project/bandit/), - [flake8](https://pypi.org/project/flake8/), - [mypy](https://pypi.org/project/mypy/), - [prospector](https://pypi.org/project/prospector/), - [pylint](https://pypi.org/project/pylint/), - [pydocstyle](https://pypi.org/project/pydocstyle/), - [pylama](https://pypi.org/project/pylama/) -- Testing: - [nose](https://pypi.org/project/nose/), - [pytest](https://pypi.org/project/pytest/), - [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [bandit](https://pypi.org/project/bandit/), + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) And finally thanks to the [Python](https://www.python.org/) development team and community for creating a fantastic programming language and community to be a @@ -2449,7 +2469,6 @@ part of! ### Fixes - 1. Exclude files `travis*.log`, `pythonFiles/tests/**`, `types/**` from the extension. ([#4554](https://github.com/Microsoft/vscode-python/issues/4554)) ([#4566](https://github.com/Microsoft/vscode-python/issues/4566)) @@ -2460,48 +2479,50 @@ part of! Thanks to the following projects which we fully rely on to provide some of our features: -- [isort 4.3.4](https://pypi.org/project/isort/4.3.4/) -- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) - and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/) -- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) -- [ptvsd](https://pypi.org/project/ptvsd/) -- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) -- [rope](https://pypi.org/project/rope/) (user-installed) + +- [isort 4.3.4](https://pypi.org/project/isort/4.3.4/) +- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) + and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/) +- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) +- [ptvsd](https://pypi.org/project/ptvsd/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) Also thanks to the various projects we provide integrations with which help make this extension useful: -- Debugging support: - [Django](https://pypi.org/project/Django/), - [Flask](https://pypi.org/project/Flask/), - [gevent](https://pypi.org/project/gevent/), - [Jinja](https://pypi.org/project/Jinja/), - [Pyramid](https://pypi.org/project/pyramid/), - [PySpark](https://pypi.org/project/pyspark/), - [Scrapy](https://pypi.org/project/Scrapy/), - [Watson](https://pypi.org/project/Watson/) -- Formatting: - [autopep8](https://pypi.org/project/autopep8/), - [black](https://pypi.org/project/black/), - [yapf](https://pypi.org/project/yapf/) -- Interpreter support: - [conda](https://conda.io/), - [direnv](https://direnv.net/), - [pipenv](https://pypi.org/project/pipenv/), - [pyenv](https://github.com/pyenv/pyenv), - [venv](https://docs.python.org/3/library/venv.html#module-venv), - [virtualenv](https://pypi.org/project/virtualenv/) -- Linting: - [bandit](https://pypi.org/project/bandit/), - [flake8](https://pypi.org/project/flake8/), - [mypy](https://pypi.org/project/mypy/), - [prospector](https://pypi.org/project/prospector/), - [pylint](https://pypi.org/project/pylint/), - [pydocstyle](https://pypi.org/project/pydocstyle/), - [pylama](https://pypi.org/project/pylama/) -- Testing: - [nose](https://pypi.org/project/nose/), - [pytest](https://pypi.org/project/pytest/), - [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [bandit](https://pypi.org/project/bandit/), + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) And finally thanks to the [Python](https://www.python.org/) development team and community for creating a fantastic programming language and community to be a @@ -2554,8 +2575,8 @@ part of! ([#4371](https://github.com/Microsoft/vscode-python/issues/4371)) 1. Update ptvsd to [4.2.4](https://github.com/Microsoft/ptvsd/releases/tag/v4.2.4). ([#4457](https://github.com/Microsoft/vscode-python/issues/4457)) - * Validate breakpoint targets. - * Properly exclude certain files from showing up in the debugger. + - Validate breakpoint targets. + - Properly exclude certain files from showing up in the debugger. ### Fixes @@ -2584,8 +2605,8 @@ part of! ([#4418](https://github.com/Microsoft/vscode-python/issues/4418)) 1. Update ptvsd to [4.2.4](https://github.com/Microsoft/ptvsd/releases/tag/v4.2.4). ([#4457](https://github.com/Microsoft/vscode-python/issues/4457)) - * `BreakOnSystemExitZero` now respected. - * Fix a bug causing breakpoints not to be hit when attached to a remote target. + - `BreakOnSystemExitZero` now respected. + - Fix a bug causing breakpoints not to be hit when attached to a remote target. 1. Fix double running of cells with the context menu ([#4532](https://github.com/Microsoft/vscode-python/issues/4532)) 1. Update the Python language server to 0.1.80. @@ -2607,56 +2628,56 @@ part of! 1. Fixes to smoke tests on CI. ([#4201](https://github.com/Microsoft/vscode-python/issues/4201)) - - ## 2019.1.0 (29 Jan 2019) ### Thanks Thanks to the following projects which we fully rely on to provide some of our features: -- [isort 4.3.4](https://pypi.org/project/isort/4.3.4/) -- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) - and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/) -- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) -- [ptvsd](https://pypi.org/project/ptvsd/) -- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) -- [rope](https://pypi.org/project/rope/) (user-installed) + +- [isort 4.3.4](https://pypi.org/project/isort/4.3.4/) +- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) + and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/) +- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) +- [ptvsd](https://pypi.org/project/ptvsd/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) Also thanks to the various projects we provide integrations with which help make this extension useful: -- Debugging support: - [Django](https://pypi.org/project/Django/), - [Flask](https://pypi.org/project/Flask/), - [gevent](https://pypi.org/project/gevent/), - [Jinja](https://pypi.org/project/Jinja/), - [Pyramid](https://pypi.org/project/pyramid/), - [PySpark](https://pypi.org/project/pyspark/), - [Scrapy](https://pypi.org/project/Scrapy/), - [Watson](https://pypi.org/project/Watson/) -- Formatting: - [autopep8](https://pypi.org/project/autopep8/), - [black](https://pypi.org/project/black/), - [yapf](https://pypi.org/project/yapf/) -- Interpreter support: - [conda](https://conda.io/), - [direnv](https://direnv.net/), - [pipenv](https://pypi.org/project/pipenv/), - [pyenv](https://github.com/pyenv/pyenv), - [venv](https://docs.python.org/3/library/venv.html#module-venv), - [virtualenv](https://pypi.org/project/virtualenv/) -- Linting: - [bandit](https://pypi.org/project/bandit/), - [flake8](https://pypi.org/project/flake8/), - [mypy](https://pypi.org/project/mypy/), - [prospector](https://pypi.org/project/prospector/), - [pylint](https://pypi.org/project/pylint/), - [pydocstyle](https://pypi.org/project/pydocstyle/), - [pylama](https://pypi.org/project/pylama/) -- Testing: - [nose](https://pypi.org/project/nose/), - [pytest](https://pypi.org/project/pytest/), - [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [bandit](https://pypi.org/project/bandit/), + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) And finally thanks to the [Python](https://www.python.org/) development team and community for creating a fantastic programming language and community to be a @@ -2867,7 +2888,6 @@ part of! ### Fixes - 1. Lowering threshold for Language Server support on a platform. ([#3693](https://github.com/Microsoft/vscode-python/issues/3693)) 1. Fix bug affecting multiple linters used in a workspace. @@ -2880,48 +2900,50 @@ part of! Thanks to the following projects which we fully rely on to provide some of our features: -- [isort 4.3.4](https://pypi.org/project/isort/4.3.4/) -- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) - and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/) -- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) -- [ptvsd](https://pypi.org/project/ptvsd/) -- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) -- [rope](https://pypi.org/project/rope/) (user-installed) + +- [isort 4.3.4](https://pypi.org/project/isort/4.3.4/) +- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) + and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/) +- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) +- [ptvsd](https://pypi.org/project/ptvsd/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) Also thanks to the various projects we provide integrations with which help make this extension useful: -- Debugging support: - [Django](https://pypi.org/project/Django/), - [Flask](https://pypi.org/project/Flask/), - [gevent](https://pypi.org/project/gevent/), - [Jinja](https://pypi.org/project/Jinja/), - [Pyramid](https://pypi.org/project/pyramid/), - [PySpark](https://pypi.org/project/pyspark/), - [Scrapy](https://pypi.org/project/Scrapy/), - [Watson](https://pypi.org/project/Watson/) -- Formatting: - [autopep8](https://pypi.org/project/autopep8/), - [black](https://pypi.org/project/black/), - [yapf](https://pypi.org/project/yapf/) -- Interpreter support: - [conda](https://conda.io/), - [direnv](https://direnv.net/), - [pipenv](https://pypi.org/project/pipenv/), - [pyenv](https://github.com/pyenv/pyenv), - [venv](https://docs.python.org/3/library/venv.html#module-venv), - [virtualenv](https://pypi.org/project/virtualenv/) -- Linting: - [bandit](https://pypi.org/project/bandit/), - [flake8](https://pypi.org/project/flake8/), - [mypy](https://pypi.org/project/mypy/), - [prospector](https://pypi.org/project/prospector/), - [pylint](https://pypi.org/project/pylint/), - [pydocstyle](https://pypi.org/project/pydocstyle/), - [pylama](https://pypi.org/project/pylama/) -- Testing: - [nose](https://pypi.org/project/nose/), - [pytest](https://pypi.org/project/pytest/), - [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [bandit](https://pypi.org/project/bandit/), + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) And finally thanks to the [Python](https://www.python.org/) development team and community for creating a fantastic programming language and community to be a @@ -2972,11 +2994,10 @@ part of! 1. Fix crash when `kernelspec` is missing path or language. ([#3561](https://github.com/Microsoft/vscode-python/issues/3561)) 1. Update the Microsoft Python Language Server to 0.1.72/[2018.12.1](https://github.com/Microsoft/python-language-server/releases/tag/2018.12.1) ([#3657](https://github.com/Microsoft/vscode-python/issues/3657)): - * Properly resolve namespace packages and relative imports. - * `Go to Definition` now supports namespace packages. - * Fixed `null` reference exceptions. - * Fixed erroneously reporting `None`, `True`, and `False` as undefined. - + - Properly resolve namespace packages and relative imports. + - `Go to Definition` now supports namespace packages. + - Fixed `null` reference exceptions. + - Fixed erroneously reporting `None`, `True`, and `False` as undefined. ### Code Health @@ -2999,48 +3020,50 @@ part of! Thanks to the following projects which we fully rely on to provide some of our features: -- [isort 4.3.4](https://pypi.org/project/isort/4.3.4/) -- [jedi 0.13.1](https://pypi.org/project/jedi/0.13.1/) - and [parso 0.3.1](https://pypi.org/project/parso/0.3.1/) -- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) -- [ptvsd](https://pypi.org/project/ptvsd/) -- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) -- [rope](https://pypi.org/project/rope/) (user-installed) + +- [isort 4.3.4](https://pypi.org/project/isort/4.3.4/) +- [jedi 0.13.1](https://pypi.org/project/jedi/0.13.1/) + and [parso 0.3.1](https://pypi.org/project/parso/0.3.1/) +- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) +- [ptvsd](https://pypi.org/project/ptvsd/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) Also thanks to the various projects we provide integrations with which help make this extension useful: -- Debugging support: - [Django](https://pypi.org/project/Django/), - [Flask](https://pypi.org/project/Flask/), - [gevent](https://pypi.org/project/gevent/), - [Jinja](https://pypi.org/project/Jinja/), - [Pyramid](https://pypi.org/project/pyramid/), - [PySpark](https://pypi.org/project/pyspark/), - [Scrapy](https://pypi.org/project/Scrapy/), - [Watson](https://pypi.org/project/Watson/) -- Formatting: - [autopep8](https://pypi.org/project/autopep8/), - [black](https://pypi.org/project/black/), - [yapf](https://pypi.org/project/yapf/) -- Interpreter support: - [conda](https://conda.io/), - [direnv](https://direnv.net/), - [pipenv](https://pypi.org/project/pipenv/), - [pyenv](https://github.com/pyenv/pyenv), - [venv](https://docs.python.org/3/library/venv.html#module-venv), - [virtualenv](https://pypi.org/project/virtualenv/) -- Linting: - [bandit](https://pypi.org/project/bandit/), - [flake8](https://pypi.org/project/flake8/), - [mypy](https://pypi.org/project/mypy/), - [prospector](https://pypi.org/project/prospector/), - [pylint](https://pypi.org/project/pylint/), - [pydocstyle](https://pypi.org/project/pydocstyle/), - [pylama](https://pypi.org/project/pylama/) -- Testing: - [nose](https://pypi.org/project/nose/), - [pytest](https://pypi.org/project/pytest/), - [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [bandit](https://pypi.org/project/bandit/), + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) And finally thanks to the [Python](https://www.python.org/) development team and community for creating a fantastic programming language and community to be a @@ -3055,8 +3078,8 @@ part of! 1. Expose an API that can be used by other extensions to interact with the Python Extension. ([#3121](https://github.com/Microsoft/vscode-python/issues/3121)) 1. Updated the language server to [0.1.65](https://github.com/Microsoft/python-language-server/releases/tag/2018.11.1): - - Improved `formatOnType` so it handles mismatched braces better - ([#3482](https://github.com/Microsoft/vscode-python/issues/3482)) + - Improved `formatOnType` so it handles mismatched braces better + ([#3482](https://github.com/Microsoft/vscode-python/issues/3482)) ### Fixes @@ -3065,12 +3088,12 @@ part of! ([#793](https://github.com/Microsoft/vscode-python/issues/793)) 1. Always use bundled version of [`ptvsd`](https://github.com/microsoft/ptvsd), unless specified. To use a custom version of `ptvsd` in the debugger, add `customDebugger` into your `launch.json` configuration as follows: - ```json - "type": "python", - "request": "launch", - "customDebugger": true - ``` - ([#3283](https://github.com/Microsoft/vscode-python/issues/3283)) + ```json + "type": "python", + "request": "launch", + "customDebugger": true + ``` + ([#3283](https://github.com/Microsoft/vscode-python/issues/3283)) 1. Fix problems with virtual environments not matching the loaded python when running cells. ([#3294](https://github.com/Microsoft/vscode-python/issues/3294)) 1. Add button for interrupting the jupyter kernel @@ -3084,11 +3107,11 @@ part of! 1. Re-run Jupyter notebook setup when the kernel is restarted. This correctly picks up dark color themes for matplotlib. ([#3418](https://github.com/Microsoft/vscode-python/issues/3418)) 1. Update the language server to [0.1.65](https://github.com/Microsoft/python-language-server/releases/tag/2018.11.1): - - Fixed `null` reference exception when executing "Find symbol in workspace" - - Fixed `null` argument exception that could happen when a function used tuples - - Fixed issue when variables in nested list comprehensions were marked as undefined - - Fixed exception that could be thrown with certain generic syntax - ([#3482](https://github.com/Microsoft/vscode-python/issues/3482)) + - Fixed `null` reference exception when executing "Find symbol in workspace" + - Fixed `null` argument exception that could happen when a function used tuples + - Fixed issue when variables in nested list comprehensions were marked as undefined + - Fixed exception that could be thrown with certain generic syntax + ([#3482](https://github.com/Microsoft/vscode-python/issues/3482)) ### Code Health @@ -3113,7 +3136,6 @@ part of! (make sure to cleanup any kernelspecs that are created during this process). ([#3433](https://github.com/Microsoft/vscode-python/issues/3433)) - ## 2018.10.1 (09 Nov 2018) ### Fixes @@ -3127,48 +3149,50 @@ part of! Thanks to the following projects which we fully rely on to provide some of our features: -- [isort 4.3.4](https://pypi.org/project/isort/4.3.4/) -- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) - and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/) -- Microsoft Python Language Server -- ptvsd -- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) -- [rope](https://pypi.org/project/rope/) (user-installed) + +- [isort 4.3.4](https://pypi.org/project/isort/4.3.4/) +- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) + and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/) +- Microsoft Python Language Server +- ptvsd +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) Also thanks to the various projects we provide integrations with which help make this extension useful: -- Debugging support: - [Django](https://pypi.org/project/Django/), - [Flask](https://pypi.org/project/Flask/), - [gevent](https://pypi.org/project/gevent/), - [Jinja](https://pypi.org/project/Jinja/), - [Pyramid](https://pypi.org/project/pyramid/), - [PySpark](https://pypi.org/project/pyspark/), - [Scrapy](https://pypi.org/project/Scrapy/), - [Watson](https://pypi.org/project/Watson/) -- Formatting: - [autopep8](https://pypi.org/project/autopep8/), - [black](https://pypi.org/project/black/), - [yapf](https://pypi.org/project/yapf/) -- Interpreter support: - [conda](https://conda.io/), - [direnv](https://direnv.net/), - [pipenv](https://pypi.org/project/pipenv/), - [pyenv](https://github.com/pyenv/pyenv), - [venv](https://docs.python.org/3/library/venv.html#module-venv), - [virtualenv](https://pypi.org/project/virtualenv/) -- Linting: - [bandit](https://pypi.org/project/bandit/), - [flake8](https://pypi.org/project/flake8/), - [mypy](https://pypi.org/project/mypy/), - [prospector](https://pypi.org/project/prospector/), - [pylint](https://pypi.org/project/pylint/), - [pydocstyle](https://pypi.org/project/pydocstyle/), - [pylama](https://pypi.org/project/pylama/) -- Testing: - [nose](https://pypi.org/project/nose/), - [pytest](https://pypi.org/project/pytest/), - [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [bandit](https://pypi.org/project/bandit/), + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) And finally thanks to the [Python](https://www.python.org/) development team and community for creating a fantastic programming language and community to be a @@ -3195,13 +3219,13 @@ part of! 1. Updated the [language server](https://github.com/Microsoft/python-language-server) to [0.1.57/2018.11.0](https://github.com/Microsoft/python-language-server/releases/tag/2018.11.0) (from 2018.10.0) and the [debugger](https://pypi.org/project/ptvsd/) to [4.2.0](https://github.com/Microsoft/ptvsd/releases/tag/v4.2.0) (from 4.1.3). Highlights include: - * Language server - - Completion support for [`collections.namedtuple`](https://docs.python.org/3/library/collections.html#collections.namedtuple). - - Support [`typing.NewType`](https://docs.python.org/3/library/typing.html#typing.NewType) - and [`typing.TypeVar`](https://docs.python.org/3/library/typing.html#typing.TypeVar). - * Debugger - - Add support for sub-process debugging (set `"subProcess": true` in your `launch.json` to use). - - Add support for [pyside2](https://pypi.org/project/PySide2/). + - Language server + - Completion support for [`collections.namedtuple`](https://docs.python.org/3/library/collections.html#collections.namedtuple). + - Support [`typing.NewType`](https://docs.python.org/3/library/typing.html#typing.NewType) + and [`typing.TypeVar`](https://docs.python.org/3/library/typing.html#typing.TypeVar). + - Debugger + - Add support for sub-process debugging (set `"subProcess": true` in your `launch.json` to use). + - Add support for [pyside2](https://pypi.org/project/PySide2/). 1. Add localization of strings. Localized versions are specified in the package.nls.\.json files. ([#463](https://github.com/Microsoft/vscode-python/issues/463)) 1. Clear cached list of interpreters when an interpeter is created in the workspace folder (this allows for virtual environments created in one's workspace folder to be detectable immediately). @@ -3231,17 +3255,17 @@ part of! 1. Updated the [language server](https://github.com/Microsoft/python-language-server) to [0.1.57/2018.11.0](https://github.com/Microsoft/python-language-server/releases/tag/2018.11.0) (from 2018.10.0) and the [debugger](https://pypi.org/project/ptvsd/) to [4.2.0](https://github.com/Microsoft/ptvsd/releases/tag/v4.2.0) (from 4.1.3). Highlights include: - * Language server - - Completions on generic containers work (e.g. `x: List[T]` now have completions for `x`, not just `x[]`). - - Fixed issues relating to `Go to Definition` for `from ... import` statements. - - `None` is no longer flagged as undefined. - - `BadSourceException` should no longer be raised. - - Fixed a null reference exception when handling certain function overloads. - * Debugger - - Properly deal with handled or unhandled exception in top level frames. - - Any folder ending with `site-packages` is considered a library. - - Treat any code not in `site-packages` as user code. - - Handle case where no completions are provided by the debugger. + - Language server + - Completions on generic containers work (e.g. `x: List[T]` now have completions for `x`, not just `x[]`). + - Fixed issues relating to `Go to Definition` for `from ... import` statements. + - `None` is no longer flagged as undefined. + - `BadSourceException` should no longer be raised. + - Fixed a null reference exception when handling certain function overloads. + - Debugger + - Properly deal with handled or unhandled exception in top level frames. + - Any folder ending with `site-packages` is considered a library. + - Treat any code not in `site-packages` as user code. + - Handle case where no completions are provided by the debugger. ### Code Health @@ -3273,10 +3297,6 @@ part of! 1. Pin extension to a minimum version of the language server. ([#3125](https://github.com/Microsoft/vscode-python/issues/3125)) - - - - ## 2018.9.2 (29 Oct 2018) ### Fixes @@ -3289,7 +3309,6 @@ part of! 1. Forward telemetry from the language server. ([#2940](https://github.com/Microsoft/vscode-python/issues/2940)) - ## 2018.9.1 (18 Oct 2018) ### Fixes @@ -3306,55 +3325,56 @@ part of! 1. Add ability to publish extension builds from `release` branches into the blob store. ([#2874](https://github.com/Microsoft/vscode-python/issues/2874)) - ## 2018.9.0 (9 Oct 2018) ### Thanks Thanks to the following projects which we fully rely on to provide some of our features: -- [isort 4.3.4](https://pypi.org/project/isort/4.3.4/) -- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) - and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/) -- [Microsoft Python Language Server 2018.9.0](https://github.com/Microsoft/python-language-server/releases/tag/2018.9.0) -- [ptvsd 4.1.3](https://github.com/Microsoft/ptvsd/releases/tag/v4.1.3) -- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) -- [rope](https://pypi.org/project/rope/) (user-installed) + +- [isort 4.3.4](https://pypi.org/project/isort/4.3.4/) +- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) + and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/) +- [Microsoft Python Language Server 2018.9.0](https://github.com/Microsoft/python-language-server/releases/tag/2018.9.0) +- [ptvsd 4.1.3](https://github.com/Microsoft/ptvsd/releases/tag/v4.1.3) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) Also thanks to the various projects we provide integrations with which help make this extension useful: -- Debugging support: - [Django](https://pypi.org/project/Django/), - [Flask](https://pypi.org/project/Flask/), - [gevent](https://pypi.org/project/gevent/), - [Jinja](https://pypi.org/project/Jinja/), - [Pyramid](https://pypi.org/project/pyramid/), - [PySpark](https://pypi.org/project/pyspark/), - [Scrapy](https://pypi.org/project/Scrapy/), - [Watson](https://pypi.org/project/Watson/) -- Formatting: - [autopep8](https://pypi.org/project/autopep8/), - [black](https://pypi.org/project/black/), - [yapf](https://pypi.org/project/yapf/) -- Interpreter support: - [conda](https://conda.io/), - [direnv](https://direnv.net/), - [pipenv](https://pypi.org/project/pipenv/), - [pyenv](https://github.com/pyenv/pyenv), - [venv](https://docs.python.org/3/library/venv.html#module-venv), - [virtualenv](https://pypi.org/project/virtualenv/) -- Linting: - [bandit](https://pypi.org/project/bandit/), - [flake8](https://pypi.org/project/flake8/), - [mypy](https://pypi.org/project/mypy/), - [prospector](https://pypi.org/project/prospector/), - [pylint](https://pypi.org/project/pylint/), - [pydocstyle](https://pypi.org/project/pydocstyle/), - [pylama](https://pypi.org/project/pylama/) -- Testing: - [nose](https://pypi.org/project/nose/), - [pytest](https://pypi.org/project/pytest/), - [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [bandit](https://pypi.org/project/bandit/), + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) And finally thanks to the [Python](https://www.python.org/) development team and community for creating a fantastic programming language and community to be a @@ -3410,7 +3430,7 @@ part of! 1. Fix the regex expression to match MyPy linter messages that expects the file name to have a `.py` extension, that isn't always the case, to catch any filename. E.g., .pyi files that describes interfaces wouldn't get the linter messages to Problems tab. ([#2380](https://github.com/Microsoft/vscode-python/issues/2380)) -1. Do not use variable substitution when updating `python.pythonPath`. This matters +1. Do not use variable substitution when updating `python.pythonPath`. This matters because VS Code does not do variable substitution in settings values. ([#2459](https://github.com/Microsoft/vscode-python/issues/2459)) 1. Use a python script to launch the debugger, instead of using `-m` which requires changes to the `PYTHONPATH` variable. @@ -3445,53 +3465,54 @@ part of! 1. Update `vscode-extension-telemetry` to `0.0.22`. ([#2745](https://github.com/Microsoft/vscode-python/issues/2745)) - ## 2018.8.0 (04 September 2018) ### Thanks Thanks to the following projects which we fully rely on to provide some of our features: -- [isort 4.3.4](https://pypi.org/project/isort/4.3.4/) -- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) - and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/) -- [4.1.1](https://pypi.org/project/ptvsd/4.1.1/) -- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) -- [rope](https://pypi.org/project/rope/) (user-installed) + +- [isort 4.3.4](https://pypi.org/project/isort/4.3.4/) +- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) + and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/) +- [4.1.1](https://pypi.org/project/ptvsd/4.1.1/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) Also thanks to the various projects we provide integrations with which help make this extension useful: -- Debugging support: - [Django](https://pypi.org/project/Django/), - [Flask](https://pypi.org/project/Flask/), - [gevent](https://pypi.org/project/gevent/), - [Jinja](https://pypi.org/project/Jinja/), - [Pyramid](https://pypi.org/project/pyramid/), - [PySpark](https://pypi.org/project/pyspark/), - [Scrapy](https://pypi.org/project/Scrapy/), - [Watson](https://pypi.org/project/Watson/) -- Formatting: - [autopep8](https://pypi.org/project/autopep8/), - [black](https://pypi.org/project/black/), - [yapf](https://pypi.org/project/yapf/) -- Interpreter support: - [conda](https://conda.io/), - [direnv](https://direnv.net/), - [pipenv](https://pypi.org/project/pipenv/), - [pyenv](https://github.com/pyenv/pyenv), - [venv](https://docs.python.org/3/library/venv.html#module-venv), - [virtualenv](https://pypi.org/project/virtualenv/) -- Linting: - [flake8](https://pypi.org/project/flake8/), - [mypy](https://pypi.org/project/mypy/), - [prospector](https://pypi.org/project/prospector/), - [pylint](https://pypi.org/project/pylint/), - [pydocstyle](https://pypi.org/project/pydocstyle/), - [pylama](https://pypi.org/project/pylama/) -- Testing: - [nose](https://pypi.org/project/nose/), - [pytest](https://pypi.org/project/pytest/), - [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) And finally thanks to the [Python](https://www.python.org/) development team and community for creating a fantastic programming language and community to be a @@ -3597,7 +3618,6 @@ part of! 1. Only use the current stable version of PTVSD in CI builds/releases. ([#2432](https://github.com/Microsoft/vscode-python/issues/2432)) - ## 2018.7.1 (23 July 2018) ### Fixes @@ -3606,53 +3626,54 @@ part of! [651468731500ec1cc644029c3666c57b82f77d76](https://github.com/Microsoft/PTVS/commit/651468731500ec1cc644029c3666c57b82f77d76). ([#2233](https://github.com/Microsoft/vscode-python/issues/2233)) - ## 2018.7.0 (18 July 2018) ### Thanks Thanks to the following projects which we fully rely on to provide some of our features: -- [isort 4.3.4](https://pypi.org/project/isort/4.3.4/) -- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) - and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/) -- [ptvsd 3.0.0](https://pypi.org/project/ptvsd/3.0.0/) and [4.1.11a5](https://pypi.org/project/ptvsd/4.1.11a5/) -- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) -- [rope](https://pypi.org/project/rope/) (user-installed) + +- [isort 4.3.4](https://pypi.org/project/isort/4.3.4/) +- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) + and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/) +- [ptvsd 3.0.0](https://pypi.org/project/ptvsd/3.0.0/) and [4.1.11a5](https://pypi.org/project/ptvsd/4.1.11a5/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) Also thanks to the various projects we provide integrations with which help make this extension useful: -- Debugging support: - [Django](https://pypi.org/project/Django/), - [Flask](https://pypi.org/project/Flask/), - [gevent](https://pypi.org/project/gevent/), - [Jinja](https://pypi.org/project/Jinja/), - [Pyramid](https://pypi.org/project/pyramid/), - [PySpark](https://pypi.org/project/pyspark/), - [Scrapy](https://pypi.org/project/Scrapy/), - [Watson](https://pypi.org/project/Watson/) -- Formatting: - [autopep8](https://pypi.org/project/autopep8/), - [black](https://pypi.org/project/black/), - [yapf](https://pypi.org/project/yapf/) -- Interpreter support: - [conda](https://conda.io/), - [direnv](https://direnv.net/), - [pipenv](https://pypi.org/project/pipenv/), - [pyenv](https://github.com/pyenv/pyenv), - [venv](https://docs.python.org/3/library/venv.html#module-venv), - [virtualenv](https://pypi.org/project/virtualenv/) -- Linting: - [flake8](https://pypi.org/project/flake8/), - [mypy](https://pypi.org/project/mypy/), - [prospector](https://pypi.org/project/prospector/), - [pylint](https://pypi.org/project/pylint/), - [pydocstyle](https://pypi.org/project/pydocstyle/), - [pylama](https://pypi.org/project/pylama/) -- Testing: - [nose](https://pypi.org/project/nose/), - [pytest](https://pypi.org/project/pytest/), - [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) And finally thanks to the [Python](https://www.python.org/) development team and community for creating a fantastic programming language and community to be a @@ -3705,54 +3726,54 @@ part of! 1. Change the download links of the language server files. ([#2180](https://github.com/Microsoft/vscode-python/issues/2180)) - - ## 2018.6.0 (20 June 2018) ### Thanks Thanks to the following projects which we fully rely on to provide some of our features: -- [isort 4.3.4](https://pypi.org/project/isort/4.3.4/) -- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) - and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/) -- [ptvsd 3.0.0](https://pypi.org/project/ptvsd/3.0.0/) and [4.1.11a5](https://pypi.org/project/ptvsd/4.1.11a5/) -- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) -- [rope](https://pypi.org/project/rope/) (user-installed) + +- [isort 4.3.4](https://pypi.org/project/isort/4.3.4/) +- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) + and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/) +- [ptvsd 3.0.0](https://pypi.org/project/ptvsd/3.0.0/) and [4.1.11a5](https://pypi.org/project/ptvsd/4.1.11a5/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) Also thanks to the various projects we provide integrations with which help make this extension useful: -- Debugging support: - [Django](https://pypi.org/project/Django/), - [Flask](https://pypi.org/project/Flask/), - [gevent](https://pypi.org/project/gevent/), - [Jinja](https://pypi.org/project/Jinja/), - [Pyramid](https://pypi.org/project/pyramid/), - [PySpark](https://pypi.org/project/pyspark/), - [Scrapy](https://pypi.org/project/Scrapy/), - [Watson](https://pypi.org/project/Watson/) -- Formatting: - [autopep8](https://pypi.org/project/autopep8/), - [black](https://pypi.org/project/black/), - [yapf](https://pypi.org/project/yapf/) -- Interpreter support: - [conda](https://conda.io/), - [direnv](https://direnv.net/), - [pipenv](https://pypi.org/project/pipenv/), - [pyenv](https://github.com/pyenv/pyenv), - [venv](https://docs.python.org/3/library/venv.html#module-venv), - [virtualenv](https://pypi.org/project/virtualenv/) -- Linting: - [flake8](https://pypi.org/project/flake8/), - [mypy](https://pypi.org/project/mypy/), - [prospector](https://pypi.org/project/prospector/), - [pylint](https://pypi.org/project/pylint/), - [pydocstyle](https://pypi.org/project/pydocstyle/), - [pylama](https://pypi.org/project/pylama/) -- Testing: - [nose](https://pypi.org/project/nose/), - [pytest](https://pypi.org/project/pytest/), - [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) And finally thanks to the [Python](https://www.python.org/) development team and community for creating a fantastic programming language and community to be a @@ -3767,14 +3788,14 @@ part of! (thanks [Bence Nagy](https://github.com/underyx)) ([#127](https://github.com/Microsoft/vscode-python/issues/127)) 1. Add support for the `"source.organizeImports"` setting for `"editor.codeActionsOnSave"` (thanks [Nathan Gaberel](https://github.com/n6g7)); you can turn this on just for Python using: - ```json - "[python]": { - "editor.codeActionsOnSave": { - "source.organizeImports": true - } - } - ``` - ([#156](https://github.com/Microsoft/vscode-python/issues/156)) + ```json + "[python]": { + "editor.codeActionsOnSave": { + "source.organizeImports": true + } + } + ``` + ([#156](https://github.com/Microsoft/vscode-python/issues/156)) 1. Added Spanish translation. (thanks [Mario Rubio](https://github.com/mario-mra/)) ([#1902](https://github.com/Microsoft/vscode-python/issues/1902)) @@ -3877,20 +3898,17 @@ part of! 1. Create tests to measure activation times for the extension. ([#932](https://github.com/Microsoft/vscode-python/issues/932)) - - - - ## 2018.5.0 (05 Jun 2018) Thanks to the following projects which we fully rely on to provide some of our features: -- [isort 4.2.15](https://pypi.org/project/isort/4.2.15/) -- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) - and [parso 0.2.0](https://pypi.org/project/parso/0.2.0/) -- [ptvsd 3.0.0](https://pypi.org/project/ptvsd/3.0.0/) and [4.1.1a5](https://pypi.org/project/ptvsd/4.1.1a5/) -- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) -- [rope](https://pypi.org/project/rope/) (user-installed) + +- [isort 4.2.15](https://pypi.org/project/isort/4.2.15/) +- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) + and [parso 0.2.0](https://pypi.org/project/parso/0.2.0/) +- [ptvsd 3.0.0](https://pypi.org/project/ptvsd/3.0.0/) and [4.1.1a5](https://pypi.org/project/ptvsd/4.1.1a5/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) And thanks to the many other projects which users can optionally choose from and install to work with the extension. Without them the extension would not be @@ -3996,20 +4014,17 @@ nearly as feature-rich and useful as it is. 1. Ensure `Outline` view doesn't overload the language server with too many requests, while user is editing text in the editor. ([#1856](https://github.com/Microsoft/vscode-python/issues/1856)) - - - - ## 2018.4.0 (2 May 2018) Thanks to the following projects which we fully rely on to provide some of our features: -- [isort 4.2.15](https://pypi.org/project/isort/4.2.15/) -- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) - and [parso 0.2.0](https://pypi.org/project/parso/0.2.0/) -- [ptvsd 3.0.0](https://pypi.org/project/ptvsd/3.0.0/) and [4.1.1a1](https://pypi.org/project/ptvsd/4.1.1a1/) -- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) -- [rope](https://pypi.org/project/rope/) (user-installed) + +- [isort 4.2.15](https://pypi.org/project/isort/4.2.15/) +- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/) + and [parso 0.2.0](https://pypi.org/project/parso/0.2.0/) +- [ptvsd 3.0.0](https://pypi.org/project/ptvsd/3.0.0/) and [4.1.1a1](https://pypi.org/project/ptvsd/4.1.1a1/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) And a special thanks to [Patryk Zawadzki](https://github.com/patrys) for all of his help on [our issue tracker](https://github.com/Microsoft/vscode-python)! @@ -4018,12 +4033,12 @@ his help on [our issue tracker](https://github.com/Microsoft/vscode-python)! 1. Enable debugging of Jinja templates in the experimental debugger. This is made possible with the addition of the `jinja` setting in the `launch.json` file as follows: - ```json - "request": "launch or attach", - ... - "jinja": true - ``` - ([#1206](https://github.com/Microsoft/vscode-python/issues/1206)) + ```json + "request": "launch or attach", + ... + "jinja": true + ``` + ([#1206](https://github.com/Microsoft/vscode-python/issues/1206)) 1. Remove empty spaces from the selected text of the active editor when executing in a terminal. ([#1207](https://github.com/Microsoft/vscode-python/issues/1207)) 1. Add prelimnary support for remote debugging using the experimental debugger. @@ -4049,15 +4064,15 @@ his help on [our issue tracker](https://github.com/Microsoft/vscode-python)! ([#1492](https://github.com/Microsoft/vscode-python/issues/1492)) 1. Add prelimnary support for remote debugging using the experimental debugger. Attach to a Python program after having imported `ptvsd` and enabling the debugger to attach as follows: - ```python - import ptvsd - ptvsd.enable_attach(('0.0.0.0', 5678)) - ``` - Additional capabilities: - * `ptvsd.break_into_debugger()` to break into the attached debugger. - * `ptvsd.wait_for_attach(timeout)` to cause the program to wait until a debugger attaches. - * `ptvsd.is_attached()` to determine whether a debugger is attached to the program. - ([#907](https://github.com/Microsoft/vscode-python/issues/907)) + ```python + import ptvsd + ptvsd.enable_attach(('0.0.0.0', 5678)) + ``` + Additional capabilities: + - `ptvsd.break_into_debugger()` to break into the attached debugger. + - `ptvsd.wait_for_attach(timeout)` to cause the program to wait until a debugger attaches. + - `ptvsd.is_attached()` to determine whether a debugger is attached to the program. + ([#907](https://github.com/Microsoft/vscode-python/issues/907)) ### Fixes @@ -4135,118 +4150,117 @@ his help on [our issue tracker](https://github.com/Microsoft/vscode-python)! 1. Register language server functionality in the extension against specific resource types supporting the python language. ([#1530](https://github.com/Microsoft/vscode-python/issues/1530)) - ## 2018.3.1 (29 Mar 2018) ### Fixes 1. Fixes issue that causes linter to fail when file path contains spaces. -([#1239](https://github.com/Microsoft/vscode-python/issues/1239)) + ([#1239](https://github.com/Microsoft/vscode-python/issues/1239)) ## 2018.3.0 (28 Mar 2018) ### Enhancements 1. Add a PySpark debug configuration for the experimental debugger. - ([#1029](https://github.com/Microsoft/vscode-python/issues/1029)) + ([#1029](https://github.com/Microsoft/vscode-python/issues/1029)) 1. Add a Pyramid debug configuration for the experimental debugger. - ([#1030](https://github.com/Microsoft/vscode-python/issues/1030)) + ([#1030](https://github.com/Microsoft/vscode-python/issues/1030)) 1. Add a Watson debug configuration for the experimental debugger. - ([#1031](https://github.com/Microsoft/vscode-python/issues/1031)) + ([#1031](https://github.com/Microsoft/vscode-python/issues/1031)) 1. Add a Scrapy debug configuration for the experimental debugger. - ([#1032](https://github.com/Microsoft/vscode-python/issues/1032)) + ([#1032](https://github.com/Microsoft/vscode-python/issues/1032)) 1. When using pipenv, install packages (such as linters, test frameworks) in dev-packages. - ([#1110](https://github.com/Microsoft/vscode-python/issues/1110)) + ([#1110](https://github.com/Microsoft/vscode-python/issues/1110)) 1. Added commands translation for italian locale. -(thanks [Dotpys](https://github.com/Dotpys/)) ([#1152](https://github.com/Microsoft/vscode-python/issues/1152)) + (thanks [Dotpys](https://github.com/Dotpys/)) ([#1152](https://github.com/Microsoft/vscode-python/issues/1152)) 1. Add support for Django Template debugging in experimental debugger. - ([#1189](https://github.com/Microsoft/vscode-python/issues/1189)) + ([#1189](https://github.com/Microsoft/vscode-python/issues/1189)) 1. Add support for Flask Template debugging in experimental debugger. - ([#1190](https://github.com/Microsoft/vscode-python/issues/1190)) + ([#1190](https://github.com/Microsoft/vscode-python/issues/1190)) 1. Add support for Jinja template debugging. ([#1210](https://github.com/Microsoft/vscode-python/issues/1210)) 1. When debugging, use `Integrated Terminal` as the default console. - ([#526](https://github.com/Microsoft/vscode-python/issues/526)) + ([#526](https://github.com/Microsoft/vscode-python/issues/526)) 1. Disable the display of errors messages when rediscovering of tests fail in response to changes to files, e.g. don't show a message if there's a syntax error in the test code. - ([#704](https://github.com/Microsoft/vscode-python/issues/704)) + ([#704](https://github.com/Microsoft/vscode-python/issues/704)) 1. Bundle python dependencies (PTVSD package) in the extension for the experimental debugger. - ([#741](https://github.com/Microsoft/vscode-python/issues/741)) -1. Add support for experimental debugger when debugging Python Unit Tests. - ([#906](https://github.com/Microsoft/vscode-python/issues/906)) + ([#741](https://github.com/Microsoft/vscode-python/issues/741)) +1. Add support for experimental debugger when debugging Python Unit Tests. + ([#906](https://github.com/Microsoft/vscode-python/issues/906)) 1. Support `Debug Console` as a `console` option for the Experimental Debugger. - ([#950](https://github.com/Microsoft/vscode-python/issues/950)) + ([#950](https://github.com/Microsoft/vscode-python/issues/950)) 1. Enable syntax highlighting for `requirements.in` files as used by -e.g. [pip-tools](https://github.com/jazzband/pip-tools) -(thanks [Lorenzo Villani](https://github.com/lvillani)) - ([#961](https://github.com/Microsoft/vscode-python/issues/961)) + e.g. [pip-tools](https://github.com/jazzband/pip-tools) + (thanks [Lorenzo Villani](https://github.com/lvillani)) + ([#961](https://github.com/Microsoft/vscode-python/issues/961)) 1. Add support to read name of Pipfile from environment variable. - ([#999](https://github.com/Microsoft/vscode-python/issues/999)) + ([#999](https://github.com/Microsoft/vscode-python/issues/999)) ### Fixes 1. Fixes issue that causes debugging of unit tests to hang indefinitely. ([#1009](https://github.com/Microsoft/vscode-python/issues/1009)) 1. Add ability to disable the check on memory usage of language server (Jedi) process. -To turn off this check, add `"python.jediMemoryLimit": -1` to your user or workspace settings (`settings.json`) file. - ([#1036](https://github.com/Microsoft/vscode-python/issues/1036)) + To turn off this check, add `"python.jediMemoryLimit": -1` to your user or workspace settings (`settings.json`) file. + ([#1036](https://github.com/Microsoft/vscode-python/issues/1036)) 1. Ignore test results when debugging unit tests. - ([#1043](https://github.com/Microsoft/vscode-python/issues/1043)) + ([#1043](https://github.com/Microsoft/vscode-python/issues/1043)) 1. Fixes auto formatting of conditional statements containing expressions with `<=` symbols. - ([#1096](https://github.com/Microsoft/vscode-python/issues/1096)) + ([#1096](https://github.com/Microsoft/vscode-python/issues/1096)) 1. Resolve debug configuration information in `launch.json` when debugging without opening a python file. - ([#1098](https://github.com/Microsoft/vscode-python/issues/1098)) + ([#1098](https://github.com/Microsoft/vscode-python/issues/1098)) 1. Disables auto completion when editing text at the end of a comment string. - ([#1123](https://github.com/Microsoft/vscode-python/issues/1123)) + ([#1123](https://github.com/Microsoft/vscode-python/issues/1123)) 1. Ensures file paths are properly encoded when passing them as arguments to linters. - ([#199](https://github.com/Microsoft/vscode-python/issues/199)) + ([#199](https://github.com/Microsoft/vscode-python/issues/199)) 1. Fix occasionally having unverified breakpoints - ([#87](https://github.com/Microsoft/vscode-python/issues/87)) + ([#87](https://github.com/Microsoft/vscode-python/issues/87)) 1. Ensure conda installer is not used for non-conda environments. - ([#969](https://github.com/Microsoft/vscode-python/issues/969)) + ([#969](https://github.com/Microsoft/vscode-python/issues/969)) 1. Fixes issue that display incorrect interpreter briefly before updating it to the right value. - ([#981](https://github.com/Microsoft/vscode-python/issues/981)) + ([#981](https://github.com/Microsoft/vscode-python/issues/981)) ### Code Health 1. Exclude 'news' folder from getting packaged into the extension. - ([#1020](https://github.com/Microsoft/vscode-python/issues/1020)) + ([#1020](https://github.com/Microsoft/vscode-python/issues/1020)) 1. Remove Jupyter commands. -(thanks [Yu Zhang](https://github.com/neilsustc)) - ([#1034](https://github.com/Microsoft/vscode-python/issues/1034)) + (thanks [Yu Zhang](https://github.com/neilsustc)) + ([#1034](https://github.com/Microsoft/vscode-python/issues/1034)) 1. Trigger incremental build compilation only when typescript files are modified. - ([#1040](https://github.com/Microsoft/vscode-python/issues/1040)) + ([#1040](https://github.com/Microsoft/vscode-python/issues/1040)) 1. Updated npm dependencies in devDependencies and fix TypeScript compilation issues. - ([#1042](https://github.com/Microsoft/vscode-python/issues/1042)) + ([#1042](https://github.com/Microsoft/vscode-python/issues/1042)) 1. Enable unit testing of stdout and stderr redirection for the experimental debugger. - ([#1048](https://github.com/Microsoft/vscode-python/issues/1048)) + ([#1048](https://github.com/Microsoft/vscode-python/issues/1048)) 1. Update npm package `vscode-extension-telemetry` to fix the warning 'os.tmpDir() deprecation'. -(thanks [osya](https://github.com/osya)) - ([#1066](https://github.com/Microsoft/vscode-python/issues/1066)) + (thanks [osya](https://github.com/osya)) + ([#1066](https://github.com/Microsoft/vscode-python/issues/1066)) 1. Prevent the debugger stepping into JS code while developing the extension when debugging async TypeScript code. - ([#1090](https://github.com/Microsoft/vscode-python/issues/1090)) + ([#1090](https://github.com/Microsoft/vscode-python/issues/1090)) 1. Increase timeouts for the debugger unit tests. - ([#1094](https://github.com/Microsoft/vscode-python/issues/1094)) + ([#1094](https://github.com/Microsoft/vscode-python/issues/1094)) 1. Change the command used to install pip on AppVeyor to avoid installation errors. - ([#1107](https://github.com/Microsoft/vscode-python/issues/1107)) + ([#1107](https://github.com/Microsoft/vscode-python/issues/1107)) 1. Check whether a document is active when detecthing changes in the active document. - ([#1114](https://github.com/Microsoft/vscode-python/issues/1114)) + ([#1114](https://github.com/Microsoft/vscode-python/issues/1114)) 1. Remove SIGINT handler in debugger adapter, thereby preventing it from shutting down the debugger. - ([#1122](https://github.com/Microsoft/vscode-python/issues/1122)) + ([#1122](https://github.com/Microsoft/vscode-python/issues/1122)) 1. Improve compilation speed of the extension's TypeScript code. - ([#1146](https://github.com/Microsoft/vscode-python/issues/1146)) + ([#1146](https://github.com/Microsoft/vscode-python/issues/1146)) 1. Changes to how debug options are passed into the experimental version of PTVSD (debugger). - ([#1168](https://github.com/Microsoft/vscode-python/issues/1168)) + ([#1168](https://github.com/Microsoft/vscode-python/issues/1168)) 1. Ensure file paths are not sent in telemetry when running unit tests. - ([#1180](https://github.com/Microsoft/vscode-python/issues/1180)) + ([#1180](https://github.com/Microsoft/vscode-python/issues/1180)) 1. Change `DjangoDebugging` to `Django` in `debugOptions` of launch.json. - ([#1198](https://github.com/Microsoft/vscode-python/issues/1198)) + ([#1198](https://github.com/Microsoft/vscode-python/issues/1198)) 1. Changed property name used to capture the trigger source of Unit Tests. ([#1213](https://github.com/Microsoft/vscode-python/issues/1213)) 1. Enable unit testing of the experimental debugger on CI servers - ([#742](https://github.com/Microsoft/vscode-python/issues/742)) + ([#742](https://github.com/Microsoft/vscode-python/issues/742)) 1. Generate code coverage for debug adapter unit tests. - ([#778](https://github.com/Microsoft/vscode-python/issues/778)) + ([#778](https://github.com/Microsoft/vscode-python/issues/778)) 1. Execute prospector as a module (using -m). - ([#982](https://github.com/Microsoft/vscode-python/issues/982)) + ([#982](https://github.com/Microsoft/vscode-python/issues/982)) 1. Launch unit tests in debug mode as opposed to running and attaching the debugger to the already-running interpreter. - ([#983](https://github.com/Microsoft/vscode-python/issues/983)) + ([#983](https://github.com/Microsoft/vscode-python/issues/983)) ## 2018.2.1 (09 Mar 2018) @@ -4267,11 +4281,11 @@ those who reported bugs or provided feedback)! A special thanks goes out to the following external contributors who contributed code in this release: -* [Andrea D'Amore](https://github.com/Microsoft/vscode-python/commits?author=anddam) -* [Tzu-ping Chung](https://github.com/Microsoft/vscode-python/commits?author=uranusjr) -* [Elliott Beach](https://github.com/Microsoft/vscode-python/commits?author=elliott-beach) -* [Manuja Jay](https://github.com/Microsoft/vscode-python/commits?author=manujadev) -* [philipwasserman](https://github.com/Microsoft/vscode-python/commits?author=philipwasserman) +- [Andrea D'Amore](https://github.com/Microsoft/vscode-python/commits?author=anddam) +- [Tzu-ping Chung](https://github.com/Microsoft/vscode-python/commits?author=uranusjr) +- [Elliott Beach](https://github.com/Microsoft/vscode-python/commits?author=elliott-beach) +- [Manuja Jay](https://github.com/Microsoft/vscode-python/commits?author=manujadev) +- [philipwasserman](https://github.com/Microsoft/vscode-python/commits?author=philipwasserman) ### Enhancements @@ -4305,9 +4319,9 @@ contributed code in this release: 1. Better detection of a `pylintrc` is available to automatically disable our default Pylint checks ([#728](https://github.com/Microsoft/vscode-python/issues/728), - [#788](https://github.com/Microsoft/vscode-python/issues/788), - [#838](https://github.com/Microsoft/vscode-python/issues/838), - [#442](https://github.com/Microsoft/vscode-python/issues/442)) + [#788](https://github.com/Microsoft/vscode-python/issues/788), + [#838](https://github.com/Microsoft/vscode-python/issues/838), + [#442](https://github.com/Microsoft/vscode-python/issues/442)) 1. Fix `Got to Python object` ([#403](https://github.com/Microsoft/vscode-python/issues/403)) 1. When reformatting a file, put the temporary file in the workspace folder so e.g. yapf detect their configuration files appropriately @@ -4330,14 +4344,14 @@ contributed code in this release: automatically killing the process; reload VS Code to start the process again if desired ([#926](https://github.com/Microsoft/vscode-python/issues/926), - [#263](https://github.com/Microsoft/vscode-python/issues/263)) + [#263](https://github.com/Microsoft/vscode-python/issues/263)) 1. Support multiple linters again ([#913](https://github.com/Microsoft/vscode-python/issues/913)) 1. Don't over-escape markup found in docstrings ([#911](https://github.com/Microsoft/vscode-python/issues/911), - [#716](https://github.com/Microsoft/vscode-python/issues/716), - [#627](https://github.com/Microsoft/vscode-python/issues/627), - [#692](https://github.com/Microsoft/vscode-python/issues/692)) + [#716](https://github.com/Microsoft/vscode-python/issues/716), + [#627](https://github.com/Microsoft/vscode-python/issues/627), + [#692](https://github.com/Microsoft/vscode-python/issues/692)) 1. Fix when the `Problems` pane lists file paths prefixed with `git:` ([#916](https://github.com/Microsoft/vscode-python/issues/916)) 1. Fix inline documentation when an odd number of quotes exists @@ -4353,8 +4367,8 @@ contributed code in this release: 1. Upgrade to Jedi 0.11.1 ([#674](https://github.com/Microsoft/vscode-python/issues/674), - [#607](https://github.com/Microsoft/vscode-python/issues/607), - [#99](https://github.com/Microsoft/vscode-python/issues/99)) + [#607](https://github.com/Microsoft/vscode-python/issues/607), + [#99](https://github.com/Microsoft/vscode-python/issues/99)) 1. Removed the banner announcing the extension moving over to Microsoft ([#830](https://github.com/Microsoft/vscode-python/issues/830)) 1. Renamed the default debugger configurations ([#412](https://github.com/Microsoft/vscode-python/issues/412)) @@ -4368,607 +4382,667 @@ contributed code in this release: Thanks to everyone who contributed to this release, including the following people who contributed code: -* [jpfarias](https://github.com/jpfarias) -* [Hongbo He](https://github.com/graycarl) -* [JohnstonCode](https://github.com/JohnstonCode) -* [Yuichi Nukiyama](https://github.com/YuichiNukiyama) -* [MichaelSuen](https://github.com/MichaelSuen-thePointer) +- [jpfarias](https://github.com/jpfarias) +- [Hongbo He](https://github.com/graycarl) +- [JohnstonCode](https://github.com/JohnstonCode) +- [Yuichi Nukiyama](https://github.com/YuichiNukiyama) +- [MichaelSuen](https://github.com/MichaelSuen-thePointer) ### Fixed issues -* Support cached interpreter locations for faster interpreter selection ([#666](https://github.com/Microsoft/vscode-python/issues/259)) -* Sending a block of code with multiple global-level scopes now works ([#259](https://github.com/Microsoft/vscode-python/issues/259)) -* Automatic activation of virtual or conda environment in terminal when executing Python code/file ([#383](https://github.com/Microsoft/vscode-python/issues/383)) -* Introduce a `Python: Create Terminal` to create a terminal that activates the selected virtual/conda environment ([#622](https://github.com/Microsoft/vscode-python/issues/622)) -* Add a `ko-kr` translation ([#540](https://github.com/Microsoft/vscode-python/pull/540)) -* Add a `ru` translation ([#411](https://github.com/Microsoft/vscode-python/pull/411)) -* Performance improvements to detection of virtual environments in current workspace ([#372](https://github.com/Microsoft/vscode-python/issues/372)) -* Correctly detect 64-bit python ([#414](https://github.com/Microsoft/vscode-python/issues/414)) -* Display parameter information while typing ([#70](https://github.com/Microsoft/vscode-python/issues/70)) -* Use `localhost` instead of `0.0.0.0` when starting debug servers ([#205](https://github.com/Microsoft/vscode-python/issues/205)) -* Ability to configure host name of debug server ([#227](https://github.com/Microsoft/vscode-python/issues/227)) -* Use environment variable PYTHONPATH defined in `.env` for intellisense and code navigation ([#316](https://github.com/Microsoft/vscode-python/issues/316)) -* Support path variable when debugging ([#436](https://github.com/Microsoft/vscode-python/issues/436)) -* Ensure virtual environments can be created in `.env` directory ([#435](https://github.com/Microsoft/vscode-python/issues/435), [#482](https://github.com/Microsoft/vscode-python/issues/482), [#486](https://github.com/Microsoft/vscode-python/issues/486)) -* Reload environment variables from `.env` without having to restart VS Code ([#183](https://github.com/Microsoft/vscode-python/issues/183)) -* Support debugging of Pyramid framework on Windows ([#519](https://github.com/Microsoft/vscode-python/issues/519)) -* Code snippet for `pubd` ([#545](https://github.com/Microsoft/vscode-python/issues/545)) -* Code clean up ([#353](https://github.com/Microsoft/vscode-python/issues/353), [#352](https://github.com/Microsoft/vscode-python/issues/352), [#354](https://github.com/Microsoft/vscode-python/issues/354), [#456](https://github.com/Microsoft/vscode-python/issues/456), [#491](https://github.com/Microsoft/vscode-python/issues/491), [#228](https://github.com/Microsoft/vscode-python/issues/228), [#549](https://github.com/Microsoft/vscode-python/issues/545), [#594](https://github.com/Microsoft/vscode-python/issues/594), [#617](https://github.com/Microsoft/vscode-python/issues/617), [#556](https://github.com/Microsoft/vscode-python/issues/556)) -* Move to `yarn` from `npm` ([#421](https://github.com/Microsoft/vscode-python/issues/421)) -* Add code coverage for extension itself ([#464](https://github.com/Microsoft/vscode-python/issues/464)) -* Releasing [insiders build](https://pvsc.blob.core.windows.net/extension-builds/ms-python-insiders.vsix) of the extension and uploading to cloud storage ([#429](https://github.com/Microsoft/vscode-python/issues/429)) -* Japanese translation ([#434](https://github.com/Microsoft/vscode-python/pull/434)) -* Russian translation ([#411](https://github.com/Microsoft/vscode-python/pull/411)) -* Support paths with spaces when generating tags with `Build Workspace Symbols` ([#44](https://github.com/Microsoft/vscode-python/issues/44)) -* Add ability to configure the linters ([#572](https://github.com/Microsoft/vscode-python/issues/572)) -* Add default set of rules for Pylint ([#554](https://github.com/Microsoft/vscode-python/issues/554)) -* Prompt to install formatter if not available ([#524](https://github.com/Microsoft/vscode-python/issues/524)) -* work around `editor.formatOnSave` failing when taking more then 750ms ([#124](https://github.com/Microsoft/vscode-python/issues/124), [#590](https://github.com/Microsoft/vscode-python/issues/590), [#624](https://github.com/Microsoft/vscode-python/issues/624), [#427](https://github.com/Microsoft/vscode-python/issues/427), [#492](https://github.com/Microsoft/vscode-python/issues/492)) -* Function argument completion no longer automatically includes the default argument ([#522](https://github.com/Microsoft/vscode-python/issues/522)) -* When sending a selection to the terminal, keep the focus in the editor window ([#60](https://github.com/Microsoft/vscode-python/issues/60)) -* Install packages for non-environment Pythons as `--user` installs ([#527](https://github.com/Microsoft/vscode-python/issues/527)) -* No longer suggest the system Python install on macOS when running `Select Interpreter` as it's too outdated (e.g. lacks `pip`) ([#440](https://github.com/Microsoft/vscode-python/issues/440)) -* Fix potential hang from Intellisense ([#423](https://github.com/Microsoft/vscode-python/issues/423)) +- Support cached interpreter locations for faster interpreter selection ([#666](https://github.com/Microsoft/vscode-python/issues/259)) +- Sending a block of code with multiple global-level scopes now works ([#259](https://github.com/Microsoft/vscode-python/issues/259)) +- Automatic activation of virtual or conda environment in terminal when executing Python code/file ([#383](https://github.com/Microsoft/vscode-python/issues/383)) +- Introduce a `Python: Create Terminal` to create a terminal that activates the selected virtual/conda environment ([#622](https://github.com/Microsoft/vscode-python/issues/622)) +- Add a `ko-kr` translation ([#540](https://github.com/Microsoft/vscode-python/pull/540)) +- Add a `ru` translation ([#411](https://github.com/Microsoft/vscode-python/pull/411)) +- Performance improvements to detection of virtual environments in current workspace ([#372](https://github.com/Microsoft/vscode-python/issues/372)) +- Correctly detect 64-bit python ([#414](https://github.com/Microsoft/vscode-python/issues/414)) +- Display parameter information while typing ([#70](https://github.com/Microsoft/vscode-python/issues/70)) +- Use `localhost` instead of `0.0.0.0` when starting debug servers ([#205](https://github.com/Microsoft/vscode-python/issues/205)) +- Ability to configure host name of debug server ([#227](https://github.com/Microsoft/vscode-python/issues/227)) +- Use environment variable PYTHONPATH defined in `.env` for intellisense and code navigation ([#316](https://github.com/Microsoft/vscode-python/issues/316)) +- Support path variable when debugging ([#436](https://github.com/Microsoft/vscode-python/issues/436)) +- Ensure virtual environments can be created in `.env` directory ([#435](https://github.com/Microsoft/vscode-python/issues/435), [#482](https://github.com/Microsoft/vscode-python/issues/482), [#486](https://github.com/Microsoft/vscode-python/issues/486)) +- Reload environment variables from `.env` without having to restart VS Code ([#183](https://github.com/Microsoft/vscode-python/issues/183)) +- Support debugging of Pyramid framework on Windows ([#519](https://github.com/Microsoft/vscode-python/issues/519)) +- Code snippet for `pubd` ([#545](https://github.com/Microsoft/vscode-python/issues/545)) +- Code clean up ([#353](https://github.com/Microsoft/vscode-python/issues/353), [#352](https://github.com/Microsoft/vscode-python/issues/352), [#354](https://github.com/Microsoft/vscode-python/issues/354), [#456](https://github.com/Microsoft/vscode-python/issues/456), [#491](https://github.com/Microsoft/vscode-python/issues/491), [#228](https://github.com/Microsoft/vscode-python/issues/228), [#549](https://github.com/Microsoft/vscode-python/issues/545), [#594](https://github.com/Microsoft/vscode-python/issues/594), [#617](https://github.com/Microsoft/vscode-python/issues/617), [#556](https://github.com/Microsoft/vscode-python/issues/556)) +- Move to `yarn` from `npm` ([#421](https://github.com/Microsoft/vscode-python/issues/421)) +- Add code coverage for extension itself ([#464](https://github.com/Microsoft/vscode-python/issues/464)) +- Releasing [insiders build](https://pvsc.blob.core.windows.net/extension-builds/ms-python-insiders.vsix) of the extension and uploading to cloud storage ([#429](https://github.com/Microsoft/vscode-python/issues/429)) +- Japanese translation ([#434](https://github.com/Microsoft/vscode-python/pull/434)) +- Russian translation ([#411](https://github.com/Microsoft/vscode-python/pull/411)) +- Support paths with spaces when generating tags with `Build Workspace Symbols` ([#44](https://github.com/Microsoft/vscode-python/issues/44)) +- Add ability to configure the linters ([#572](https://github.com/Microsoft/vscode-python/issues/572)) +- Add default set of rules for Pylint ([#554](https://github.com/Microsoft/vscode-python/issues/554)) +- Prompt to install formatter if not available ([#524](https://github.com/Microsoft/vscode-python/issues/524)) +- work around `editor.formatOnSave` failing when taking more then 750ms ([#124](https://github.com/Microsoft/vscode-python/issues/124), [#590](https://github.com/Microsoft/vscode-python/issues/590), [#624](https://github.com/Microsoft/vscode-python/issues/624), [#427](https://github.com/Microsoft/vscode-python/issues/427), [#492](https://github.com/Microsoft/vscode-python/issues/492)) +- Function argument completion no longer automatically includes the default argument ([#522](https://github.com/Microsoft/vscode-python/issues/522)) +- When sending a selection to the terminal, keep the focus in the editor window ([#60](https://github.com/Microsoft/vscode-python/issues/60)) +- Install packages for non-environment Pythons as `--user` installs ([#527](https://github.com/Microsoft/vscode-python/issues/527)) +- No longer suggest the system Python install on macOS when running `Select Interpreter` as it's too outdated (e.g. lacks `pip`) ([#440](https://github.com/Microsoft/vscode-python/issues/440)) +- Fix potential hang from Intellisense ([#423](https://github.com/Microsoft/vscode-python/issues/423)) ## Version 0.9.1 (19 December 2017) -* Fixes the compatibility issue with the [Visual Studio Code Tools for AI](https://marketplace.visualstudio.com/items?itemName=ms-toolsai.vscode-ai) [#432](https://github.com/Microsoft/vscode-python/issues/432) -* Display runtime errors encountered when running a python program without debugging [#454](https://github.com/Microsoft/vscode-python/issues/454) +- Fixes the compatibility issue with the [Visual Studio Code Tools for AI](https://marketplace.visualstudio.com/items?itemName=ms-toolsai.vscode-ai) [#432](https://github.com/Microsoft/vscode-python/issues/432) +- Display runtime errors encountered when running a python program without debugging [#454](https://github.com/Microsoft/vscode-python/issues/454) ## Version 0.9.0 (14 December 2017) -* Translated the commands to simplified Chinese [#240](https://github.com/Microsoft/vscode-python/pull/240) (thanks [Wai Sui kei](https://github.com/WaiSiuKei)) -* Change all links to point to their Python 3 equivalents instead of Python 2[#203](https://github.com/Microsoft/vscode-python/issues/203) -* Respect `{workspaceFolder}` [#258](https://github.com/Microsoft/vscode-python/issues/258) -* Running a program using Ctrl-F5 will work more than once [#25](https://github.com/Microsoft/vscode-python/issues/25) -* Removed the feedback service to rely on VS Code's own support (which fixed an issue of document reformatting failing) [#245](https://github.com/Microsoft/vscode-python/issues/245), [#303](https://github.com/Microsoft/vscode-python/issues/303), [#363](https://github.com/Microsoft/vscode-python/issues/365) -* Do not create empty '.vscode' directory [#253](https://github.com/Microsoft/vscode-python/issues/253), [#277](https://github.com/Microsoft/vscode-python/issues/277) -* Ensure python execution environment handles unicode characters [#393](https://github.com/Microsoft/vscode-python/issues/393) -* Remove Jupyter support in favour of the [Jupyter extension](https://marketplace.visualstudio.com/items?itemName=donjayamanne.jupyter) [#223](https://github.com/microsoft/vscode-python/issues/223) +- Translated the commands to simplified Chinese [#240](https://github.com/Microsoft/vscode-python/pull/240) (thanks [Wai Sui kei](https://github.com/WaiSiuKei)) +- Change all links to point to their Python 3 equivalents instead of Python 2[#203](https://github.com/Microsoft/vscode-python/issues/203) +- Respect `{workspaceFolder}` [#258](https://github.com/Microsoft/vscode-python/issues/258) +- Running a program using Ctrl-F5 will work more than once [#25](https://github.com/Microsoft/vscode-python/issues/25) +- Removed the feedback service to rely on VS Code's own support (which fixed an issue of document reformatting failing) [#245](https://github.com/Microsoft/vscode-python/issues/245), [#303](https://github.com/Microsoft/vscode-python/issues/303), [#363](https://github.com/Microsoft/vscode-python/issues/365) +- Do not create empty '.vscode' directory [#253](https://github.com/Microsoft/vscode-python/issues/253), [#277](https://github.com/Microsoft/vscode-python/issues/277) +- Ensure python execution environment handles unicode characters [#393](https://github.com/Microsoft/vscode-python/issues/393) +- Remove Jupyter support in favour of the [Jupyter extension](https://marketplace.visualstudio.com/items?itemName=donjayamanne.jupyter) [#223](https://github.com/microsoft/vscode-python/issues/223) ### `conda` -* Support installing Pylint using conda or pip when an Anaconda installation of Python is selected as the active interpreter [#301](https://github.com/Microsoft/vscode-python/issues/301) -* Add JSON schema support for conda's meta.yaml [#281](https://github.com/Microsoft/vscode-python/issues/281) -* Add JSON schema support for conda's environment.yml [#280](https://github.com/Microsoft/vscode-python/issues/280) -* Add JSON schema support for .condarc [#189](https://github.com/Microsoft/vscode-python/issues/280) -* Ensure company name 'Continuum Analytics' is replaced with 'Ananconda Inc' in the list of interpreters [#390](https://github.com/Microsoft/vscode-python/issues/390) -* Display the version of the interpreter instead of conda [#378](https://github.com/Microsoft/vscode-python/issues/378) -* Detect Anaconda on Linux even if it is not in the current path [#22](https://github.com/Microsoft/vscode-python/issues/22) +- Support installing Pylint using conda or pip when an Anaconda installation of Python is selected as the active interpreter [#301](https://github.com/Microsoft/vscode-python/issues/301) +- Add JSON schema support for conda's meta.yaml [#281](https://github.com/Microsoft/vscode-python/issues/281) +- Add JSON schema support for conda's environment.yml [#280](https://github.com/Microsoft/vscode-python/issues/280) +- Add JSON schema support for .condarc [#189](https://github.com/Microsoft/vscode-python/issues/280) +- Ensure company name 'Continuum Analytics' is replaced with 'Ananconda Inc' in the list of interpreters [#390](https://github.com/Microsoft/vscode-python/issues/390) +- Display the version of the interpreter instead of conda [#378](https://github.com/Microsoft/vscode-python/issues/378) +- Detect Anaconda on Linux even if it is not in the current path [#22](https://github.com/Microsoft/vscode-python/issues/22) ### Interpreter selection -* Fixes in the discovery and display of interpreters, including virtual environments [#56](https://github.com/Microsoft/vscode-python/issues/56) -* Retrieve the right value from the registry when determining the version of an interpreter on Windows [#389](https://github.com/Microsoft/vscode-python/issues/389) +- Fixes in the discovery and display of interpreters, including virtual environments [#56](https://github.com/Microsoft/vscode-python/issues/56) +- Retrieve the right value from the registry when determining the version of an interpreter on Windows [#389](https://github.com/Microsoft/vscode-python/issues/389) ### Intellisense -* Fetch intellisense details on-demand instead of for all possible completions [#152](https://github.com/Microsoft/vscode-python/issues/152) -* Disable auto completion in comments and strings [#110](https://github.com/Microsoft/vscode-python/issues/110), [#921](https://github.com/Microsoft/vscode-python/issues/921), [#34](https://github.com/Microsoft/vscode-python/issues/34) +- Fetch intellisense details on-demand instead of for all possible completions [#152](https://github.com/Microsoft/vscode-python/issues/152) +- Disable auto completion in comments and strings [#110](https://github.com/Microsoft/vscode-python/issues/110), [#921](https://github.com/Microsoft/vscode-python/issues/921), [#34](https://github.com/Microsoft/vscode-python/issues/34) ### Linting -* Deprecate `python.linting.lintOnTextChange` [#313](https://github.com/Microsoft/vscode-python/issues/313), [#297](https://github.com/Microsoft/vscode-python/issues/297), [#28](https://github.com/Microsoft/vscode-python/issues/28), [#272](https://github.com/Microsoft/vscode-python/issues/272) -* Refactor code for executing linters (fixes running the proper linter under the selected interpreter) [#351](https://github.com/Microsoft/vscode-python/issues/351), [#397](https://github.com/Microsoft/vscode-python/issues/397) -* Don't attempt to install linters when not in a workspace [#42](https://github.com/Microsoft/vscode-python/issues/42) -* Honour `python.linting.enabled` [#26](https://github.com/Microsoft/vscode-python/issues/26) -* Don't display message 'Linter pylint is not installed' when changing settings [#260](https://github.com/Microsoft/vscode-python/issues/260) -* Display a meaningful message if pip is unavailable to install necessary module such as 'pylint' [#266](https://github.com/Microsoft/vscode-python/issues/266) -* Improvement environment variable parsing in the debugging (allows for embedded `=`) [#149](https://github.com/Microsoft/vscode-python/issues/149), [#361](https://github.com/Microsoft/vscode-python/issues/361) +- Deprecate `python.linting.lintOnTextChange` [#313](https://github.com/Microsoft/vscode-python/issues/313), [#297](https://github.com/Microsoft/vscode-python/issues/297), [#28](https://github.com/Microsoft/vscode-python/issues/28), [#272](https://github.com/Microsoft/vscode-python/issues/272) +- Refactor code for executing linters (fixes running the proper linter under the selected interpreter) [#351](https://github.com/Microsoft/vscode-python/issues/351), [#397](https://github.com/Microsoft/vscode-python/issues/397) +- Don't attempt to install linters when not in a workspace [#42](https://github.com/Microsoft/vscode-python/issues/42) +- Honour `python.linting.enabled` [#26](https://github.com/Microsoft/vscode-python/issues/26) +- Don't display message 'Linter pylint is not installed' when changing settings [#260](https://github.com/Microsoft/vscode-python/issues/260) +- Display a meaningful message if pip is unavailable to install necessary module such as 'pylint' [#266](https://github.com/Microsoft/vscode-python/issues/266) +- Improvement environment variable parsing in the debugging (allows for embedded `=`) [#149](https://github.com/Microsoft/vscode-python/issues/149), [#361](https://github.com/Microsoft/vscode-python/issues/361) ### Debugging -* Improve selecting the port used when debugging [#304](https://github.com/Microsoft/vscode-python/pull/304) -* Don't block debugging in other extensions [#58](https://github.com/Microsoft/vscode-python/issues/58) -* Don't trigger an error to the Console Window when trying to debug an invalid Python file [#157](https://github.com/Microsoft/vscode-python/issues/157) -* No longer prompt to `Press any key to continue . . .` once debugging finishes [#239](https://github.com/Microsoft/vscode-python/issues/239) -* Do not start the extension when debugging non-Python projects [#57](https://github.com/Microsoft/vscode-python/issues/57) -* Support custom external terminals in debugger [#250](https://github.com/Microsoft/vscode-python/issues/250), [#114](https://github.com/Microsoft/vscode-python/issues/114) -* Debugging a python program should not display the message 'Cannot read property …' [#247](https://github.com/Microsoft/vscode-python/issues/247) +- Improve selecting the port used when debugging [#304](https://github.com/Microsoft/vscode-python/pull/304) +- Don't block debugging in other extensions [#58](https://github.com/Microsoft/vscode-python/issues/58) +- Don't trigger an error to the Console Window when trying to debug an invalid Python file [#157](https://github.com/Microsoft/vscode-python/issues/157) +- No longer prompt to `Press any key to continue . . .` once debugging finishes [#239](https://github.com/Microsoft/vscode-python/issues/239) +- Do not start the extension when debugging non-Python projects [#57](https://github.com/Microsoft/vscode-python/issues/57) +- Support custom external terminals in debugger [#250](https://github.com/Microsoft/vscode-python/issues/250), [#114](https://github.com/Microsoft/vscode-python/issues/114) +- Debugging a python program should not display the message 'Cannot read property …' [#247](https://github.com/Microsoft/vscode-python/issues/247) ### Testing -* Refactor unit test library execution code [#350](https://github.com/Microsoft/vscode-python/issues/350) +- Refactor unit test library execution code [#350](https://github.com/Microsoft/vscode-python/issues/350) ### Formatting -* Deprecate the setting `python.formatting.formatOnSave` with an appropriate message [#285](https://github.com/Microsoft/vscode-python/issues/285), [#309](https://github.com/Microsoft/vscode-python/issues/309) +- Deprecate the setting `python.formatting.formatOnSave` with an appropriate message [#285](https://github.com/Microsoft/vscode-python/issues/285), [#309](https://github.com/Microsoft/vscode-python/issues/309) ## Version 0.8.0 (9 November 2017) -* Add support for multi-root workspaces [#1228](https://github.com/DonJayamanne/pythonVSCode/issues/1228), [#1302](https://github.com/DonJayamanne/pythonVSCode/pull/1302), [#1328](https://github.com/DonJayamanne/pythonVSCode/issues/1328), [#1357](https://github.com/DonJayamanne/pythonVSCode/pull/1357) -* Add code snippet for ```ipdb``` [#1141](https://github.com/DonJayamanne/pythonVSCode/pull/1141) -* Add ability to resolving environment variables in path to ```mypy``` [#1195](https://github.com/DonJayamanne/pythonVSCode/issues/1195) -* Add ability to disable a linter globally and disable prompts to install linters [#1207](https://github.com/DonJayamanne/pythonVSCode/issues/1207) -* Auto-selecting an interpreter from a virtual environment if only one is found in the root directory of the project [#1216](https://github.com/DonJayamanne/pythonVSCode/issues/1216) -* Add support for specifying the working directory for unit tests [#1155](https://github.com/DonJayamanne/pythonVSCode/issues/1155), [#1185](https://github.com/DonJayamanne/pythonVSCode/issues/1185) -* Add syntax highlighting of pip requirements files [#1247](https://github.com/DonJayamanne/pythonVSCode/pull/1247) -* Add ability to select an interpreter even when a workspace is not open [#1260](https://github.com/DonJayamanne/pythonVSCode/issues/1260), [#1263](https://github.com/DonJayamanne/pythonVSCode/pull/1263) -* Display a code lens to change the selected interpreter to the one specified in the shebang line [#1257](https://github.com/DonJayamanne/pythonVSCode/pull/1257), [#1263](https://github.com/DonJayamanne/pythonVSCode/pull/1263), [#1267](https://github.com/DonJayamanne/pythonVSCode/pull/1267), [#1280](https://github.com/DonJayamanne/pythonVSCode/issues/1280), [#1261](https://github.com/DonJayamanne/pythonVSCode/issues/1261), [#1290](https://github.com/DonJayamanne/pythonVSCode/pull/1290) -* Expand list of interpreters displayed for selection [#1147](https://github.com/DonJayamanne/pythonVSCode/issues/1147), [#1148](https://github.com/DonJayamanne/pythonVSCode/issues/1148), [#1224](https://github.com/DonJayamanne/pythonVSCode/pull/1224), [#1240](https://github.com/DonJayamanne/pythonVSCode/pull/1240) -* Display details of current or selected interpreter in statusbar [#1147](https://github.com/DonJayamanne/pythonVSCode/issues/1147), [#1217](https://github.com/DonJayamanne/pythonVSCode/issues/1217) -* Ensure paths in workspace symbols are not prefixed with ```.vscode``` [#816](https://github.com/DonJayamanne/pythonVSCode/issues/816), [#1066](https://github.com/DonJayamanne/pythonVSCode/pull/1066), [#829](https://github.com/DonJayamanne/pythonVSCode/issues/829) -* Ensure paths in ```PYTHONPATH``` environment variable are delimited using the OS-specific path delimiter [#832](https://github.com/DonJayamanne/pythonVSCode/issues/832) -* Ensure ```Rope``` is not packaged with the extension [#1208](https://github.com/DonJayamanne/pythonVSCode/issues/1208), [#1207](https://github.com/DonJayamanne/pythonVSCode/issues/1207), [#1243](https://github.com/DonJayamanne/pythonVSCode/pull/1243), [#1229](https://github.com/DonJayamanne/pythonVSCode/issues/1229) -* Ensure ctags are rebuilt as expected upon file save [#624](https://github.com/DonJayamanne/pythonVSCode/issues/1212) -* Ensure right test method is executed when two test methods exist with the same name in different classes [#1203](https://github.com/DonJayamanne/pythonVSCode/issues/1203) -* Ensure unit tests run successfully on Travis for both Python 2.7 and 3.6 [#1255](https://github.com/DonJayamanne/pythonVSCode/pull/1255), [#1241](https://github.com/DonJayamanne/pythonVSCode/issues/1241), [#1315](https://github.com/DonJayamanne/pythonVSCode/issues/1315) -* Fix building of ctags when a path contains a space [#1064](https://github.com/DonJayamanne/pythonVSCode/issues/1064), [#1144](https://github.com/DonJayamanne/pythonVSCode/issues/1144),, [#1213](https://github.com/DonJayamanne/pythonVSCode/pull/1213) -* Fix autocompletion in unsaved Python files [#1194](https://github.com/DonJayamanne/pythonVSCode/issues/1194) -* Fix running of test methods in nose [#597](https://github.com/DonJayamanne/pythonVSCode/issues/597), [#1225](https://github.com/DonJayamanne/pythonVSCode/pull/1225) -* Fix to disable linting of diff windows [#1221](https://github.com/DonJayamanne/pythonVSCode/issues/1221), [#1244](https://github.com/DonJayamanne/pythonVSCode/pull/1244) -* Fix docstring formatting [#1188](https://github.com/DonJayamanne/pythonVSCode/issues/1188) -* Fix to ensure language features can run in parallel without interference with one another [#1314](https://github.com/DonJayamanne/pythonVSCode/issues/1314), [#1318](https://github.com/DonJayamanne/pythonVSCode/pull/1318) -* Fix to ensure unit tests can be debugged more than once per run [#948](https://github.com/DonJayamanne/pythonVSCode/issues/948), [#1353](https://github.com/DonJayamanne/pythonVSCode/pull/1353) -* Fix to ensure parameterized unit tests can be debugged [#1284](https://github.com/DonJayamanne/pythonVSCode/issues/1284), [#1299](https://github.com/DonJayamanne/pythonVSCode/pull/1299) -* Fix issue that causes debugger to freeze/hang [#1041](https://github.com/DonJayamanne/pythonVSCode/issues/1041), [#1354](https://github.com/DonJayamanne/pythonVSCode/pull/1354) -* Fix to support unicode characters in Python tests [#1282](https://github.com/DonJayamanne/pythonVSCode/issues/1282), [#1291](https://github.com/DonJayamanne/pythonVSCode/pull/1291) -* Changes as a result of VS Code API changes [#1270](https://github.com/DonJayamanne/pythonVSCode/issues/1270), [#1288](https://github.com/DonJayamanne/pythonVSCode/pull/1288), [#1372](https://github.com/DonJayamanne/pythonVSCode/issues/1372), [#1300](https://github.com/DonJayamanne/pythonVSCode/pull/1300), [#1298](https://github.com/DonJayamanne/pythonVSCode/issues/1298) -* Updates to Readme [#1212](https://github.com/DonJayamanne/pythonVSCode/issues/1212), [#1222](https://github.com/DonJayamanne/pythonVSCode/issues/1222) -* Fix executing a command under PowerShell [#1098](https://github.com/DonJayamanne/pythonVSCode/issues/1098) +- Add support for multi-root workspaces [#1228](https://github.com/DonJayamanne/pythonVSCode/issues/1228), [#1302](https://github.com/DonJayamanne/pythonVSCode/pull/1302), [#1328](https://github.com/DonJayamanne/pythonVSCode/issues/1328), [#1357](https://github.com/DonJayamanne/pythonVSCode/pull/1357) +- Add code snippet for `ipdb` [#1141](https://github.com/DonJayamanne/pythonVSCode/pull/1141) +- Add ability to resolving environment variables in path to `mypy` [#1195](https://github.com/DonJayamanne/pythonVSCode/issues/1195) +- Add ability to disable a linter globally and disable prompts to install linters [#1207](https://github.com/DonJayamanne/pythonVSCode/issues/1207) +- Auto-selecting an interpreter from a virtual environment if only one is found in the root directory of the project [#1216](https://github.com/DonJayamanne/pythonVSCode/issues/1216) +- Add support for specifying the working directory for unit tests [#1155](https://github.com/DonJayamanne/pythonVSCode/issues/1155), [#1185](https://github.com/DonJayamanne/pythonVSCode/issues/1185) +- Add syntax highlighting of pip requirements files [#1247](https://github.com/DonJayamanne/pythonVSCode/pull/1247) +- Add ability to select an interpreter even when a workspace is not open [#1260](https://github.com/DonJayamanne/pythonVSCode/issues/1260), [#1263](https://github.com/DonJayamanne/pythonVSCode/pull/1263) +- Display a code lens to change the selected interpreter to the one specified in the shebang line [#1257](https://github.com/DonJayamanne/pythonVSCode/pull/1257), [#1263](https://github.com/DonJayamanne/pythonVSCode/pull/1263), [#1267](https://github.com/DonJayamanne/pythonVSCode/pull/1267), [#1280](https://github.com/DonJayamanne/pythonVSCode/issues/1280), [#1261](https://github.com/DonJayamanne/pythonVSCode/issues/1261), [#1290](https://github.com/DonJayamanne/pythonVSCode/pull/1290) +- Expand list of interpreters displayed for selection [#1147](https://github.com/DonJayamanne/pythonVSCode/issues/1147), [#1148](https://github.com/DonJayamanne/pythonVSCode/issues/1148), [#1224](https://github.com/DonJayamanne/pythonVSCode/pull/1224), [#1240](https://github.com/DonJayamanne/pythonVSCode/pull/1240) +- Display details of current or selected interpreter in statusbar [#1147](https://github.com/DonJayamanne/pythonVSCode/issues/1147), [#1217](https://github.com/DonJayamanne/pythonVSCode/issues/1217) +- Ensure paths in workspace symbols are not prefixed with `.vscode` [#816](https://github.com/DonJayamanne/pythonVSCode/issues/816), [#1066](https://github.com/DonJayamanne/pythonVSCode/pull/1066), [#829](https://github.com/DonJayamanne/pythonVSCode/issues/829) +- Ensure paths in `PYTHONPATH` environment variable are delimited using the OS-specific path delimiter [#832](https://github.com/DonJayamanne/pythonVSCode/issues/832) +- Ensure `Rope` is not packaged with the extension [#1208](https://github.com/DonJayamanne/pythonVSCode/issues/1208), [#1207](https://github.com/DonJayamanne/pythonVSCode/issues/1207), [#1243](https://github.com/DonJayamanne/pythonVSCode/pull/1243), [#1229](https://github.com/DonJayamanne/pythonVSCode/issues/1229) +- Ensure ctags are rebuilt as expected upon file save [#624](https://github.com/DonJayamanne/pythonVSCode/issues/1212) +- Ensure right test method is executed when two test methods exist with the same name in different classes [#1203](https://github.com/DonJayamanne/pythonVSCode/issues/1203) +- Ensure unit tests run successfully on Travis for both Python 2.7 and 3.6 [#1255](https://github.com/DonJayamanne/pythonVSCode/pull/1255), [#1241](https://github.com/DonJayamanne/pythonVSCode/issues/1241), [#1315](https://github.com/DonJayamanne/pythonVSCode/issues/1315) +- Fix building of ctags when a path contains a space [#1064](https://github.com/DonJayamanne/pythonVSCode/issues/1064), [#1144](https://github.com/DonJayamanne/pythonVSCode/issues/1144),, [#1213](https://github.com/DonJayamanne/pythonVSCode/pull/1213) +- Fix autocompletion in unsaved Python files [#1194](https://github.com/DonJayamanne/pythonVSCode/issues/1194) +- Fix running of test methods in nose [#597](https://github.com/DonJayamanne/pythonVSCode/issues/597), [#1225](https://github.com/DonJayamanne/pythonVSCode/pull/1225) +- Fix to disable linting of diff windows [#1221](https://github.com/DonJayamanne/pythonVSCode/issues/1221), [#1244](https://github.com/DonJayamanne/pythonVSCode/pull/1244) +- Fix docstring formatting [#1188](https://github.com/DonJayamanne/pythonVSCode/issues/1188) +- Fix to ensure language features can run in parallel without interference with one another [#1314](https://github.com/DonJayamanne/pythonVSCode/issues/1314), [#1318](https://github.com/DonJayamanne/pythonVSCode/pull/1318) +- Fix to ensure unit tests can be debugged more than once per run [#948](https://github.com/DonJayamanne/pythonVSCode/issues/948), [#1353](https://github.com/DonJayamanne/pythonVSCode/pull/1353) +- Fix to ensure parameterized unit tests can be debugged [#1284](https://github.com/DonJayamanne/pythonVSCode/issues/1284), [#1299](https://github.com/DonJayamanne/pythonVSCode/pull/1299) +- Fix issue that causes debugger to freeze/hang [#1041](https://github.com/DonJayamanne/pythonVSCode/issues/1041), [#1354](https://github.com/DonJayamanne/pythonVSCode/pull/1354) +- Fix to support unicode characters in Python tests [#1282](https://github.com/DonJayamanne/pythonVSCode/issues/1282), [#1291](https://github.com/DonJayamanne/pythonVSCode/pull/1291) +- Changes as a result of VS Code API changes [#1270](https://github.com/DonJayamanne/pythonVSCode/issues/1270), [#1288](https://github.com/DonJayamanne/pythonVSCode/pull/1288), [#1372](https://github.com/DonJayamanne/pythonVSCode/issues/1372), [#1300](https://github.com/DonJayamanne/pythonVSCode/pull/1300), [#1298](https://github.com/DonJayamanne/pythonVSCode/issues/1298) +- Updates to Readme [#1212](https://github.com/DonJayamanne/pythonVSCode/issues/1212), [#1222](https://github.com/DonJayamanne/pythonVSCode/issues/1222) +- Fix executing a command under PowerShell [#1098](https://github.com/DonJayamanne/pythonVSCode/issues/1098) ## Version 0.7.0 (3 August 2017) -* Displaying internal documentation [#1008](https://github.com/DonJayamanne/pythonVSCode/issues/1008), [#10860](https://github.com/DonJayamanne/pythonVSCode/issues/10860) -* Fixes to 'async with' snippet [#1108](https://github.com/DonJayamanne/pythonVSCode/pull/1108), [#996](https://github.com/DonJayamanne/pythonVSCode/issues/996) -* Add support for environment variable in unit tests [#1074](https://github.com/DonJayamanne/pythonVSCode/issues/1074) -* Fixes to unit test code lenses not being displayed [#1115](https://github.com/DonJayamanne/pythonVSCode/issues/1115) -* Fix to empty brackets being added [#1110](https://github.com/DonJayamanne/pythonVSCode/issues/1110), [#1031](https://github.com/DonJayamanne/pythonVSCode/issues/1031) -* Fix debugging of Django applications [#819](https://github.com/DonJayamanne/pythonVSCode/issues/819), [#999](https://github.com/DonJayamanne/pythonVSCode/issues/999) -* Update isort to the latest version [#1134](https://github.com/DonJayamanne/pythonVSCode/issues/1134), [#1135](https://github.com/DonJayamanne/pythonVSCode/pull/1135) -* Fix issue causing intellisense and similar functionality to stop working [#1072](https://github.com/DonJayamanne/pythonVSCode/issues/1072), [#1118](https://github.com/DonJayamanne/pythonVSCode/pull/1118), [#1089](https://github.com/DonJayamanne/pythonVSCode/issues/1089) -* Bunch of unit tests and code cleanup -* Resolve issue where navigation to decorated function goes to decorator [#742](https://github.com/DonJayamanne/pythonVSCode/issues/742) -* Go to symbol in workspace leads to nonexisting files [#816](https://github.com/DonJayamanne/pythonVSCode/issues/816), [#829](https://github.com/DonJayamanne/pythonVSCode/issues/829) + +- Displaying internal documentation [#1008](https://github.com/DonJayamanne/pythonVSCode/issues/1008), [#10860](https://github.com/DonJayamanne/pythonVSCode/issues/10860) +- Fixes to 'async with' snippet [#1108](https://github.com/DonJayamanne/pythonVSCode/pull/1108), [#996](https://github.com/DonJayamanne/pythonVSCode/issues/996) +- Add support for environment variable in unit tests [#1074](https://github.com/DonJayamanne/pythonVSCode/issues/1074) +- Fixes to unit test code lenses not being displayed [#1115](https://github.com/DonJayamanne/pythonVSCode/issues/1115) +- Fix to empty brackets being added [#1110](https://github.com/DonJayamanne/pythonVSCode/issues/1110), [#1031](https://github.com/DonJayamanne/pythonVSCode/issues/1031) +- Fix debugging of Django applications [#819](https://github.com/DonJayamanne/pythonVSCode/issues/819), [#999](https://github.com/DonJayamanne/pythonVSCode/issues/999) +- Update isort to the latest version [#1134](https://github.com/DonJayamanne/pythonVSCode/issues/1134), [#1135](https://github.com/DonJayamanne/pythonVSCode/pull/1135) +- Fix issue causing intellisense and similar functionality to stop working [#1072](https://github.com/DonJayamanne/pythonVSCode/issues/1072), [#1118](https://github.com/DonJayamanne/pythonVSCode/pull/1118), [#1089](https://github.com/DonJayamanne/pythonVSCode/issues/1089) +- Bunch of unit tests and code cleanup +- Resolve issue where navigation to decorated function goes to decorator [#742](https://github.com/DonJayamanne/pythonVSCode/issues/742) +- Go to symbol in workspace leads to nonexisting files [#816](https://github.com/DonJayamanne/pythonVSCode/issues/816), [#829](https://github.com/DonJayamanne/pythonVSCode/issues/829) ## Version 0.6.9 (22 July 2017) -* Fix to enure custom linter paths are respected [#1106](https://github.com/DonJayamanne/pythonVSCode/issues/1106) + +- Fix to enure custom linter paths are respected [#1106](https://github.com/DonJayamanne/pythonVSCode/issues/1106) ## Version 0.6.8 (20 July 2017) -* Add new editor menu 'Run Current Unit Test File' [#1061](https://github.com/DonJayamanne/pythonVSCode/issues/1061) -* Changed 'mypy-lang' to mypy [#930](https://github.com/DonJayamanne/pythonVSCode/issues/930), [#998](https://github.com/DonJayamanne/pythonVSCode/issues/998), [#505](https://github.com/DonJayamanne/pythonVSCode/issues/505) -* Using "Python -m" to launch linters [#716](https://github.com/DonJayamanne/pythonVSCode/issues/716), [#923](https://github.com/DonJayamanne/pythonVSCode/issues/923), [#1059](https://github.com/DonJayamanne/pythonVSCode/issues/1059) -* Add PEP 526 AutoCompletion [#1102](https://github.com/DonJayamanne/pythonVSCode/pull/1102), [#1101](https://github.com/DonJayamanne/pythonVSCode/issues/1101) -* Resolved issues in Go To and Peek Definitions [#1085](https://github.com/DonJayamanne/pythonVSCode/pull/1085), [#961](https://github.com/DonJayamanne/pythonVSCode/issues/961), [#870](https://github.com/DonJayamanne/pythonVSCode/issues/870) + +- Add new editor menu 'Run Current Unit Test File' [#1061](https://github.com/DonJayamanne/pythonVSCode/issues/1061) +- Changed 'mypy-lang' to mypy [#930](https://github.com/DonJayamanne/pythonVSCode/issues/930), [#998](https://github.com/DonJayamanne/pythonVSCode/issues/998), [#505](https://github.com/DonJayamanne/pythonVSCode/issues/505) +- Using "Python -m" to launch linters [#716](https://github.com/DonJayamanne/pythonVSCode/issues/716), [#923](https://github.com/DonJayamanne/pythonVSCode/issues/923), [#1059](https://github.com/DonJayamanne/pythonVSCode/issues/1059) +- Add PEP 526 AutoCompletion [#1102](https://github.com/DonJayamanne/pythonVSCode/pull/1102), [#1101](https://github.com/DonJayamanne/pythonVSCode/issues/1101) +- Resolved issues in Go To and Peek Definitions [#1085](https://github.com/DonJayamanne/pythonVSCode/pull/1085), [#961](https://github.com/DonJayamanne/pythonVSCode/issues/961), [#870](https://github.com/DonJayamanne/pythonVSCode/issues/870) ## Version 0.6.7 (02 July 2017) -* Updated icon from jpg to png (transparent background) + +- Updated icon from jpg to png (transparent background) ## Version 0.6.6 (02 July 2017) -* Provide details of error with solution for changes to syntax in launch.json [#1047](https://github.com/DonJayamanne/pythonVSCode/issues/1047), [#1025](https://github.com/DonJayamanne/pythonVSCode/issues/1025) -* Provide a warning about known issues with having pyenv.cfg whilst debugging [#913](https://github.com/DonJayamanne/pythonVSCode/issues/913) -* Create .vscode directory if not found [#1043](https://github.com/DonJayamanne/pythonVSCode/issues/1043) -* Highlighted text due to linter errors is off by one column [#965](https://github.com/DonJayamanne/pythonVSCode/issues/965), [#970](https://github.com/DonJayamanne/pythonVSCode/pull/970) -* Added preliminary support for WSL Bash and Cygwin [#1049](https://github.com/DonJayamanne/pythonVSCode/pull/1049) -* Ability to configure the linter severity levels [#941](https://github.com/DonJayamanne/pythonVSCode/pull/941), [#895](https://github.com/DonJayamanne/pythonVSCode/issues/895) -* Fixes to unit tests [#1051](https://github.com/DonJayamanne/pythonVSCode/pull/1051), [#1050](https://github.com/DonJayamanne/pythonVSCode/pull/1050) -* Outdent lines following `continue`, `break` and `return` [#1050](https://github.com/DonJayamanne/pythonVSCode/pull/1050) -* Change location of cache for Jedi files [#1035](https://github.com/DonJayamanne/pythonVSCode/pull/1035) -* Fixes to the way directories are searched for Python interpreters [#569](https://github.com/DonJayamanne/pythonVSCode/issues/569), [#1040](https://github.com/DonJayamanne/pythonVSCode/pull/1040) -* Handle outputs from Python packages that interfere with the way autocompletion is handled [#602](https://github.com/DonJayamanne/pythonVSCode/issues/602) + +- Provide details of error with solution for changes to syntax in launch.json [#1047](https://github.com/DonJayamanne/pythonVSCode/issues/1047), [#1025](https://github.com/DonJayamanne/pythonVSCode/issues/1025) +- Provide a warning about known issues with having pyenv.cfg whilst debugging [#913](https://github.com/DonJayamanne/pythonVSCode/issues/913) +- Create .vscode directory if not found [#1043](https://github.com/DonJayamanne/pythonVSCode/issues/1043) +- Highlighted text due to linter errors is off by one column [#965](https://github.com/DonJayamanne/pythonVSCode/issues/965), [#970](https://github.com/DonJayamanne/pythonVSCode/pull/970) +- Added preliminary support for WSL Bash and Cygwin [#1049](https://github.com/DonJayamanne/pythonVSCode/pull/1049) +- Ability to configure the linter severity levels [#941](https://github.com/DonJayamanne/pythonVSCode/pull/941), [#895](https://github.com/DonJayamanne/pythonVSCode/issues/895) +- Fixes to unit tests [#1051](https://github.com/DonJayamanne/pythonVSCode/pull/1051), [#1050](https://github.com/DonJayamanne/pythonVSCode/pull/1050) +- Outdent lines following `continue`, `break` and `return` [#1050](https://github.com/DonJayamanne/pythonVSCode/pull/1050) +- Change location of cache for Jedi files [#1035](https://github.com/DonJayamanne/pythonVSCode/pull/1035) +- Fixes to the way directories are searched for Python interpreters [#569](https://github.com/DonJayamanne/pythonVSCode/issues/569), [#1040](https://github.com/DonJayamanne/pythonVSCode/pull/1040) +- Handle outputs from Python packages that interfere with the way autocompletion is handled [#602](https://github.com/DonJayamanne/pythonVSCode/issues/602) ## Version 0.6.5 (13 June 2017) -* Fix error in launch.json [#1006](https://github.com/DonJayamanne/pythonVSCode/issues/1006) -* Detect current workspace interpreter when selecting interpreter [#1006](https://github.com/DonJayamanne/pythonVSCode/issues/979) -* Disable output buffering when debugging [#1005](https://github.com/DonJayamanne/pythonVSCode/issues/1005) -* Updated snippets to use correct placeholder syntax [#976](https://github.com/DonJayamanne/pythonVSCode/pull/976) -* Fix hover and auto complete unit tests [#1012](https://github.com/DonJayamanne/pythonVSCode/pull/1012) -* Fix hover definition variable test for Python 3.5 [#1013](https://github.com/DonJayamanne/pythonVSCode/pull/1013) -* Better formatting of docstring [#821](https://github.com/DonJayamanne/pythonVSCode/pull/821), [#919](https://github.com/DonJayamanne/pythonVSCode/pull/919) -* Supporting more paths when searching for Python interpreters [#569](https://github.com/DonJayamanne/pythonVSCode/issues/569) -* Increase buffer output (to support detection large number of tests) [#927](https://github.com/DonJayamanne/pythonVSCode/issues/927) + +- Fix error in launch.json [#1006](https://github.com/DonJayamanne/pythonVSCode/issues/1006) +- Detect current workspace interpreter when selecting interpreter [#1006](https://github.com/DonJayamanne/pythonVSCode/issues/979) +- Disable output buffering when debugging [#1005](https://github.com/DonJayamanne/pythonVSCode/issues/1005) +- Updated snippets to use correct placeholder syntax [#976](https://github.com/DonJayamanne/pythonVSCode/pull/976) +- Fix hover and auto complete unit tests [#1012](https://github.com/DonJayamanne/pythonVSCode/pull/1012) +- Fix hover definition variable test for Python 3.5 [#1013](https://github.com/DonJayamanne/pythonVSCode/pull/1013) +- Better formatting of docstring [#821](https://github.com/DonJayamanne/pythonVSCode/pull/821), [#919](https://github.com/DonJayamanne/pythonVSCode/pull/919) +- Supporting more paths when searching for Python interpreters [#569](https://github.com/DonJayamanne/pythonVSCode/issues/569) +- Increase buffer output (to support detection large number of tests) [#927](https://github.com/DonJayamanne/pythonVSCode/issues/927) ## Version 0.6.4 (4 May 2017) -* Fix dates in changelog [#899](https://github.com/DonJayamanne/pythonVSCode/pull/899) -* Using charriage return or line feeds to split a document into multiple lines [#917](https://github.com/DonJayamanne/pythonVSCode/pull/917), [#821](https://github.com/DonJayamanne/pythonVSCode/issues/821) -* Doc string not being displayed [#888](https://github.com/DonJayamanne/pythonVSCode/issues/888) -* Supporting paths that begin with the ~/ [#909](https://github.com/DonJayamanne/pythonVSCode/issues/909) -* Supporting more paths when searching for Python interpreters [#569](https://github.com/DonJayamanne/pythonVSCode/issues/569) -* Supporting ~/ paths when providing the path to ctag file [#910](https://github.com/DonJayamanne/pythonVSCode/issues/910) -* Disable linting of python files opened in diff viewer [#896](https://github.com/DonJayamanne/pythonVSCode/issues/896) -* Added a new command ```Go to Python Object``` [#928](https://github.com/DonJayamanne/pythonVSCode/issues/928) -* Restored the menu item to rediscover tests [#863](https://github.com/DonJayamanne/pythonVSCode/issues/863) -* Changes to rediscover tests when test files are altered and saved [#863](https://github.com/DonJayamanne/pythonVSCode/issues/863) + +- Fix dates in changelog [#899](https://github.com/DonJayamanne/pythonVSCode/pull/899) +- Using charriage return or line feeds to split a document into multiple lines [#917](https://github.com/DonJayamanne/pythonVSCode/pull/917), [#821](https://github.com/DonJayamanne/pythonVSCode/issues/821) +- Doc string not being displayed [#888](https://github.com/DonJayamanne/pythonVSCode/issues/888) +- Supporting paths that begin with the ~/ [#909](https://github.com/DonJayamanne/pythonVSCode/issues/909) +- Supporting more paths when searching for Python interpreters [#569](https://github.com/DonJayamanne/pythonVSCode/issues/569) +- Supporting ~/ paths when providing the path to ctag file [#910](https://github.com/DonJayamanne/pythonVSCode/issues/910) +- Disable linting of python files opened in diff viewer [#896](https://github.com/DonJayamanne/pythonVSCode/issues/896) +- Added a new command `Go to Python Object` [#928](https://github.com/DonJayamanne/pythonVSCode/issues/928) +- Restored the menu item to rediscover tests [#863](https://github.com/DonJayamanne/pythonVSCode/issues/863) +- Changes to rediscover tests when test files are altered and saved [#863](https://github.com/DonJayamanne/pythonVSCode/issues/863) ## Version 0.6.3 (19 April 2017) -* Fix debugger issue [#893](https://github.com/DonJayamanne/pythonVSCode/issues/893) -* Improvements to debugging unit tests (check if string starts with, instead of comparing equality) [#797](https://github.com/DonJayamanne/pythonVSCode/issues/797) + +- Fix debugger issue [#893](https://github.com/DonJayamanne/pythonVSCode/issues/893) +- Improvements to debugging unit tests (check if string starts with, instead of comparing equality) [#797](https://github.com/DonJayamanne/pythonVSCode/issues/797) ## Version 0.6.2 (13 April 2017) -* Fix incorrect indenting [#880](https://github.com/DonJayamanne/pythonVSCode/issues/880) + +- Fix incorrect indenting [#880](https://github.com/DonJayamanne/pythonVSCode/issues/880) ### Thanks -* [Yuwei Ba](https://github.com/ibigbug) + +- [Yuwei Ba](https://github.com/ibigbug) ## Version 0.6.1 (10 April 2017) -* Add support for new variable syntax in upcoming VS Code release [#774](https://github.com/DonJayamanne/pythonVSCode/issues/774), [#855](https://github.com/DonJayamanne/pythonVSCode/issues/855), [#873](https://github.com/DonJayamanne/pythonVSCode/issues/873), [#823](https://github.com/DonJayamanne/pythonVSCode/issues/823) -* Resolve issues in code refactoring [#802](https://github.com/DonJayamanne/pythonVSCode/issues/802), [#824](https://github.com/DonJayamanne/pythonVSCode/issues/824), [#825](https://github.com/DonJayamanne/pythonVSCode/pull/825) -* Changes to labels in Python Interpreter lookup [#815](https://github.com/DonJayamanne/pythonVSCode/pull/815) -* Resolve Typos [#852](https://github.com/DonJayamanne/pythonVSCode/issues/852) -* Use fully qualitified Python Path when installing dependencies [#866](https://github.com/DonJayamanne/pythonVSCode/issues/866) -* Commands for running tests from a file [#502](https://github.com/DonJayamanne/pythonVSCode/pull/502) -* Fix Sorting of imports when path contains spaces [#811](https://github.com/DonJayamanne/pythonVSCode/issues/811) -* Fixing occasional failure of linters [#793](https://github.com/DonJayamanne/pythonVSCode/issues/793), [#833](https://github.com/DonJayamanne/pythonVSCode/issues/838), [#860](https://github.com/DonJayamanne/pythonVSCode/issues/860) -* Added ability to pre-load some modules to improve autocompletion [#581](https://github.com/DonJayamanne/pythonVSCode/issues/581) + +- Add support for new variable syntax in upcoming VS Code release [#774](https://github.com/DonJayamanne/pythonVSCode/issues/774), [#855](https://github.com/DonJayamanne/pythonVSCode/issues/855), [#873](https://github.com/DonJayamanne/pythonVSCode/issues/873), [#823](https://github.com/DonJayamanne/pythonVSCode/issues/823) +- Resolve issues in code refactoring [#802](https://github.com/DonJayamanne/pythonVSCode/issues/802), [#824](https://github.com/DonJayamanne/pythonVSCode/issues/824), [#825](https://github.com/DonJayamanne/pythonVSCode/pull/825) +- Changes to labels in Python Interpreter lookup [#815](https://github.com/DonJayamanne/pythonVSCode/pull/815) +- Resolve Typos [#852](https://github.com/DonJayamanne/pythonVSCode/issues/852) +- Use fully qualitified Python Path when installing dependencies [#866](https://github.com/DonJayamanne/pythonVSCode/issues/866) +- Commands for running tests from a file [#502](https://github.com/DonJayamanne/pythonVSCode/pull/502) +- Fix Sorting of imports when path contains spaces [#811](https://github.com/DonJayamanne/pythonVSCode/issues/811) +- Fixing occasional failure of linters [#793](https://github.com/DonJayamanne/pythonVSCode/issues/793), [#833](https://github.com/DonJayamanne/pythonVSCode/issues/838), [#860](https://github.com/DonJayamanne/pythonVSCode/issues/860) +- Added ability to pre-load some modules to improve autocompletion [#581](https://github.com/DonJayamanne/pythonVSCode/issues/581) ### Thanks -* [Ashwin Mathews](https://github.com/ajmathews) -* [Alexander Ioannidis](https://github.com/slint) -* [Andreas Schlapsi](https://github.com/aschlapsi) + +- [Ashwin Mathews](https://github.com/ajmathews) +- [Alexander Ioannidis](https://github.com/slint) +- [Andreas Schlapsi](https://github.com/aschlapsi) ## Version 0.6.0 (10 March 2017) -* Moved Jupyter functionality into a separate extension [Jupyter]() -* Updated readme [#779](https://github.com/DonJayamanne/pythonVSCode/issues/779) -* Changing default arguments of ```mypy``` [#658](https://github.com/DonJayamanne/pythonVSCode/issues/658) -* Added ability to disable formatting [#559](https://github.com/DonJayamanne/pythonVSCode/issues/559) -* Fixing ability to run a Python file in a terminal [#784](https://github.com/DonJayamanne/pythonVSCode/issues/784) -* Added support for Proxy settings when installing Python packages using Pip [#778](https://github.com/DonJayamanne/pythonVSCode/issues/778) + +- Moved Jupyter functionality into a separate extension [Jupyter]() +- Updated readme [#779](https://github.com/DonJayamanne/pythonVSCode/issues/779) +- Changing default arguments of `mypy` [#658](https://github.com/DonJayamanne/pythonVSCode/issues/658) +- Added ability to disable formatting [#559](https://github.com/DonJayamanne/pythonVSCode/issues/559) +- Fixing ability to run a Python file in a terminal [#784](https://github.com/DonJayamanne/pythonVSCode/issues/784) +- Added support for Proxy settings when installing Python packages using Pip [#778](https://github.com/DonJayamanne/pythonVSCode/issues/778) ## Version 0.5.9 (3 March 2017) -* Fixed navigating to definitions [#711](https://github.com/DonJayamanne/pythonVSCode/issues/711) -* Support auto detecting binaries from Python Path [#716](https://github.com/DonJayamanne/pythonVSCode/issues/716) -* Setting PYTHONPATH environment variable [#686](https://github.com/DonJayamanne/pythonVSCode/issues/686) -* Improving Linter performance, killing redundant processes [4a8319e](https://github.com/DonJayamanne/pythonVSCode/commit/4a8319e0859f2d49165c9a08fe147a647d03ece9) -* Changed default path of the CATAS file to `.vscode/tags` [#722](https://github.com/DonJayamanne/pythonVSCode/issues/722) -* Add parsing severity level for flake8 and pep8 linters [#709](https://github.com/DonJayamanne/pythonVSCode/pull/709) -* Fix to restore function descriptions (intellisense) [#727](https://github.com/DonJayamanne/pythonVSCode/issues/727) -* Added default configuration for debugging Pyramid [#287](https://github.com/DonJayamanne/pythonVSCode/pull/287) -* Feature request: Run current line in Terminal [#738](https://github.com/DonJayamanne/pythonVSCode/issues/738) -* Miscellaneous improvements to hover provider [6a7a3f3](https://github.com/DonJayamanne/pythonVSCode/commit/6a7a3f32ab8add830d13399fec6f0cdd14cd66fc), [6268306](https://github.com/DonJayamanne/pythonVSCode/commit/62683064d01cfc2b76d9be45587280798a96460b) -* Fixes to rename refactor (due to 'LF' EOL in Windows) [#748](https://github.com/DonJayamanne/pythonVSCode/pull/748) -* Fixes to ctag file being generated in home folder when no workspace is opened [#753](https://github.com/DonJayamanne/pythonVSCode/issues/753) -* Fixes to ctag file being generated in home folder when no workspace is opened [#753](https://github.com/DonJayamanne/pythonVSCode/issues/753) -* Disabling auto-completion in single line comments [#74](https://github.com/DonJayamanne/pythonVSCode/issues/74) -* Fixes to debugging of modules [#518](https://github.com/DonJayamanne/pythonVSCode/issues/518) -* Displaying unit test status icons against unit test code lenses [#678](https://github.com/DonJayamanne/pythonVSCode/issues/678) -* Fix issue where causing 'python.python-debug.startSession' not found message to be displayed when debugging single file [#708](https://github.com/DonJayamanne/pythonVSCode/issues/708) -* Ability to include packages directory when generating tags file [#735](https://github.com/DonJayamanne/pythonVSCode/issues/735) -* Fix issue where running selected text in terminal does not work [#758](https://github.com/DonJayamanne/pythonVSCode/issues/758) -* Fix issue where disabling linter doesn't disable it (when no workspace is open) [#763](https://github.com/DonJayamanne/pythonVSCode/issues/763) -* Search additional directories for Python Interpreters (~/.virtualenvs, ~/Envs, ~/.pyenv) [#569](https://github.com/DonJayamanne/pythonVSCode/issues/569) -* Added ability to pre-load some modules to improve autocompletion [#581](https://github.com/DonJayamanne/pythonVSCode/issues/581) -* Removed invalid default value in launch.json file [#586](https://github.com/DonJayamanne/pythonVSCode/issues/586) -* Added ability to configure the pylint executable path [#766](https://github.com/DonJayamanne/pythonVSCode/issues/766) -* Fixed single file debugger to ensure the Python interpreter configured in python.PythonPath is being used [#769](https://github.com/DonJayamanne/pythonVSCode/issues/769) + +- Fixed navigating to definitions [#711](https://github.com/DonJayamanne/pythonVSCode/issues/711) +- Support auto detecting binaries from Python Path [#716](https://github.com/DonJayamanne/pythonVSCode/issues/716) +- Setting PYTHONPATH environment variable [#686](https://github.com/DonJayamanne/pythonVSCode/issues/686) +- Improving Linter performance, killing redundant processes [4a8319e](https://github.com/DonJayamanne/pythonVSCode/commit/4a8319e0859f2d49165c9a08fe147a647d03ece9) +- Changed default path of the CATAS file to `.vscode/tags` [#722](https://github.com/DonJayamanne/pythonVSCode/issues/722) +- Add parsing severity level for flake8 and pep8 linters [#709](https://github.com/DonJayamanne/pythonVSCode/pull/709) +- Fix to restore function descriptions (intellisense) [#727](https://github.com/DonJayamanne/pythonVSCode/issues/727) +- Added default configuration for debugging Pyramid [#287](https://github.com/DonJayamanne/pythonVSCode/pull/287) +- Feature request: Run current line in Terminal [#738](https://github.com/DonJayamanne/pythonVSCode/issues/738) +- Miscellaneous improvements to hover provider [6a7a3f3](https://github.com/DonJayamanne/pythonVSCode/commit/6a7a3f32ab8add830d13399fec6f0cdd14cd66fc), [6268306](https://github.com/DonJayamanne/pythonVSCode/commit/62683064d01cfc2b76d9be45587280798a96460b) +- Fixes to rename refactor (due to 'LF' EOL in Windows) [#748](https://github.com/DonJayamanne/pythonVSCode/pull/748) +- Fixes to ctag file being generated in home folder when no workspace is opened [#753](https://github.com/DonJayamanne/pythonVSCode/issues/753) +- Fixes to ctag file being generated in home folder when no workspace is opened [#753](https://github.com/DonJayamanne/pythonVSCode/issues/753) +- Disabling auto-completion in single line comments [#74](https://github.com/DonJayamanne/pythonVSCode/issues/74) +- Fixes to debugging of modules [#518](https://github.com/DonJayamanne/pythonVSCode/issues/518) +- Displaying unit test status icons against unit test code lenses [#678](https://github.com/DonJayamanne/pythonVSCode/issues/678) +- Fix issue where causing 'python.python-debug.startSession' not found message to be displayed when debugging single file [#708](https://github.com/DonJayamanne/pythonVSCode/issues/708) +- Ability to include packages directory when generating tags file [#735](https://github.com/DonJayamanne/pythonVSCode/issues/735) +- Fix issue where running selected text in terminal does not work [#758](https://github.com/DonJayamanne/pythonVSCode/issues/758) +- Fix issue where disabling linter doesn't disable it (when no workspace is open) [#763](https://github.com/DonJayamanne/pythonVSCode/issues/763) +- Search additional directories for Python Interpreters (~/.virtualenvs, ~/Envs, ~/.pyenv) [#569](https://github.com/DonJayamanne/pythonVSCode/issues/569) +- Added ability to pre-load some modules to improve autocompletion [#581](https://github.com/DonJayamanne/pythonVSCode/issues/581) +- Removed invalid default value in launch.json file [#586](https://github.com/DonJayamanne/pythonVSCode/issues/586) +- Added ability to configure the pylint executable path [#766](https://github.com/DonJayamanne/pythonVSCode/issues/766) +- Fixed single file debugger to ensure the Python interpreter configured in python.PythonPath is being used [#769](https://github.com/DonJayamanne/pythonVSCode/issues/769) ## Version 0.5.8 (3 February 2017) -* Fixed a bug in [debugging single files without a launch configuration](https://code.visualstudio.com/updates/v1_9#_debugging-without-a-launch-configuration) [#700](https://github.com/DonJayamanne/pythonVSCode/issues/700) -* Fixed error when starting REPL [#692](https://github.com/DonJayamanne/pythonVSCode/issues/692) + +- Fixed a bug in [debugging single files without a launch configuration](https://code.visualstudio.com/updates/v1_9#_debugging-without-a-launch-configuration) [#700](https://github.com/DonJayamanne/pythonVSCode/issues/700) +- Fixed error when starting REPL [#692](https://github.com/DonJayamanne/pythonVSCode/issues/692) ## Version 0.5.7 (3 February 2017) -* Added support for [debugging single files without a launch configuration](https://code.visualstudio.com/updates/v1_9#_debugging-without-a-launch-configuration) -* Adding support for debug snippets [#660](https://github.com/DonJayamanne/pythonVSCode/issues/660) -* Ability to run a selected text in a Django shell [#652](https://github.com/DonJayamanne/pythonVSCode/issues/652) -* Adding support for the use of a customized 'isort' for sorting of imports [#632](https://github.com/DonJayamanne/pythonVSCode/pull/632) -* Debugger auto-detecting python interpreter from the path provided [#688](https://github.com/DonJayamanne/pythonVSCode/issues/688) -* Showing symbol type on hover [#657](https://github.com/DonJayamanne/pythonVSCode/pull/657) -* Fixes to running Python file when terminal uses Powershell [#651](https://github.com/DonJayamanne/pythonVSCode/issues/651) -* Fixes to linter issues when displaying Git diff view for Python files [#665](https://github.com/DonJayamanne/pythonVSCode/issues/665) -* Fixes to 'Go to definition' functionality [#662](https://github.com/DonJayamanne/pythonVSCode/issues/662) -* Fixes to Jupyter cells numbered larger than '10' [#681](https://github.com/DonJayamanne/pythonVSCode/issues/681) + +- Added support for [debugging single files without a launch configuration](https://code.visualstudio.com/updates/v1_9#_debugging-without-a-launch-configuration) +- Adding support for debug snippets [#660](https://github.com/DonJayamanne/pythonVSCode/issues/660) +- Ability to run a selected text in a Django shell [#652](https://github.com/DonJayamanne/pythonVSCode/issues/652) +- Adding support for the use of a customized 'isort' for sorting of imports [#632](https://github.com/DonJayamanne/pythonVSCode/pull/632) +- Debugger auto-detecting python interpreter from the path provided [#688](https://github.com/DonJayamanne/pythonVSCode/issues/688) +- Showing symbol type on hover [#657](https://github.com/DonJayamanne/pythonVSCode/pull/657) +- Fixes to running Python file when terminal uses Powershell [#651](https://github.com/DonJayamanne/pythonVSCode/issues/651) +- Fixes to linter issues when displaying Git diff view for Python files [#665](https://github.com/DonJayamanne/pythonVSCode/issues/665) +- Fixes to 'Go to definition' functionality [#662](https://github.com/DonJayamanne/pythonVSCode/issues/662) +- Fixes to Jupyter cells numbered larger than '10' [#681](https://github.com/DonJayamanne/pythonVSCode/issues/681) ## Version 0.5.6 (16 January 2017) -* Added support for Python 3.6 [#646](https://github.com/DonJayamanne/pythonVSCode/issues/646), [#631](https://github.com/DonJayamanne/pythonVSCode/issues/631), [#619](https://github.com/DonJayamanne/pythonVSCode/issues/619), [#613](https://github.com/DonJayamanne/pythonVSCode/issues/613) -* Autodetect in python path in virtual environments [#353](https://github.com/DonJayamanne/pythonVSCode/issues/353) -* Add syntax highlighting of code samples in hover defintion [#555](https://github.com/DonJayamanne/pythonVSCode/issues/555) -* Launch REPL for currently selected interpreter [#560](https://github.com/DonJayamanne/pythonVSCode/issues/560) -* Fixes to debugging of modules [#589](https://github.com/DonJayamanne/pythonVSCode/issues/589) -* Reminder to install jedi and ctags in Quick Start [#642](https://github.com/DonJayamanne/pythonVSCode/pull/642) -* Improvements to Symbol Provider [#622](https://github.com/DonJayamanne/pythonVSCode/pull/622) -* Changes to disable unit test prompts for workspace [#559](https://github.com/DonJayamanne/pythonVSCode/issues/559) -* Minor fixes [#627](https://github.com/DonJayamanne/pythonVSCode/pull/627) + +- Added support for Python 3.6 [#646](https://github.com/DonJayamanne/pythonVSCode/issues/646), [#631](https://github.com/DonJayamanne/pythonVSCode/issues/631), [#619](https://github.com/DonJayamanne/pythonVSCode/issues/619), [#613](https://github.com/DonJayamanne/pythonVSCode/issues/613) +- Autodetect in python path in virtual environments [#353](https://github.com/DonJayamanne/pythonVSCode/issues/353) +- Add syntax highlighting of code samples in hover defintion [#555](https://github.com/DonJayamanne/pythonVSCode/issues/555) +- Launch REPL for currently selected interpreter [#560](https://github.com/DonJayamanne/pythonVSCode/issues/560) +- Fixes to debugging of modules [#589](https://github.com/DonJayamanne/pythonVSCode/issues/589) +- Reminder to install jedi and ctags in Quick Start [#642](https://github.com/DonJayamanne/pythonVSCode/pull/642) +- Improvements to Symbol Provider [#622](https://github.com/DonJayamanne/pythonVSCode/pull/622) +- Changes to disable unit test prompts for workspace [#559](https://github.com/DonJayamanne/pythonVSCode/issues/559) +- Minor fixes [#627](https://github.com/DonJayamanne/pythonVSCode/pull/627) ## Version 0.5.5 (25 November 2016) -* Fixes to debugging of unittests (nose and pytest) [#543](https://github.com/DonJayamanne/pythonVSCode/issues/543) -* Fixes to debugging of Django [#546](https://github.com/DonJayamanne/pythonVSCode/issues/546) + +- Fixes to debugging of unittests (nose and pytest) [#543](https://github.com/DonJayamanne/pythonVSCode/issues/543) +- Fixes to debugging of Django [#546](https://github.com/DonJayamanne/pythonVSCode/issues/546) ## Version 0.5.4 (24 November 2016) -* Fixes to installing missing packages [#544](https://github.com/DonJayamanne/pythonVSCode/issues/544) -* Fixes to indentation of blocks of code [#432](https://github.com/DonJayamanne/pythonVSCode/issues/432) -* Fixes to debugging of unittests [#543](https://github.com/DonJayamanne/pythonVSCode/issues/543) -* Fixes to extension when a workspace (folder) isn't open [#542](https://github.com/DonJayamanne/pythonVSCode/issues/542) + +- Fixes to installing missing packages [#544](https://github.com/DonJayamanne/pythonVSCode/issues/544) +- Fixes to indentation of blocks of code [#432](https://github.com/DonJayamanne/pythonVSCode/issues/432) +- Fixes to debugging of unittests [#543](https://github.com/DonJayamanne/pythonVSCode/issues/543) +- Fixes to extension when a workspace (folder) isn't open [#542](https://github.com/DonJayamanne/pythonVSCode/issues/542) ## Version 0.5.3 (23 November 2016) -* Added support for [PySpark](http://spark.apache.org/docs/0.9.0/python-programming-guide.html) [#539](https://github.com/DonJayamanne/pythonVSCode/pull/539), [#540](https://github.com/DonJayamanne/pythonVSCode/pull/540) -* Debugging unittests (UnitTest, pytest, nose) [#333](https://github.com/DonJayamanne/pythonVSCode/issues/333) -* Displaying progress for formatting [#327](https://github.com/DonJayamanne/pythonVSCode/issues/327) -* Auto indenting ```else:``` inside ```if``` and similar code blocks [#432](https://github.com/DonJayamanne/pythonVSCode/issues/432) -* Prefixing new lines with '#' when new lines are added in the middle of a comment string [#365](https://github.com/DonJayamanne/pythonVSCode/issues/365) -* Debugging python modules [#518](https://github.com/DonJayamanne/pythonVSCode/issues/518), [#354](https://github.com/DonJayamanne/pythonVSCode/issues/354) - + Use new debug configuration ```Python Module``` -* Added support for workspace symbols using Exuberant CTags [#138](https://github.com/DonJayamanne/pythonVSCode/issues/138) - + New command ```Python: Build Workspace Symbols``` -* Added ability for linter to ignore paths or files [#501](https://github.com/DonJayamanne/pythonVSCode/issues/501) - + Add the following setting in ```settings.json``` + +- Added support for [PySpark](http://spark.apache.org/docs/0.9.0/python-programming-guide.html) [#539](https://github.com/DonJayamanne/pythonVSCode/pull/539), [#540](https://github.com/DonJayamanne/pythonVSCode/pull/540) +- Debugging unittests (UnitTest, pytest, nose) [#333](https://github.com/DonJayamanne/pythonVSCode/issues/333) +- Displaying progress for formatting [#327](https://github.com/DonJayamanne/pythonVSCode/issues/327) +- Auto indenting `else:` inside `if` and similar code blocks [#432](https://github.com/DonJayamanne/pythonVSCode/issues/432) +- Prefixing new lines with '#' when new lines are added in the middle of a comment string [#365](https://github.com/DonJayamanne/pythonVSCode/issues/365) +- Debugging python modules [#518](https://github.com/DonJayamanne/pythonVSCode/issues/518), [#354](https://github.com/DonJayamanne/pythonVSCode/issues/354) + - Use new debug configuration `Python Module` +- Added support for workspace symbols using Exuberant CTags [#138](https://github.com/DonJayamanne/pythonVSCode/issues/138) + - New command `Python: Build Workspace Symbols` +- Added ability for linter to ignore paths or files [#501](https://github.com/DonJayamanne/pythonVSCode/issues/501) + - Add the following setting in `settings.json` + ```python "python.linting.ignorePatterns": [ ".vscode/*.py", "**/site-packages/**/*.py" ], ``` -* Automatically adding brackets when autocompleting functions/methods [#425](https://github.com/DonJayamanne/pythonVSCode/issues/425) - + To enable this feature, turn on the setting ```"python.autoComplete.addBrackets": true``` -* Running nose tests with the arguments '--with-xunit' and '--xunit-file' [#517](https://github.com/DonJayamanne/pythonVSCode/issues/517) -* Added support for workspaceRootFolderName in settings.json [#525](https://github.com/DonJayamanne/pythonVSCode/pull/525), [#522](https://github.com/DonJayamanne/pythonVSCode/issues/522) -* Added support for workspaceRootFolderName in settings.json [#525](https://github.com/DonJayamanne/pythonVSCode/pull/525), [#522](https://github.com/DonJayamanne/pythonVSCode/issues/522) -* Fixes to running code in terminal [#515](https://github.com/DonJayamanne/pythonVSCode/issues/515) + +- Automatically adding brackets when autocompleting functions/methods [#425](https://github.com/DonJayamanne/pythonVSCode/issues/425) + - To enable this feature, turn on the setting `"python.autoComplete.addBrackets": true` +- Running nose tests with the arguments '--with-xunit' and '--xunit-file' [#517](https://github.com/DonJayamanne/pythonVSCode/issues/517) +- Added support for workspaceRootFolderName in settings.json [#525](https://github.com/DonJayamanne/pythonVSCode/pull/525), [#522](https://github.com/DonJayamanne/pythonVSCode/issues/522) +- Added support for workspaceRootFolderName in settings.json [#525](https://github.com/DonJayamanne/pythonVSCode/pull/525), [#522](https://github.com/DonJayamanne/pythonVSCode/issues/522) +- Fixes to running code in terminal [#515](https://github.com/DonJayamanne/pythonVSCode/issues/515) ## Version 0.5.2 -* Fix issue with mypy linter [#505](https://github.com/DonJayamanne/pythonVSCode/issues/505) -* Fix auto completion for files with different encodings [#496](https://github.com/DonJayamanne/pythonVSCode/issues/496) -* Disable warnings when debugging Django version prior to 1.8 [#479](https://github.com/DonJayamanne/pythonVSCode/issues/479) -* Prompt to save changes when refactoring without saving any changes [#441](https://github.com/DonJayamanne/pythonVSCode/issues/441) -* Prompt to save changes when renaminv without saving any changes [#443](https://github.com/DonJayamanne/pythonVSCode/issues/443) -* Use editor indentation size when refactoring code [#442](https://github.com/DonJayamanne/pythonVSCode/issues/442) -* Add support for custom jedi paths [#500](https://github.com/DonJayamanne/pythonVSCode/issues/500) + +- Fix issue with mypy linter [#505](https://github.com/DonJayamanne/pythonVSCode/issues/505) +- Fix auto completion for files with different encodings [#496](https://github.com/DonJayamanne/pythonVSCode/issues/496) +- Disable warnings when debugging Django version prior to 1.8 [#479](https://github.com/DonJayamanne/pythonVSCode/issues/479) +- Prompt to save changes when refactoring without saving any changes [#441](https://github.com/DonJayamanne/pythonVSCode/issues/441) +- Prompt to save changes when renaminv without saving any changes [#443](https://github.com/DonJayamanne/pythonVSCode/issues/443) +- Use editor indentation size when refactoring code [#442](https://github.com/DonJayamanne/pythonVSCode/issues/442) +- Add support for custom jedi paths [#500](https://github.com/DonJayamanne/pythonVSCode/issues/500) ## Version 0.5.1 -* Prompt to install linter if not installed [#255](https://github.com/DonJayamanne/pythonVSCode/issues/255) -* Prompt to configure and install test framework -* Added support for pylama [#495](https://github.com/DonJayamanne/pythonVSCode/pull/495) -* Partial support for PEP484 -* Linting python files when they are opened [#462](https://github.com/DonJayamanne/pythonVSCode/issues/462) -* Fixes to unit tests discovery [#307](https://github.com/DonJayamanne/pythonVSCode/issues/307), -[#459](https://github.com/DonJayamanne/pythonVSCode/issues/459) -* Fixes to intellisense [#438](https://github.com/DonJayamanne/pythonVSCode/issues/438), -[#433](https://github.com/DonJayamanne/pythonVSCode/issues/433), -[#457](https://github.com/DonJayamanne/pythonVSCode/issues/457), -[#436](https://github.com/DonJayamanne/pythonVSCode/issues/436), -[#434](https://github.com/DonJayamanne/pythonVSCode/issues/434), -[#447](https://github.com/DonJayamanne/pythonVSCode/issues/447), -[#448](https://github.com/DonJayamanne/pythonVSCode/issues/448), -[#293](https://github.com/DonJayamanne/pythonVSCode/issues/293), -[#381](https://github.com/DonJayamanne/pythonVSCode/pull/381) -* Supporting additional search paths for interpreters on windows [#446](https://github.com/DonJayamanne/pythonVSCode/issues/446) -* Fixes to code refactoring [#440](https://github.com/DonJayamanne/pythonVSCode/issues/440), -[#467](https://github.com/DonJayamanne/pythonVSCode/issues/467), -[#468](https://github.com/DonJayamanne/pythonVSCode/issues/468), -[#445](https://github.com/DonJayamanne/pythonVSCode/issues/445) -* Fixes to linters [#463](https://github.com/DonJayamanne/pythonVSCode/issues/463) -[#439](https://github.com/DonJayamanne/pythonVSCode/issues/439), -* Bug fix in handling nosetest arguments [#407](https://github.com/DonJayamanne/pythonVSCode/issues/407) -* Better error handling when linter fails [#402](https://github.com/DonJayamanne/pythonVSCode/issues/402) -* Restoring extension specific formatting [#421](https://github.com/DonJayamanne/pythonVSCode/issues/421) -* Fixes to debugger (unwanted breakpoints) [#392](https://github.com/DonJayamanne/pythonVSCode/issues/392), [#379](https://github.com/DonJayamanne/pythonVSCode/issues/379) -* Support spaces in python path when executing in terminal [#428](https://github.com/DonJayamanne/pythonVSCode/pull/428) -* Changes to snippets [#429](https://github.com/DonJayamanne/pythonVSCode/pull/429) -* Marketplace changes [#430](https://github.com/DonJayamanne/pythonVSCode/pull/430) -* Cleanup and miscellaneous fixes (typos, keyboard bindings and the liks) + +- Prompt to install linter if not installed [#255](https://github.com/DonJayamanne/pythonVSCode/issues/255) +- Prompt to configure and install test framework +- Added support for pylama [#495](https://github.com/DonJayamanne/pythonVSCode/pull/495) +- Partial support for PEP484 +- Linting python files when they are opened [#462](https://github.com/DonJayamanne/pythonVSCode/issues/462) +- Fixes to unit tests discovery [#307](https://github.com/DonJayamanne/pythonVSCode/issues/307), + [#459](https://github.com/DonJayamanne/pythonVSCode/issues/459) +- Fixes to intellisense [#438](https://github.com/DonJayamanne/pythonVSCode/issues/438), + [#433](https://github.com/DonJayamanne/pythonVSCode/issues/433), + [#457](https://github.com/DonJayamanne/pythonVSCode/issues/457), + [#436](https://github.com/DonJayamanne/pythonVSCode/issues/436), + [#434](https://github.com/DonJayamanne/pythonVSCode/issues/434), + [#447](https://github.com/DonJayamanne/pythonVSCode/issues/447), + [#448](https://github.com/DonJayamanne/pythonVSCode/issues/448), + [#293](https://github.com/DonJayamanne/pythonVSCode/issues/293), + [#381](https://github.com/DonJayamanne/pythonVSCode/pull/381) +- Supporting additional search paths for interpreters on windows [#446](https://github.com/DonJayamanne/pythonVSCode/issues/446) +- Fixes to code refactoring [#440](https://github.com/DonJayamanne/pythonVSCode/issues/440), + [#467](https://github.com/DonJayamanne/pythonVSCode/issues/467), + [#468](https://github.com/DonJayamanne/pythonVSCode/issues/468), + [#445](https://github.com/DonJayamanne/pythonVSCode/issues/445) +- Fixes to linters [#463](https://github.com/DonJayamanne/pythonVSCode/issues/463) + [#439](https://github.com/DonJayamanne/pythonVSCode/issues/439), +- Bug fix in handling nosetest arguments [#407](https://github.com/DonJayamanne/pythonVSCode/issues/407) +- Better error handling when linter fails [#402](https://github.com/DonJayamanne/pythonVSCode/issues/402) +- Restoring extension specific formatting [#421](https://github.com/DonJayamanne/pythonVSCode/issues/421) +- Fixes to debugger (unwanted breakpoints) [#392](https://github.com/DonJayamanne/pythonVSCode/issues/392), [#379](https://github.com/DonJayamanne/pythonVSCode/issues/379) +- Support spaces in python path when executing in terminal [#428](https://github.com/DonJayamanne/pythonVSCode/pull/428) +- Changes to snippets [#429](https://github.com/DonJayamanne/pythonVSCode/pull/429) +- Marketplace changes [#430](https://github.com/DonJayamanne/pythonVSCode/pull/430) +- Cleanup and miscellaneous fixes (typos, keyboard bindings and the liks) ## Version 0.5.0 -* Remove dependency on zmq when using Jupyter or IPython (pure python solution) -* Added a default keybinding for ```Jupyter:Run Selection/Line``` of ```ctrl+alt+enter``` -* Changes to update settings.json with path to python using [native API](https://github.com/DonJayamanne/pythonVSCode/commit/bce22a2b4af87eaf40669c6360eff3675280cdad) -* Changes to use [native API](https://github.com/DonJayamanne/pythonVSCode/commit/bce22a2b4af87eaf40669c6360eff3675280cdad) for formatting when saving documents -* Reusing existing terminal instead of creating new terminals -* Limiting linter messages to opened documents (hide messages if document is closed) [#375](https://github.com/DonJayamanne/pythonVSCode/issues/375) -* Resolving extension load errors when [#375](https://github.com/DonJayamanne/pythonVSCode/issues/375) -* Fixes to discovering unittests [#386](https://github.com/DonJayamanne/pythonVSCode/issues/386) -* Fixes to sending code to terminal on Windows [#387](https://github.com/DonJayamanne/pythonVSCode/issues/387) -* Fixes to executing python file in terminal on Windows [#385](https://github.com/DonJayamanne/pythonVSCode/issues/385) -* Fixes to launching local help (documentation) on Linux -* Fixes to typo in configuration documentation [#391](https://github.com/DonJayamanne/pythonVSCode/pull/391) -* Fixes to use ```python.pythonPath``` when sorting imports [#393](https://github.com/DonJayamanne/pythonVSCode/pull/393) -* Fixes to linters to handle situations when line numbers aren't returned [#399](https://github.com/DonJayamanne/pythonVSCode/pull/399) -* Fixes to signature tooltips when docstring is very long [#368](https://github.com/DonJayamanne/pythonVSCode/issues/368), [#113](https://github.com/DonJayamanne/pythonVSCode/issues/113) + +- Remove dependency on zmq when using Jupyter or IPython (pure python solution) +- Added a default keybinding for `Jupyter:Run Selection/Line` of `ctrl+alt+enter` +- Changes to update settings.json with path to python using [native API](https://github.com/DonJayamanne/pythonVSCode/commit/bce22a2b4af87eaf40669c6360eff3675280cdad) +- Changes to use [native API](https://github.com/DonJayamanne/pythonVSCode/commit/bce22a2b4af87eaf40669c6360eff3675280cdad) for formatting when saving documents +- Reusing existing terminal instead of creating new terminals +- Limiting linter messages to opened documents (hide messages if document is closed) [#375](https://github.com/DonJayamanne/pythonVSCode/issues/375) +- Resolving extension load errors when [#375](https://github.com/DonJayamanne/pythonVSCode/issues/375) +- Fixes to discovering unittests [#386](https://github.com/DonJayamanne/pythonVSCode/issues/386) +- Fixes to sending code to terminal on Windows [#387](https://github.com/DonJayamanne/pythonVSCode/issues/387) +- Fixes to executing python file in terminal on Windows [#385](https://github.com/DonJayamanne/pythonVSCode/issues/385) +- Fixes to launching local help (documentation) on Linux +- Fixes to typo in configuration documentation [#391](https://github.com/DonJayamanne/pythonVSCode/pull/391) +- Fixes to use `python.pythonPath` when sorting imports [#393](https://github.com/DonJayamanne/pythonVSCode/pull/393) +- Fixes to linters to handle situations when line numbers aren't returned [#399](https://github.com/DonJayamanne/pythonVSCode/pull/399) +- Fixes to signature tooltips when docstring is very long [#368](https://github.com/DonJayamanne/pythonVSCode/issues/368), [#113](https://github.com/DonJayamanne/pythonVSCode/issues/113) ## Version 0.4.2 -* Fix for autocompletion and code navigation with unicode characters [#372](https://github.com/DonJayamanne/pythonVSCode/issues/372), [#364](https://github.com/DonJayamanne/pythonVSCode/issues/364) + +- Fix for autocompletion and code navigation with unicode characters [#372](https://github.com/DonJayamanne/pythonVSCode/issues/372), [#364](https://github.com/DonJayamanne/pythonVSCode/issues/364) ## Version 0.4.1 -* Debugging of [Django templates](https://github.com/DonJayamanne/pythonVSCode/wiki/Debugging-Django#templates) -* Linting with [mypy](https://github.com/DonJayamanne/pythonVSCode/wiki/Linting#mypy) -* Improved error handling when loading [Jupyter/IPython](https://github.com/DonJayamanne/pythonVSCode/wiki/Jupyter-(IPython)) -* Fixes to unittests + +- Debugging of [Django templates](https://github.com/DonJayamanne/pythonVSCode/wiki/Debugging-Django#templates) +- Linting with [mypy](https://github.com/DonJayamanne/pythonVSCode/wiki/Linting#mypy) +- Improved error handling when loading [Jupyter/IPython]() +- Fixes to unittests ## Version 0.4.0 -* Added support for [Jupyter/IPython](https://github.com/DonJayamanne/pythonVSCode/wiki/Jupyter-(IPython)) -* Added local help (offline documentation) -* Added ability to pass in extra arguments to interpreter when executing scripts ([#316](https://github.com/DonJayamanne/pythonVSCode/issues/316)) -* Added ability set current working directory as the script file directory, when to executing a Python script -* Rendering intellisense icons correctly ([#322](https://github.com/DonJayamanne/pythonVSCode/issues/322)) -* Changes to capitalization of context menu text ([#320](https://github.com/DonJayamanne/pythonVSCode/issues/320)) -* Bug fix to running pydocstyle linter on windows ([#317](https://github.com/DonJayamanne/pythonVSCode/issues/317)) -* Fixed performance issues with regards to code navigation, displaying code Symbols and the like ([#324](https://github.com/DonJayamanne/pythonVSCode/issues/324)) -* Fixed code renaming issue when renaming imports ([#325](https://github.com/DonJayamanne/pythonVSCode/issues/325)) -* Fixed issue with the execution of the command ```python.execInTerminal``` via a shortcut ([#340](https://github.com/DonJayamanne/pythonVSCode/issues/340)) -* Fixed issue with code refactoring ([#363](https://github.com/DonJayamanne/pythonVSCode/issues/363)) + +- Added support for [Jupyter/IPython]() +- Added local help (offline documentation) +- Added ability to pass in extra arguments to interpreter when executing scripts ([#316](https://github.com/DonJayamanne/pythonVSCode/issues/316)) +- Added ability set current working directory as the script file directory, when to executing a Python script +- Rendering intellisense icons correctly ([#322](https://github.com/DonJayamanne/pythonVSCode/issues/322)) +- Changes to capitalization of context menu text ([#320](https://github.com/DonJayamanne/pythonVSCode/issues/320)) +- Bug fix to running pydocstyle linter on windows ([#317](https://github.com/DonJayamanne/pythonVSCode/issues/317)) +- Fixed performance issues with regards to code navigation, displaying code Symbols and the like ([#324](https://github.com/DonJayamanne/pythonVSCode/issues/324)) +- Fixed code renaming issue when renaming imports ([#325](https://github.com/DonJayamanne/pythonVSCode/issues/325)) +- Fixed issue with the execution of the command `python.execInTerminal` via a shortcut ([#340](https://github.com/DonJayamanne/pythonVSCode/issues/340)) +- Fixed issue with code refactoring ([#363](https://github.com/DonJayamanne/pythonVSCode/issues/363)) ## Version 0.3.24 -* Added support for clearing cached tests [#307](https://github.com/DonJayamanne/pythonVSCode/issues/307) -* Added support for executing files in terminal with spaces in paths [#308](https://github.com/DonJayamanne/pythonVSCode/issues/308) -* Fix issue related to running unittests on Windows [#309](https://github.com/DonJayamanne/pythonVSCode/issues/309) -* Support custom environment variables when launching external terminal [#311](https://github.com/DonJayamanne/pythonVSCode/issues/311) + +- Added support for clearing cached tests [#307](https://github.com/DonJayamanne/pythonVSCode/issues/307) +- Added support for executing files in terminal with spaces in paths [#308](https://github.com/DonJayamanne/pythonVSCode/issues/308) +- Fix issue related to running unittests on Windows [#309](https://github.com/DonJayamanne/pythonVSCode/issues/309) +- Support custom environment variables when launching external terminal [#311](https://github.com/DonJayamanne/pythonVSCode/issues/311) ## Version 0.3.23 -* Added support for the attribute supportsRunInTerminal attribute in debugger [#304](https://github.com/DonJayamanne/pythonVSCode/issues/304) -* Changes to ensure remote debugging resolves remote paths correctly [#302](https://github.com/DonJayamanne/pythonVSCode/issues/302) -* Added support for custom pytest and nosetest paths [#301](https://github.com/DonJayamanne/pythonVSCode/issues/301) -* Resolved issue in ```Watch``` window displaying ``` Date: Mon, 10 Feb 2020 15:49:54 -0700 Subject: [PATCH 16/30] Ignore FS errors from stat() in some cases. (#10032) (for #9901) The earlier FS code ignored errors in a couple of situations. Recent changes inadvertently stopped ignoring them. This change restores the earlier behavior (and adds logging of the errors). This is a backport of #10021. --- news/2 Fixes/9901.md | 1 + src/client/common/platform/fileSystem.ts | 16 +++++-- .../platform/filesystem.functional.test.ts | 25 +++++++++++ src/test/common/platform/filesystem.test.ts | 40 ++++++++++++++++- .../common/platform/filesystem.unit.test.ts | 43 ++++++++++++++++--- 5 files changed, 114 insertions(+), 11 deletions(-) create mode 100644 news/2 Fixes/9901.md diff --git a/news/2 Fixes/9901.md b/news/2 Fixes/9901.md new file mode 100644 index 000000000000..3f04054b0926 --- /dev/null +++ b/news/2 Fixes/9901.md @@ -0,0 +1 @@ +Ignore errors coming from stat(), where appropriate. diff --git a/src/client/common/platform/fileSystem.ts b/src/client/common/platform/fileSystem.ts index 0217163ce37c..dcef489a2c02 100644 --- a/src/client/common/platform/fileSystem.ts +++ b/src/client/common/platform/fileSystem.ts @@ -9,6 +9,7 @@ import { injectable } from 'inversify'; import { promisify } from 'util'; import * as vscode from 'vscode'; import '../../common/extensions'; +import { traceError } from '../logger'; import { createDeferred } from '../utils/async'; import { isFileNotFoundError, isNoPermissionsError } from './errors'; import { FileSystemPaths, FileSystemPathUtils } from './fs-paths'; @@ -213,9 +214,15 @@ export class RawFileSystem implements IRawFileSystem { const files = await this.fsExtra.readdir(dirname); const promises = files.map(async basename => { const filename = this.paths.join(dirname, basename); - // Note that this follows symlinks (while still preserving - // the Symlink flag). - const fileType = await this.getFileType(filename); + let fileType: FileType; + try { + // Note that getFileType() follows symlinks (while still + // preserving the Symlink flag). + fileType = await this.getFileType(filename); + } catch (err) { + traceError(`failure while getting file type for "${filename}"`, err); + fileType = FileType.Unknown; + } return [filename, fileType] as [string, FileType]; }); return Promise.all(promises); @@ -352,7 +359,8 @@ export class FileSystemUtils implements IFileSystemUtils { if (isFileNotFoundError(err)) { return false; } - throw err; + traceError(`stat() failed for "${filename}"`, err); + return false; } if (fileType === undefined) { diff --git a/src/test/common/platform/filesystem.functional.test.ts b/src/test/common/platform/filesystem.functional.test.ts index 3c5497ac88f3..fda385686562 100644 --- a/src/test/common/platform/filesystem.functional.test.ts +++ b/src/test/common/platform/filesystem.functional.test.ts @@ -678,6 +678,31 @@ suite('FileSystem - raw', () => { await expect(promise).to.eventually.be.rejected; }); + + test('ignores errors from getFileType()', async function() { + if (WINDOWS) { + // tslint:disable-next-line:no-invalid-this + this.skip(); + } + const dirname = await fix.createDirectory('x/y/z'); + const file1 = await fix.createFile('x/y/z/__init__.py', ''); + const file2 = await fix.createFile('x/y/z/spam.py', '...'); + const file3 = await fix.createFile('x/y/z/eggs.py', '...'); + await fs.chmod(dirname, 0o400); + + let entries: [string, FileType][]; + try { + entries = await fileSystem.listdir(dirname); + } finally { + await fs.chmod(dirname, 0o755); + } + + expect(entries.sort()).to.deep.equal([ + [file1, FileType.Unknown], + [file3, FileType.Unknown], + [file2, FileType.Unknown] + ]); + }); }); // non-async diff --git a/src/test/common/platform/filesystem.test.ts b/src/test/common/platform/filesystem.test.ts index 3b4c9a69f2b9..5346ba851f51 100644 --- a/src/test/common/platform/filesystem.test.ts +++ b/src/test/common/platform/filesystem.test.ts @@ -17,7 +17,7 @@ import { // prettier-ignore import { assertDoesNotExist, DOES_NOT_EXIST, FSFixture, - SUPPORTS_SOCKETS, SUPPORTS_SYMLINKS + SUPPORTS_SOCKETS, SUPPORTS_SYMLINKS, WINDOWS } from './utils'; // Note: all functional tests that do not trigger the VS Code "fs" API @@ -242,6 +242,25 @@ suite('FileSystem - utils', () => { expect(exists).to.equal(false); }); + + test('failure in stat()', async function() { + if (WINDOWS) { + // tslint:disable-next-line:no-invalid-this + this.skip(); + } + const dirname = await fix.createDirectory('x/y/z'); + const filename = await fix.createFile('x/y/z/spam.py', '...'); + await fsextra.chmod(dirname, 0o400); + + let exists: boolean; + try { + exists = await utils.fileExists(filename); + } finally { + await fsextra.chmod(dirname, 0o755); + } + + expect(exists).to.equal(false); + }); }); suite('directoryExists', () => { @@ -282,6 +301,25 @@ suite('FileSystem - utils', () => { expect(exists).to.equal(false); }); + + test('failure in stat()', async function() { + if (WINDOWS) { + // tslint:disable-next-line:no-invalid-this + this.skip(); + } + const parentdir = await fix.createDirectory('x/y/z'); + const dirname = await fix.createDirectory('x/y/z/spam'); + await fsextra.chmod(parentdir, 0o400); + + let exists: boolean; + try { + exists = await utils.fileExists(dirname); + } finally { + await fsextra.chmod(parentdir, 0o755); + } + + expect(exists).to.equal(false); + }); }); suite('getSubDirectories', () => { diff --git a/src/test/common/platform/filesystem.unit.test.ts b/src/test/common/platform/filesystem.unit.test.ts index 1764add2cd30..b5148cbd2047 100644 --- a/src/test/common/platform/filesystem.unit.test.ts +++ b/src/test/common/platform/filesystem.unit.test.ts @@ -597,6 +597,38 @@ suite('Raw FileSystem', () => { await expect(promise).to.eventually.be.rejected; verifyAll(); }); + + test('ignores errors from getFileType()', async () => { + const dirname = 'x/y/z'; + const names = [ + // These match the items in "expected". + '__init__.py', + 'spam.py', + 'eggs.py' + ]; + const expected: [string, FileType][] = [ + ['x/y/z/__init__.py', FileType.File], + ['x/y/z/spam.py', FileType.File], + ['x/y/z/eggs.py', FileType.Unknown] + ]; + raw.setup(r => r.readdir(dirname)) // expect the specific filename + .returns(() => Promise.resolve(names)); + names.forEach((name, i) => { + const [filename, filetype] = expected[i]; + raw.setup(r => r.join(dirname, name)) // expect the specific filename + .returns(() => filename); + if (filetype === FileType.Unknown) { + raw.setup(r => r.lstat(filename)) // expect the specific filename + .throws(new Error('oops!')); + } else { + setupForFileType(filename, filetype); + } + }); + + const entries = await filesystem.listdir(dirname); + + expect(entries.sort()).to.deep.equal(expected.sort()); + }); }); suite('readTextSync', () => { @@ -781,15 +813,14 @@ suite('FileSystemUtils', () => { verifyAll(); }); - test('fails if stat fails', async () => { + test('ignores errors from stat()', async () => { const filename = 'x/y/z/spam.py'; - const err = new Error('oops!'); - deps.setup(d => d.stat(filename)) // There was a problem while stat'ing the file. - .throws(err); + deps.setup(d => d.stat(filename)) // It's broken. + .returns(() => Promise.reject(new Error('oops!'))); - const promise = utils.pathExists(filename); + const exists = await utils.pathExists(filename); - await expect(promise).to.eventually.be.rejected; + expect(exists).to.equal(false); verifyAll(); }); From f2d788c04294266df2441668177ea79608ec68f3 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Mon, 10 Feb 2020 21:23:35 -0800 Subject: [PATCH 17/30] Update chang log (#10041) --- CHANGELOG.md | 4 +++- news/2 Fixes/9901.md | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) delete mode 100644 news/2 Fixes/9901.md diff --git a/CHANGELOG.md b/CHANGELOG.md index f4398ffc113b..0fdcac529d5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 2020.2.0 (10 February 2020) +## 2020.2.0 (11 February 2020) ### Enhancements @@ -129,6 +129,8 @@ ([#9780](https://github.com/Microsoft/vscode-python/issues/9780)) 1. When comitting intellisense in Notebook Editor with Jedi place code in correct position. ([#9857](https://github.com/Microsoft/vscode-python/issues/9857)) +1. Ignore errors coming from stat(), where appropriate. + ([#9901](https://github.com/Microsoft/vscode-python/issues/9901)) ### Code Health diff --git a/news/2 Fixes/9901.md b/news/2 Fixes/9901.md deleted file mode 100644 index 3f04054b0926..000000000000 --- a/news/2 Fixes/9901.md +++ /dev/null @@ -1 +0,0 @@ -Ignore errors coming from stat(), where appropriate. From ffbe5e1bd85cabf86f124a890c58adb9fced505b Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Wed, 12 Feb 2020 11:15:19 -0800 Subject: [PATCH 18/30] Install jupyter instead of installing kernel spec (#10080) (#10083) * Install jupyter instead of installing kernel spec For #10071 --- news/2 Fixes/10071.md | 1 + .../jupyterInterpreterDependencyService.ts | 16 +++++++++++----- ...rInterpreterDependencyService.unit.test.ts | 19 +++++++++++++++++++ 3 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 news/2 Fixes/10071.md diff --git a/news/2 Fixes/10071.md b/news/2 Fixes/10071.md new file mode 100644 index 000000000000..842c8c2786d1 --- /dev/null +++ b/news/2 Fixes/10071.md @@ -0,0 +1 @@ +Re-install `Jupyter` instead of installing `kernelspec` if `kernelspec` cannot be found in the python environment. diff --git a/src/client/datascience/jupyter/interpreter/jupyterInterpreterDependencyService.ts b/src/client/datascience/jupyter/interpreter/jupyterInterpreterDependencyService.ts index a1d7fc2495a5..34ef6f01aaae 100644 --- a/src/client/datascience/jupyter/interpreter/jupyterInterpreterDependencyService.ts +++ b/src/client/datascience/jupyter/interpreter/jupyterInterpreterDependencyService.ts @@ -57,9 +57,8 @@ function sortProductsInOrderForInstallation(products: Product[]) { * @returns {string} */ export function getMessageForLibrariesNotInstalled(products: Product[]): string { + // Even though kernelspec cannot be installed, display it so user knows what is missing. const names = products - // Ignore kernelspec as it not something that can be installed. - .filter(product => product !== Product.kernelspec) .map(product => ProductNames.get(product)) .filter(name => !!name) .map(name => name as string); @@ -122,15 +121,15 @@ export class JupyterInterpreterDependencyService { _error?: JupyterInstallError, token?: CancellationToken ): Promise { - const productsToInstall = await this.getDependenciesNotInstalled(interpreter, token); + const missingProducts = await this.getDependenciesNotInstalled(interpreter, token); if (Cancellation.isCanceled(token)) { return JupyterInterpreterDependencyResponse.cancel; } - if (productsToInstall.length === 0) { + if (missingProducts.length === 0) { return JupyterInterpreterDependencyResponse.ok; } - const message = getMessageForLibrariesNotInstalled(productsToInstall); + const message = getMessageForLibrariesNotInstalled(missingProducts); sendTelemetryEvent(Telemetry.JupyterNotInstalledErrorShown); const selection = await this.applicationShell.showErrorMessage( @@ -147,8 +146,15 @@ export class JupyterInterpreterDependencyService { switch (selection) { case DataScience.jupyterInstall(): { + // Ignore kernelspec as it not something that can be installed. + // If kernelspec isn't available, then re-install `Jupyter`. + if (missingProducts.includes(Product.kernelspec) && !missingProducts.includes(Product.jupyter)) { + missingProducts.push(Product.jupyter); + } + const productsToInstall = missingProducts.filter(product => product !== Product.kernelspec); // Install jupyter, then notebook, then others in that order. sortProductsInOrderForInstallation(productsToInstall); + let productToInstall = productsToInstall.shift(); const cancellatonPromise = createPromiseFromCancellation({ cancelAction: 'resolve', defaultValue: InstallerResponse.Ignore, token }); while (productToInstall) { diff --git a/src/test/datascience/jupyter/interpreter/jupyterInterpreterDependencyService.unit.test.ts b/src/test/datascience/jupyter/interpreter/jupyterInterpreterDependencyService.unit.test.ts index 6d3391569da3..a230f6607b1e 100644 --- a/src/test/datascience/jupyter/interpreter/jupyterInterpreterDependencyService.unit.test.ts +++ b/src/test/datascience/jupyter/interpreter/jupyterInterpreterDependencyService.unit.test.ts @@ -17,6 +17,7 @@ import { Architecture } from '../../../../client/common/utils/platform'; import { JupyterInterpreterDependencyResponse, JupyterInterpreterDependencyService } from '../../../../client/datascience/jupyter/interpreter/jupyterInterpreterDependencyService'; import { InterpreterType, PythonInterpreter } from '../../../../client/interpreter/contracts'; +// tslint:disable-next-line: max-func-body-length suite('Data Science - Jupyter Interpreter Configuration', () => { let configuration: JupyterInterpreterDependencyService; let appShell: IApplicationShell; @@ -62,6 +63,24 @@ suite('Data Science - Jupyter Interpreter Configuration', () => { test('Prompt to install if Jupyter is not installed', async () => testPromptIfModuleNotInstalled(false, true)); test('Prompt to install if notebook is not installed', async () => testPromptIfModuleNotInstalled(true, false)); test('Prompt to install if jupyter & notebook is not installed', async () => testPromptIfModuleNotInstalled(false, false)); + test('Reinstall Jupyter if jupyter and notebook are installed but kernelspec is not found', async () => { + when(installer.isInstalled(Product.jupyter, pythonInterpreter)).thenResolve(true); + when(installer.isInstalled(Product.notebook, pythonInterpreter)).thenResolve(true); + when(appShell.showErrorMessage(anything(), anything(), anything(), anything())).thenResolve( + // tslint:disable-next-line: no-any + DataScience.jupyterInstall() as any + ); + when(pythonExecService.execModule('jupyter', deepEqual(['kernelspec', '--version']), anything())).thenReject(new Error('Not found')); + when(installer.install(anything(), anything(), anything())).thenResolve(InstallerResponse.Installed); + + const response = await configuration.installMissingDependencies(pythonInterpreter); + + // Jupyter must be installed & not kernelspec or anything else. + verify(installer.install(Product.jupyter, anything(), anything())).once(); + verify(installer.install(anything(), anything(), anything())).once(); + verify(appShell.showErrorMessage(anything(), DataScience.jupyterInstall(), DataScience.selectDifferentJupyterInterpreter(), anything())).once(); + assert.equal(response, JupyterInterpreterDependencyResponse.cancel); + }); async function testInstallationOfJupyter(installerResponse: InstallerResponse, expectedConfigurationReponse: JupyterInterpreterDependencyResponse): Promise { when(installer.isInstalled(Product.jupyter, pythonInterpreter)).thenResolve(false); From c8895be26c52dbcfcc61410205db158046ed0e5b Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Wed, 12 Feb 2020 12:28:42 -0800 Subject: [PATCH 19/30] Fix for zh-tw loading issue. (#10085) (#10089) --- news/2 Fixes/10072.md | 2 ++ package.nls.zh-tw.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 news/2 Fixes/10072.md diff --git a/news/2 Fixes/10072.md b/news/2 Fixes/10072.md new file mode 100644 index 000000000000..195bfad15543 --- /dev/null +++ b/news/2 Fixes/10072.md @@ -0,0 +1,2 @@ +Fix zh-tw localization file loading issue. +(thanks to [ChenKB91](https://github.com/ChenKB91/)) diff --git a/package.nls.zh-tw.json b/package.nls.zh-tw.json index fee7b9393e67..4555d98fb5ed 100644 --- a/package.nls.zh-tw.json +++ b/package.nls.zh-tw.json @@ -158,5 +158,5 @@ "Interpreters.selectInterpreterTip": "小提示:您能透過按下狀態列中的 Python 版本,變更 Python 延伸模組使用的 Python 解譯器。", "downloading.file": "正在下載 {0}...", "downloading.file.progress": "目前 {0}{1},總共 {2} KB ({3}%)", - "products.installingModule": "正在安裝 {0}", + "products.installingModule": "正在安裝 {0}" } From 506631953569537f46bd877e1fd9ca7581d095be Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Wed, 12 Feb 2020 14:00:07 -0800 Subject: [PATCH 20/30] Update version and changelog for point release. (#10091) * Update version and changelog for point release. * Add note to change log. --- CHANGELOG.md | 67 +++++++++++++++++++++++++++++++++++++++++++ news/2 Fixes/10071.md | 1 - news/2 Fixes/10072.md | 2 -- package-lock.json | 2 +- package.json | 2 +- 5 files changed, 69 insertions(+), 5 deletions(-) delete mode 100644 news/2 Fixes/10071.md delete mode 100644 news/2 Fixes/10072.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fdcac529d5c..a425fb90c29a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,72 @@ # Changelog +## 2020.2.1 (12 February 2020) + +### Fixes + +1. Re-install `Jupyter` instead of installing `kernelspec` if `kernelspec` cannot be found in the python environment. + ([#10071](https://github.com/Microsoft/vscode-python/issues/10071)) +1. Fix zh-tw localization file loading issue. + (thanks to [ChenKB91](https://github.com/ChenKB91/)) + ([#10072](https://github.com/Microsoft/vscode-python/issues/10072)) + +### Note + +1. Please only set the `python.languageServer` setting if you want to turn IntelliSense off. To switch between language servers, please keep using the `python.jediEnabled` setting for now. + +### Thanks + +Thanks to the following projects which we fully rely on to provide some of +our features: + +- [isort](https://pypi.org/project/isort/) +- [jedi](https://pypi.org/project/jedi/) + and [parso](https://pypi.org/project/parso/) +- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) +- [ptvsd](https://pypi.org/project/ptvsd/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) + +Also thanks to the various projects we provide integrations with which help +make this extension useful: + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [bandit](https://pypi.org/project/bandit/), + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +And finally thanks to the [Python](https://www.python.org/) development team and +community for creating a fantastic programming language and community to be a +part of! + ## 2020.2.0 (11 February 2020) ### Enhancements diff --git a/news/2 Fixes/10071.md b/news/2 Fixes/10071.md deleted file mode 100644 index 842c8c2786d1..000000000000 --- a/news/2 Fixes/10071.md +++ /dev/null @@ -1 +0,0 @@ -Re-install `Jupyter` instead of installing `kernelspec` if `kernelspec` cannot be found in the python environment. diff --git a/news/2 Fixes/10072.md b/news/2 Fixes/10072.md deleted file mode 100644 index 195bfad15543..000000000000 --- a/news/2 Fixes/10072.md +++ /dev/null @@ -1,2 +0,0 @@ -Fix zh-tw localization file loading issue. -(thanks to [ChenKB91](https://github.com/ChenKB91/)) diff --git a/package-lock.json b/package-lock.json index 90be962cc550..1e7f8ee744af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "python", - "version": "2020.2.0", + "version": "2020.2.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 0b3c35454d58..db5ba88ab73d 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "python", "displayName": "Python", "description": "Linting, Debugging (multi-threaded, remote), Intellisense, Jupyter Notebooks, code formatting, refactoring, unit tests, snippets, and more.", - "version": "2020.2.0", + "version": "2020.2.1", "languageServerVersion": "0.5.30", "publisher": "ms-python", "author": { From dcc695c756dbed14fc868a584e57fb1a8d28c8f8 Mon Sep 17 00:00:00 2001 From: Rich Chiodo Date: Tue, 18 Feb 2020 09:50:06 -0800 Subject: [PATCH 21/30] Port fixes for second point release. (#10146) * Better messaging on notebook fail (#10056) * Install jupyter instead of installing kernel spec (#10080) * Install jupyter instead of installing kernel spec For #10071 * Eliminate variable value when computing data frame info (#10081) * Fix ndarray types to be viewable again (#10093) * Eliminate variable value when computing data frame info * Fix ndarrays to work again Add test to make sure we don't regress this again * Rchiodo/kernel telemetry (#10115) * Add duration to select local/remote kernel * Add notebook language telemetry * Add news entries * #9883 telemetry * News entry * Another spot for kernel spec failure * Add telemetry on product install * Fix install telemetry * Undo launch.json change * Handle other cases * Better way to handle case * Wrong event for jupyter install * Fix unit tests * Clear variables when restarting regardless if visible or not (#10117) * Use different method for checking if kernelspec is available (#10114) * Use different method for checking if kernelspec is available * Fix unit tests * More logging for kernelspec problems (#10132) * More logging for kernelspec problems * Actually capture the exception on the new code * Not actually using output if first exception still there. * Actually only return output on one of the expected calls. * Fix nightly flake * Check our saved jupyter interpreters before allowing any of them to be used as active interpreters (#10113) * Update changelog and package.json * Missing part of changelog * Fix tests and linter problems Co-authored-by: Ian Huff Co-authored-by: Don Jayamanne --- CHANGELOG.md | 77 +++++++++ PYTHON_INTERACTIVE_TROUBLESHOOTING.md | 17 +- package.json | 2 +- package.nls.json | 2 + .../getJupyterKernelspecVersion.py | 7 + resources/InstallJupyter.png | Bin 0 -> 14757 bytes .../common/installer/productInstaller.ts | 18 ++- src/client/common/process/types.ts | 4 +- src/client/common/utils/localize.ts | 8 + src/client/datascience/activation.ts | 2 + src/client/datascience/constants.ts | 14 +- .../interactive-ipynb/nativeEditor.ts | 35 ++++- .../jupyter/interpreter/jupyterCommand.ts | 53 +++++-- ...yterCommandInterpreterDependencyService.ts | 23 ++- .../jupyterInterpreterDependencyService.ts | 50 +++--- .../interpreter/jupyterInterpreterService.ts | 146 ++++++++++++------ .../jupyterInterpreterStateStore.ts | 7 +- ...erInterpreterSubCommandExecutionService.ts | 6 +- .../datascience/jupyter/jupyterExecution.ts | 2 +- .../datascience/jupyter/jupyterVariables.ts | 7 +- .../jupyter/kernels/kernelSelector.ts | 35 ++++- .../jupyter/kernels/kernelService.ts | 12 +- .../jupyter/kernels/kernelSwitcher.ts | 11 +- src/client/telemetry/index.ts | 75 ++++++++- .../history-react/interactivePanel.tsx | 10 +- .../redux/reducers/variables.ts | 25 +-- src/test/datascience/activation.unit.test.ts | 1 + ...rInterpreterDependencyService.unit.test.ts | 35 +++-- .../jupyterInterpreterService.unit.test.ts | 31 +++- ...terSubCommandExecutionService.unit.test.ts | 40 +++-- .../kernels/kernelSelector.unit.test.ts | 21 +-- .../kernels/kernelSwitcher.unit.test.ts | 20 +-- .../datascience/notebook.functional.test.ts | 2 +- .../variableexplorer.functional.test.tsx | 42 +++-- 34 files changed, 648 insertions(+), 192 deletions(-) create mode 100644 pythonFiles/datascience/getJupyterKernelspecVersion.py create mode 100644 resources/InstallJupyter.png diff --git a/CHANGELOG.md b/CHANGELOG.md index a425fb90c29a..b3063ba7db68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,82 @@ # Changelog +## 2020.2.2 (18 February 2020) + +### Fixes + +1. Improve error messaging when the jupyter notebook cannot be started. + ([#9904](https://github.com/Microsoft/vscode-python/issues/9904)) +1. Clear variables in notebooks and interactive-window when restarting. + ([#9991](https://github.com/Microsoft/vscode-python/issues/9991)) +1. Re-install `Jupyter` instead of installing `kernelspec` if `kernelspec` cannot be found in the python environment. + ([#10071](https://github.com/Microsoft/vscode-python/issues/10071)) +1. Fixes problem with showing ndarrays in the data viewer. + ([#10074](https://github.com/Microsoft/vscode-python/issues/10074)) +1. Fix data viewer not opening on certain data frames. + ([#10075](https://github.com/Microsoft/vscode-python/issues/10075)) + +### Code Health + +1. Add telemetry to track notebook languages + ([#9819](https://github.com/Microsoft/vscode-python/issues/9819)) +1. Telemetry around kernels not working and installs not working. + ([#9883](https://github.com/Microsoft/vscode-python/issues/9883)) +1. Change select kernel telemetry to track duration till quick pick appears. + ([#10049](https://github.com/Microsoft/vscode-python/issues/10049)) + +### Thanks + +Thanks to the following projects which we fully rely on to provide some of +our features: + +- [isort](https://pypi.org/project/isort/) +- [jedi](https://pypi.org/project/jedi/) + and [parso](https://pypi.org/project/parso/) +- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) +- [ptvsd](https://pypi.org/project/ptvsd/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) + +Also thanks to the various projects we provide integrations with which help +make this extension useful: + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [bandit](https://pypi.org/project/bandit/), + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +And finally thanks to the [Python](https://www.python.org/) development team and +community for creating a fantastic programming language and community to be a +part of! + ## 2020.2.1 (12 February 2020) ### Fixes diff --git a/PYTHON_INTERACTIVE_TROUBLESHOOTING.md b/PYTHON_INTERACTIVE_TROUBLESHOOTING.md index c24ac2d0fe77..35e3f779e765 100644 --- a/PYTHON_INTERACTIVE_TROUBLESHOOTING.md +++ b/PYTHON_INTERACTIVE_TROUBLESHOOTING.md @@ -1,6 +1,6 @@ -# Trouble shooting the Python Interactive Window +# Troubleshooting Jupyter issues in the Python Interactive Window or Notebook Editor -This document is intended to help troubleshoot problems in the Python Interactive Window. +This document is intended to help troubleshoot problems with starting Jupyter in the Python Interactive Window or Notebook Editor. --- ## Jupyter Not Starting @@ -10,12 +10,21 @@ This error can happen when * Jupyter is not installed * You picked the wrong Python environment (one that doesn't have Jupyter installed). -### The first step is to verify you are running the Python environment you want. +### The first step is to verify you are running the Python environment that you have Jupyter installed into. -The Python you're using is picked with the selection dropdown on the bottom left of the VS Code window: +The first time that you start the Interactive Window or the Notebook Editor VS Code will attempt to locate a Python environment that has Jupyter installed in it and can start a notebook. + +The first Python interpreter to check will be the one selected with the selection dropdown on the bottom left of the VS Code window: ![selector](resources/PythonSelector.png) +Once a suitable interpreter with Jupyter has been located, VS Code will continue to use that interpreter for starting up Jupyter servers. +If no interpreters are found with Jupyter installed a popup message will ask if you would like to install Jupyter into the current interpreter. + +![install Jupyter](resources/InstallJupyter.png) + +If you would like to change from using the saved Python interpreter to a new interpreter for launching Jupyter just use the "Python: Select interpreter to start Jupyter server" VS Code command to change it. + ### The second step is to check that jupyter isn't giving any errors on startup. Run the following command from an environment that matches the Python you selected: diff --git a/package.json b/package.json index db5ba88ab73d..8e11ca5be90e 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "python", "displayName": "Python", "description": "Linting, Debugging (multi-threaded, remote), Intellisense, Jupyter Notebooks, code formatting, refactoring, unit tests, snippets, and more.", - "version": "2020.2.1", + "version": "2020.2.2", "languageServerVersion": "0.5.30", "publisher": "ms-python", "author": { diff --git a/package.nls.json b/package.nls.json index a70fc4d71a7d..594eb1bbde3c 100644 --- a/package.nls.json +++ b/package.nls.json @@ -193,6 +193,8 @@ "DataScience.libraryNotInstalled": "Data Science library {0} is not installed. Install?", "DataScience.libraryRequiredToLaunchJupyterNotInstalled": "Data Science library {0} is not installed.", "DataScience.librariesRequiredToLaunchJupyterNotInstalled": "Data Science libraries {0} are not installed.", + "DataScience.libraryRequiredToLaunchJupyterNotInstalledInterpreter": "Data Science library {1} is not installed in interpreter {0}.", + "DataScience.librariesRequiredToLaunchJupyterNotInstalledInterpreter": "Data Science libraries {1} are not installed in interpreter {0}.", "DataScience.jupyterInstall": "Install", "DataScience.jupyterSelectURIPrompt": "Enter the URI of the running Jupyter server", "DataScience.jupyterSelectURIInvalidURI": "Invalid URI specified", diff --git a/pythonFiles/datascience/getJupyterKernelspecVersion.py b/pythonFiles/datascience/getJupyterKernelspecVersion.py new file mode 100644 index 000000000000..1dbcd7694bfc --- /dev/null +++ b/pythonFiles/datascience/getJupyterKernelspecVersion.py @@ -0,0 +1,7 @@ +# Check whether kernelspec module exists. +import sys +import jupyter_client +import jupyter_client.kernelspec + +sys.stdout.write(jupyter_client.__version__) +sys.stdout.flush() diff --git a/resources/InstallJupyter.png b/resources/InstallJupyter.png new file mode 100644 index 0000000000000000000000000000000000000000..f36c380608f450439738eb357cd0b4458bb69413 GIT binary patch literal 14757 zcmeIZWl&vRvo4CeTX0EW;j#k3Ed&UJg==sL!7aE4cM0z9ZVPt}9-QD3TmuA`JIVWg zd+$@X?y2+RR^2~$Rv~MyVY6qC?tY%p9ikxj9utie4F(1VQ(8(~2?hqP8u-5)1rGSl zz*$ub{DHMsdM^f3F-E=zd_XXHEBh7(raB7!-T)E!jA|?O(H;hdi0=6ZR$7Vn6b6Qm zUt0XFii_@1`oom!O#III3ka80OtSQu(R-se)!_wGDGoXPrXDi6lG8Xja4#_t6ki!C zP<@+QlZk%u78eKMEh3jFBqysVtEjl*xcGQ4@dDyp!mOMuUDy(Hp)xKb`^V$BmW?^g zacucYxbxgL)4iibSU970e8u9V?Q+4r-2S*J@ygSZ!}G%S_WSw;RTSjut@Pi^tS-Oc zg-BY8@Z&2gGq;B*ujy_WnTVvUWKUjd(^+)8&JJ~@zZYqG@!s$|5B=lzy}NfBr@{ga z!=p7pxv;T+)}w{<{<*kFm8R^mLH4`bOQ{);-@mUlfPJp7)VrYRi;bXn{sbf%Flz>HIYCtxM3@?)`Y$0l&l9*4E42a7q~H zEFkJOc0>d}1MyeX!P%Y2V*DTf9j`@s$^^TBm|R0cv;-491?+?T+=`RB%Cs{t(}A~5 z?|-z*bco@zi^7W|Kn8|SL?ys~9#}{| z95onr-^e#sUijwW#M}Gdf#LM1^f*=i>BJa{3iL&p$dZNF4y~~hGl76lG;WkpsD}r^ zf4>VBmH_)a-y~)D`<*y^AHwsKn`R}6KF@+FCknCc-z$8Y;LB|HKJ3GeYPsKLe_U@e z@pw)6+^_dL=NE9-&yFj1=8C5w`E9v}KRF+tYOd?Qi(o*!4=udKeN-f#M|#yS)r(N* zbw7Qg>)yw{J>L6pe$`nC9)@xLzWX$+@MDPNoR=t!r7`gK>uN@8}$dU|8p; z%CY-?8zh~_&iOETkw0}RFk^g1Bek&u59i%l-fgC{_0n_G3AoQ4s$RE(yGROw#d1(n zvzXpZbh5ti%4qcI_D6i4+(GquEj>dV{Rr2NtpdUsRbSVrb;`F=#yz(SuVn9LxipN@~kJ(f~p^WF)NHXWD*WD3r((G8*iq~}ymGx@7&=!?* z4)hAuOfib~e0#KKvWiDQNOEh@X?jRXZjB=--fpvkLd45sDBNR{j7QsXW`?oWJ`fDL z-tOCZ`0_X+l4*bbVodOr4wLO7-3x^Sn{Bza(?iawe1wA2&FB@^o%DyhE1UV#>F?|( z=WKR@1G^X+$}cPtbQLr=*cD*r%?dECG10Z z)nS$(fIn%+|OTRu(p==bheC;4ny?SsIu9sd<{FhY&yfrk8%D{h`2H z)Ak^3nEhge@r74AxA67C&Un*3r^({)Vk(h8TYGv>qZ^BqZO3Tr3g`u=vsyN+TJ@Ie z-4erzl`fArJHLBfjD7u7OVuJsrY6+M$N6@aFv++rS6cbDoUv%gs!<}27oe%uWglw; zBf)gJ&WVgHDq8+JTY}BWds8N@7n3r}RKDS&5Dpbp1`w~gJ4fYpHntrX`ykylAEWOcR19Y5* zuiBb5No*zq1WD>t6Z=%%cHM4!zjH7?^FW} zeRDt4mRlEDF@kv6rf(lN@o+kA`w-;i8qf5IR{QnF`5vaHGExPPdBSYmuOdSzi6AYz z=prrNNVuI1Y!63%k@n-)zw}0u#iZWquP3XT8^I9^I31Q&w%;yTRO+~HsqQJo8!fq& z@rU?1m|f%~t+`|;bt*zQ3>iSX$Vv#dt#EL}6-jHr&hqB--sWK!X8)XFce^K&#GO&K zR=#L0xDyWE?65tSKS`CW4p7&@3+p;Ao>R7bRMnHa`KAVjEz_vpSax1b7jUjf*L6Q~ z92dT0sW+{p0N%w->-iWxRajlrlaN8puPBo9!M?B;i}bj(SjWu=Z20lK=Ogk*OHIJ8 zS#4bpB%8|rKFTBiv(24Hb_&6p$7;c0jBiKnfw^s=(QZ@ArcDC;_{H)8fjykz@`GDI z8ijz9w%cC5E`>SS%cr_2;cDCUZa|5(`h?ssA!)pfYT>;BDfOREkY;dw84%j<&xTiT zXVcYS%5Hf&_|5}f=&qH_w4HXdTP-#2b^5^1g4u4gI93oofMRMt632Y`igmyHUZlo{ zlj3}5{7U8s^DtsgRWfrQK5kuy2J!|q;TrX+9rZ+`}K za)G2RdLnjR-wMs6`tm~(4+TU4@VS$b=(Nz)QdnIc+JM7ri`lXhj~#*C+2&EaFskwF z=%2MGXN*~bhE}2FGN0VOs1l6SlzA}2PgF2;D#;?EQE=u+!}NS|sBAqOYP6ekBPnd< zOe*?x^VP0Kvh0H&v*%S*fvc(gP}wawZ&-;!4qS^`IT6Z^O3Gipk_ z0pQP>-x}Mg8L7~kUk`dY&Q&ZsFWDi_cv6ROK@MzP&BECPu{7#Tzfq98i^BBa;m=1r zjvr@w^-*!H;@P60AMT(%PU-MG^>kk7v8Mg`(KxI`GVd{^K4lch1aYdNM^5cIvy9># z&iXYJUrNNLeQ|$2ZiKm5Z)GI^-cKe`_`BpgShlV=bK$vYfilTQi_R<`Yd-y~F`hR5 zHj)JH*?Mn@-^IhCQAJ(xGDsF}^Bn8+s%a-9SKT^S?Jy^d&1)||ard&>@qpoST3KEZ zy~PB5t%R_Db!u^dQtJr5i}gm!rJU4|wftjkKiXn2j#yA3q^XYyv>{fmqkdTOY=UdH zNGt-3qmX|1sqb7Mi(GfLU9B9r!{U9{Zn=~$Swq~T_mkjFEJMxld7I`wc3hfSpkm z*=}erta6WN3={d(V1-W0Zj!3O<+rb5WiYQ5dHH_jz9f}E4G$9zrxMA?o+-((Ot6Z_ zMrk1Dlt9xMz_AEaKTbjo0U4ySyw+-)(^(b)dz0^rkRYv77MH zc?R`5q`A1Y8itjdggBjmOZ5J8q-DO!P)Ehux%K2WQFfxM_4IN*r<6UrvtAk#dl?NR zu%PTuoass8w@Ey#(e4qjDpmcZ%By0*Q?!O`b4=jm!UTiEWNcYuWdUj-L~nOcUR%Wp zLK?X2gvajv{uMLQ3X9nU>|S8NZJv&RrNLVJd3hT#xDq*0JeOWA>CIY2qK~b>##M1Z zAl7>+`D@`fUiWj=G?(w$@k7v|PCEHsE4DomyZGe`oTw$aXvdtbFdT?p_L4mFA8>qE zc%dNT1=a=#6pn*-3+MLQAMQ-#VQ;lzQ=DAWygS%E!4bnmT1$7WW|+;SwA)JCu1{Uz z%_4(Vo~uLS*-&YfPq|h@O34%!%9f8t;t-X4{LxQZg2UeMF705#PVG$BZIS|(;%);1 z?T7+n&M~XDQ5RK^Mwzxkz>K+Z0^-)mVnY=CrQNnrB*8AsvaQyBo{=@)WerEMswm7> zI;`U0S!K(y8^VTrEBtP>UDH0Em8vX$-L4`o2bv-E>ktLj!jgS)P2knBmQ|W-DHqD+ zy9*ccthh}1z#}(OG^DAl#E;v3RCjvggy&P_#vw>522s!;&HbiGgg-4z4|9hLr!8D} zy9XDB%Dt+xc|rkNJYw{5O4?I%C%>^y9JDqE8!;ss80oaSfcq>Ro1Su6SF`azv-~$( z?0VgwuQtL~!*DIaEz7FdS^Wf5kPI`RKX7<*zbA97lV$kfh=XkdPm-~6w5y>9On-n_ z)N?MY`KpAl9`kpik%ccohae~IR+&~qh7j%!ZoIM#xu#`z2q5zCf;~|dWd(t&ciPPl zmjYOsl-2N*%Pb86%_|?u{pStHHD=@*#eD!13bN?(Ma<}-9F;p#4)jqqo`k)0u4f9f ziDAlm-WKu_B`p@troM1XC|{PO2Z-O0-fi=kOp@ys-qYxJ*BzDifL>|}^R#GyzWMLK zD2uXkc8h{s-y(pOtB$-wflCziWLtzt>CP{Ls{aZxQ^ z6S334L=Q%a-13COKtJ#Pei)a^RM&q5=S+-H?w{~1c8u`P8@btNJVZ{G;Pb>yv3J_96&azEy4pq1gOc0t zy-x3x83$NY!m!D??8k+!@c3R7clA5{}@*Sh_&5m;^hCb7wt#HJs`n5ZdLExdN8~MFkXp z|0T`Lmq`YUUyUFOV>q~CQ$3YZwCsckAv*j;wVPQJz0F9oPV!Im6tzYy$hEYugZoP2 zoRP%ohUragA$)YIyvC}FKTsStR5^6)n9pv;y?v%MX>gfOmf3iQ>Ff^tv1yBdbuA34?-gxElyfMC>i+z=Jp-_eME9D95xCImQ>+DcU3Qf zzMRlQf9F;v-yQpj^?lg;(t#&jyBCo1h^F(xuMq0#d=7yo7ef|juerFR8zp6Qz zKxJqtABT3*$wV~npx1srn9}oNf~y~y(k1J1roN`c%JdZ#zG&&6`28HA9N3{Moaic# z8#JQ3l{R;?NXgQz-2S2F4fD{3PJ)eR`>$#6%LO(|Bo_=Sihzk!*Wl0w`#c02+(-DZ zXE+u-;0Mbu+rH6VecfTZO>(jV{#LctG`M-6DcpRC{j}DxEV8-ll?iirF2;>`X<<2? zfgefrLEsvVT^6d`t#xItH4R^TIc)q{Q|NZU)5uM0^62DGW&Oag}v>lnw zaJ3B8dt)Cl#!5w^n(@8rD&U<}ngH8!%HZdgu|`LdCF7Tyx+SIMUJ)OCm}ic0sa>wx zVn!gT?HTa?!kSQ(#<G*Oi`vGnU%2Z#37xn_dCbRK=OZFctEaCptMJ z=mkS*%32^!;fx9L?v$KGfHfifSbo5`nU~?P;06^opNRvGtZf8s-ch94(YO(a#gde`4YmliW!>;yOB-mKG-dmW= z$Bt39a8;palM^u-srS8E&}sp&sIbE>&SC^R9{mD?kco4y`h=b20;xkbjk}QWv9a;r zpsB29FqU2mOJfSaU*MbSW}nsk(1GiV=*5~bBj5U=YMyKiw3GSj9_M@U!_=cHT1a=r z>;lreo}w}saiG}$2i`YC@ELdL`|5e!Y`MJXW9l}4 zxRcZ1L|kG6+Z~1zLY>N!=f>{(IN5fIbGKTE`%fp_ULqm?wsQziL3oT>MVVPMXCA7iE}$ zZw%}coFjkXA89iB)5Ie{kQ)7?M2D%_Bk1OfteRES1Xz;vtf9BGgdx?Ken@_(uG)5= ztu{7NB9=NV0;SPvk$YsmtPe@95-oGTz+e*1iZG$y)F+jB z)zV^b#T(vigkHF7`Kg1Yz5Ld_zr68mY4vGvskkFe2WJ#lPAx z<$EC-;m?JQ9-+GrzNoa-qpW)E27PkY<;Nb zJfKCE7inv{lq1~`v#PGh5RG7%x|PmE7lDJvfIS&LmUblwpidR?Zod+IV}K#ehb?r$ z;rB<;-uy;YX;ogx|YJ@os2`GpyeMz5nbE^1k};Z*ZM81 zr28!NLzmjjG(S=C?%&5&`4cj$0qT>j+M?ocgJm9)@+pr+$jM&P-0=CCQWgdxc| zXsEDC$nC8!p;To|-I2y?R41*^2#UX5zbdbg#4z-z(Qz76@VcB*vnA*VB-rsQzDeIf z>gORZJ8r*2A}&a*RCS~+Z>*0XnpKCgf>74gl2F|Dr;F2KOykaq%k!#hDom$^GdA&N z!!TD}Hf0r`{+c}iY@!hNC&3)r!*=_2w7L(e?#y}{FC{;-E?%cpA0pYwQS8Wzm!VqU zF5}>c@OvB318@wv0KyJ-Ud!Jfu_H<3{C8zkxu?}>ckTER-&V7?u1l#m9StGQM&nn% z9pTCu_!#jWa2Eg<5oUZBzRntqx$g5%x1m}-z~MM{+abUKXKK$+yY8G6uhcG@^> z(1WS|(3i&8q01E}4Zh>mpDo-7Wt_AwPW!+nW-I;Pl7INhR6)hkRWQF@yuyN--{lzjSUe(!X@B=>MLw z{f8gU@%i6(4xdfZ|6fSVXtof8js4P&+kP?|!N==OMm_R3R;q3bW|=Oxd!xu$)@Pg}p2E@+O~5wP|nqJeqPoCLj`j7>$pI zukHOXm*M?*)3EB5`q%+bknA1zXNNzX*BO<;NqqJNgrx=D9nK!-qsmn|&MU4#hAQ6o zzv-2HP>v?~J+tWJ22|N~TWRBc#=S0U-7h_;%p4eXKGdo1C7XDeAIz4&$Hh-`oc#&# zREIL`Z4MI>FSM8eN>#=iG?6x9>Jp_S{l@qb3MGkjjUqV3be zRjslfK&vr!kP%0=e}q(dKRxElP-!>XP5_)KKre)Ga*BLIQ%@H5M54=OHb3YL^aHH( zUjM5ok3^a>?WRzywT_)pcWOdEVD<|iWXdd!U&VzPZb0}qAIbSifJBl9`s^GMRSvjASj3q?rh*y6evg==804H16yy&{^f)o98a ze?*yt>7`}Rylt#{ZG?-zk#8?1&(e3wTL9y2BJt~#_@4ZPS~yROB6z!=u62#3^4QCy zv(3DAJ{AhXqR@nzs~#z%nE=XhcX{;gjH3@BJqgXz<Fb^2ehzpE1{TCFBreuGy-*m=X$5NyAlJ4;X;-V1Nnw$v<=1qx{J{zUy@D1+WuCd9#ISinPcN{mDJSb0X zuuj^+zC)+*mf}M@L5W<$*+#4{1I#Ri<_;=Fm2SwPn-HxDh zO%<0Xt0Ej6Ri1ZPsWlp%+mVKVXT1!-07Ce9bv;jLe1bo*fg2M@|7R_T3NU2d0b#&a zcdb`_*NRafe&v7gtkZzqu?=h7Cz z`7$>q8Ls`p{-0xWP|X$RxMdGep}U;{FT4iL*DZe5N7q{~^OL&m7Z=Wxj_5%5wX)IF zE$$LH2*2^3LN1k^Y{g*hE3Ro4$uXUrG+i$y-v6BAwqEK5Z|48uv)|6@SNm|;VscRr zP<>zS@!hmh#2BJV%25&UnC!+!HGWXOlLR@R0|qLH&=j#Jjo*=p;xoLX86q*GEdA5^ z5^$Wt5IyR--2A70?mW@6gZt}OAX3{nEQSJ+OK*zJ^_X)ze!NX(I1Pdj2jrJCF}}W_ zDTYoq7=kSdr2-Y!zI86BEk&TerM^>LmHqX*&L^{+u5t;mydr=gTj7W!A@B98|NoQ?4! z>#CE4P{kys>HO9X zE^9FPpkRWmUJ&?gimAJa;ar8zHf@Ym-V_tpPtYz!h!n_6GD1+cv?w2q z;-ziL-ZL-F=X(TMXGQEX&6n+&v?7MT zJLdi?CUN+pq8|>=Qu6gWUTVVM>=hq0x#aV@UVm>ovC$1cw6%H5P7I7{ZqGnMzb`zz zvS8*wO=v~^j}N7q1J)Jww92MqV0Co+Pp>x-vggmz(7=WlDv(aYb2$CT*bb+mnZ{Gg z9`ozL53l*Q2{xTzw9iHts%OhNoh*O9ZCxPn{B-tM*bXgMT5RwyMtN_%D&Y@UufEYR zchloM#&^LIOZDhuWPHAs-oR|OXDIsKj z@Oa1Z?TlhWqB-4{NlXZ?eWCCerHqL@>iW3l+_>CZl>^2)O@r2C#~l%Sj{~UYHe2A;gPXgftaO0lzluden%x3H+R*@7jT((6yf&Q zk%gaa%8zmN%NI9$&E;8kfKw=`@~o^msnq&L)T?k9LWiLsZe!L#LQ05x9Ns@ zRr9+9DFI8?ZDAlh@E&GWo{;pI*R{$ik3q*aBEj<8;EEvN-!t)NSag%!rlj|J z8kw;BINRfA?L*W%xT~_@(35X;N~;TM#Yb8>%{^+>fsI-Vb!N(L>@lFpBNr_?drs%w zAKBO00`oFjk5*VEFStLBTLySKMK`DDN3nU^!dNZ|I3I`G!2B?&KjC3s_2x8vkx8&B zQsus(7C8i}6MU=Bls^HmGVa^!4fFeN5+M0#DP1KNBCy~gjk}W5Bo$R5Td8L2>A*)t9IL~~7<9ob4PW9H+UYj7 z?~lZKxE(wwbvA^NXsqJHk$%9#OY0qnR@Ai)x)tad^5ck6MPK&fTNH&KkOM)pU1-g}8{&nwLN0<{BYtEeO( za<^uO5G?YnbYFEXWQg7y;6K*95xib|=j8|3L$POpO>WPiwXpvh3tXe#=FHg|PMiuo zGHslfi-VK{$l@nav4pTY-J)TS+giSgYE5P7HLoJ2 zyH0riWZ&*)7<;2V0}TE`8A`gZeF#!ggJt>eWU8o`82ot&*m@B-K9A790NngpwmWTe zgko~treVb(6GzFlFzh6^&5C8pr_f~60)Yi2_+Qg%nTBw7-OqR`B&Yd(xDyMgil=Fk z4*a3o`vgWy_9kbMy4&4=PA)K{BqwM#Z!nUo7`ucTx4|wl&`g}SR+0EJ3){BGZ>?zd$H<9!IL#EXK8SMV=&Yq(k zsTZF_q9t`eGlV%*Ql(jt66WSKE>B|u{EIh(4sP*W`>%^Da2`Z85sj5}CbshSm~)e| zDy0jiO7j#Gr5yuyktdlLV)sMY=wJw4y-ik8ci=O-9ReVk zMa

li4&d49%@i9okS{bI!2zl)5DNtzImoP+dBgEp{Jm0y|Gt0a%NUTuS@vP}JL$ zPyB5kNF9M;g1xBAeSx*?ewn<8SA_hSqn+AQoh%y8YZkkJHzSObc9ckrEvO7P^lb+v z%T>nwfBHyWRp-~6QBS8qB7#r%=t^EZ(U3y)o8iod^YO<$Z{5c=8FFuvtIYe8r@JTa z_TO{WqV#{o85F`OfBZDs@tFDWbYsHU;htr45$#pr;YVVi`*^haIBF8)x*q31fKMyO z`_D7?CR|RG`<~?pm;+)VSxH*^mp!?^wspHZYA_i~OCEBd2e=3er(4@@XyI#$Nf|I~ zV5E9KPvQN#kxDN@*(dv;gk5_k1!IRk1nF}koL+;-Rs#pAtAi$)zY4L)H!p4fja)9B zC1C=ye;7*CjM&Uy6E<7|q)GaqUthiBs6FqiKw!M{#9@;dIQ zI*xlS8KiX{3+~x^B}HUz<2#h8ZcUN zl|<@8_>*KIxW98mpJoo}1iuR9gED|jhoc2a?xc7I5Z<>12L0EdrlF{k;kXC#&l_U7 zp8U^iI|6)ibU?*1)FCiH790Dj#wPDkuA7oWCv=>c*KyqZ_&Gu2m%`kuC^a~~wdu25 z_X5K&_i{9#B3-zHm8;!O94# z!W!#h0ql^njjzQoqfEvg#io{!+cuxf_C1MaC zWD8OSA*R$4= zW2!C;ND$B(Y{x1-o6LNijszbxVz3OD`;-&$c+$EUwEUtIpntYmi$q%0PQYr!E0Q2 zi$=Z5@&>y!wIfw8rp5qE`kB}Wu1A}ckx#Kz|DthCcXf%j5US26XFX$Il2OA{qB@9x zm}4ZDkyMcTBB~GyeoKI8#}XHwL;WY&Pa{i>?>%6<>-FPi;y3H9FJ(akpMSLHy_&D9 z^wEsg7dxCsU#uyM{|NdkC)8PRg2gma@0j0SZ-Rqhq#NgkRP5L*t2ZQ!Bf*Z;M{h0$ zf?~P!(u27syF1IRElZgqN>{iB%&uqZJ1aqkQyeO0s#^nR$>t?9E%?I(*C*!2b>`c>VPujOSBmC!^P#~ zoDX&1F-Q0-*m{N*x!<0_u|;n-x&(?p`=%pCI#8j2GxGNmeWi-< zA)2zFGId#KedAz}6AXiN!I3bicOXWN#;Hc|)O>lLp>f~5OgDl8zBlEUW)8@pXtJc+ z$dyesKc75u5KL3d*-1QD{f)F3vM-{@D#$C+~*~eCi*25vZoB@=~>un>1e8 z3LPz_PC8_AqYhLOz&fy9#~2f7QuUwN^T>TDc}Zq@N^2T&5^~_E1?$l}3LvLiRmo zoQdH7^5EJKoCm!bSuuwmKQCJp@Y{0HqJ+cfFAx|4j)wFUN+n3AonxK?Tc_EPew6R? zD3Cfwv^rW(Git4)wn;8_{L#oq7cMxF6U!X&J^LU5ummE#6r z$*-$-Xnp?K=ijzZ59^xic*}L}?JC0uqCYKs2rixbA1}7=1*>PljbL6t~73)b4$Crj$TRzG!s)d)orkTQo>=Va|nHH&PMF(=LnC+S8 zEO2d2Y2;LtaVpvryQ@Z4i=_YSfeZZiITQo13kA7oZK3hsL`mIMTDnv-Z_Tv^O=Ih7 zr0Ff?v_`)OR^SPIrc=&M1Hm8r15qiEK;1dG-jGw;6DzSZVCK-=*zXc5A0dCuIATTv zs(P*H3xxYL(~k5J{+MJLulb56q!yE4EX9FC1ZEe9toUEugLbMKH+jhpr1>8s(SOaO zPifs+e&DRuEh8LsSn$mrU}Y~S9|p(vWvxCAj7t!{rRkGuSt~W0o>trQ{hn4@M z_r|+U+AC%(4sV(ao`yshNO`mJup@p`-Y#Y?7RkD|D}P0oPJvKQRchLo8^TFZR4LnV z{S)|nl_^J()9LLOR!9CmbJn0@xbBbw99yRy_H67n>wkr)oZONejTuwP% z3+WhdeNwQ|Ix&OIqVlsAZE%qQVi7hhZHs`vaPkS2{&Gm%nBNB(sBk-YPcs^C$*5L1 zF8m^JaP@J_+bltN@=Vqx+0etx%u}JMV<@3&W|A1N6Y#;wj8_|Z3Pd9)NQ<9j& zl^ZWjUs7wySM5)5FGetxeE;k;Euv;S@CkBsn}rt7`P?Sv#Gy4&~PyW(glQlmik{G_j+ zs9xTWtyL1I3nt0&r>#`}Q%^U&T)bB+&p(*PyRx)GQ$>%EcM-i7oJ1XnNJOHcvG&b} zKDOfDmQbK2a;yYA?bG+KDxOk5f>E#81At~2fw&RhsgaQXQ%*NiHd z#6%jOIEW>=UctvmhYxE0Q|za-A2WUNgXT@!^|vTwsqG6^7@!Wyi0V$`6^Qy{MLhM# zfG(*V5^@c5G_`*^>>p2GEcp$RH}hQ;6jmZ2L;#Ohmq z!AMd>IMJkF*kYi_kcIlq0fn5b>wnfq56rnfeev57wrfE6vib>|3ppU~G_`UKD6NE% NmXHYzYlzW{5igd_j} literal 0 HcmV?d00001 diff --git a/src/client/common/installer/productInstaller.ts b/src/client/common/installer/productInstaller.ts index d05a0ff7a0d1..7c07fd50dec8 100644 --- a/src/client/common/installer/productInstaller.ts +++ b/src/client/common/installer/productInstaller.ts @@ -5,6 +5,7 @@ import * as os from 'os'; import { CancellationToken, OutputChannel, Uri } from 'vscode'; import '../../common/extensions'; import * as localize from '../../common/utils/localize'; +import { Telemetry } from '../../datascience/constants'; import { IInterpreterService } from '../../interpreter/contracts'; import { IServiceContainer } from '../../ioc/types'; import { LinterId } from '../../linters/types'; @@ -18,6 +19,7 @@ import { IProcessServiceFactory, IPythonExecutionFactory } from '../process/type import { ITerminalServiceFactory } from '../terminal/types'; import { IConfigurationService, IInstaller, InstallerResponse, IOutputChannel, IPersistentStateFactory, ModuleNamePurpose, Product, ProductType } from '../types'; import { isResource } from '../utils/misc'; +import { StopWatch } from '../utils/stopWatch'; import { ProductNames } from './productNames'; import { IInstallationChannelManager, InterpreterUri, IProductPathService, IProductService } from './types'; @@ -278,7 +280,21 @@ export class DataScienceInstaller extends BaseInstaller { protected async promptToInstallImplementation(product: Product, resource?: InterpreterUri, cancel?: CancellationToken): Promise { const productName = ProductNames.get(product)!; const item = await this.appShell.showErrorMessage(localize.DataScience.libraryNotInstalled().format(productName), 'Yes', 'No'); - return item === 'Yes' ? this.install(product, resource, cancel) : InstallerResponse.Ignore; + if (item === 'Yes') { + const stopWatch = new StopWatch(); + try { + const response = await this.install(product, resource, cancel); + const event = product === Product.jupyter ? Telemetry.UserInstalledJupyter : Telemetry.UserInstalledModule; + sendTelemetryEvent(event, stopWatch.elapsedTime, { product: productName }); + return response; + } catch (e) { + if (product === Product.jupyter) { + sendTelemetryEvent(Telemetry.JupyterInstallFailed); + } + throw e; + } + } + return InstallerResponse.Ignore; } } diff --git a/src/client/common/process/types.ts b/src/client/common/process/types.ts index 1ac520a1a8e2..17e8143c5614 100644 --- a/src/client/common/process/types.ts +++ b/src/client/common/process/types.ts @@ -113,8 +113,8 @@ export interface IPythonExecutionFactory { create(options: ExecutionFactoryCreationOptions): Promise; /** * Creates a daemon Python Process. - * On windows its cheapter to create a daemon and use that than spin up Python Processes everytime. - * If something cannot be executed within the daemin, it will resort to using the stanard IPythonExecutionService. + * On windows it's cheaper to create a daemon and use that than spin up Python Processes everytime. + * If something cannot be executed within the daemon, it will resort to using the standard IPythonExecutionService. * Note: The returned execution service is always using an activated environment. * * @param {ExecutionFactoryCreationOptions} options diff --git a/src/client/common/utils/localize.ts b/src/client/common/utils/localize.ts index 56d85b0211bc..020ef99f1c95 100644 --- a/src/client/common/utils/localize.ts +++ b/src/client/common/utils/localize.ts @@ -211,6 +211,14 @@ export namespace DataScience { 'DataScience.librariesRequiredToLaunchJupyterNotInstalled', 'Data Science libraries {0} are not installed.' ); + export const libraryRequiredToLaunchJupyterNotInstalledInterpreter = localize( + 'DataScience.libraryRequiredToLaunchJupyterNotInstalledInterpreter', + 'Data Science library {1} is not installed in interpreter {0}.' + ); + export const librariesRequiredToLaunchJupyterNotInstalledInterpreter = localize( + 'DataScience.librariesRequiredToLaunchJupyterNotInstalledInterpreter', + 'Data Science libraries {1} are not installed in interpreter {0}.' + ); export const selectJupyterInterpreter = localize('DataScience.selectJupyterInterpreter', 'Select an Interpreter to start Jupyter'); export const jupyterInstall = localize('DataScience.jupyterInstall', 'Install'); export const currentlySelectedJupyterInterpreterForPlaceholder = localize('Datascience.currentlySelectedJupyterInterpreterForPlaceholder', 'current: {0}'); diff --git a/src/client/datascience/activation.ts b/src/client/datascience/activation.ts index 4ff5b35c8d7c..7e73b10dd1a3 100644 --- a/src/client/datascience/activation.ts +++ b/src/client/datascience/activation.ts @@ -28,6 +28,8 @@ export class Activation implements IExtensionSingleActivationService { public async activate(): Promise { this.disposables.push(this.notebookProvider.onDidOpenNotebookEditor(this.onDidOpenNotebookEditor, this)); this.disposables.push(this.jupyterInterpreterService.onDidChangeInterpreter(this.onDidChangeInterpreter, this)); + // Warm up our selected interpreter for the extension + this.jupyterInterpreterService.setInitialInterpreter().ignoreErrors(); await this.contextService.activate(); } diff --git a/src/client/datascience/constants.ts b/src/client/datascience/constants.ts index 4f59c614cf29..07f4e8959013 100644 --- a/src/client/datascience/constants.ts +++ b/src/client/datascience/constants.ts @@ -14,6 +14,9 @@ export const JUPYTER_OUTPUT_CHANNEL = 'JUPYTER_OUTPUT_CHANNEL'; // Python Module to be used when instantiating the Python Daemon. export const PythonDaemonModule = 'datascience.jupyter_daemon'; +// List of 'language' names that we know about. All should be lower case as that's how we compare. +export const KnownNotebookLanguages: string[] = ['python', 'r', 'julia', 'c++', 'c#', 'f#', 'scala', 'haskell', 'bash', 'cling', 'sas']; + export namespace Commands { export const RunAllCells = 'python.datascience.runallcells'; export const RunAllCellsAbove = 'python.datascience.runallcellsabove'; @@ -147,7 +150,7 @@ export enum Telemetry { CollapseAll = 'DATASCIENCE.COLLAPSE_ALL', SelectJupyterURI = 'DATASCIENCE.SELECT_JUPYTER_URI', SelectLocalJupyterKernel = 'DATASCIENCE.SELECT_LOCAL_JUPYTER_KERNEL', - SelectRemoteJupyuterKernel = 'DATASCIENCE.SELECT_REMOTE_JUPYTER_KERNEL', + SelectRemoteJupyterKernel = 'DATASCIENCE.SELECT_REMOTE_JUPYTER_KERNEL', SetJupyterURIToLocal = 'DATASCIENCE.SET_JUPYTER_URI_LOCAL', SetJupyterURIToUserSpecified = 'DATASCIENCE.SET_JUPYTER_URI_USER_SPECIFIED', Interrupt = 'DATASCIENCE.INTERRUPT', @@ -239,7 +242,14 @@ export enum Telemetry { OpenedInteractiveWindow = 'DATASCIENCE.OPENED_INTERACTIVE', FindKernelForLocalConnection = 'DS_INTERNAL.FIND_KERNEL_FOR_LOCAL_CONNECTION', CompletionTimeFromLS = 'DS_INTERNAL.COMPLETION_TIME_FROM_LS', - CompletionTimeFromJupyter = 'DS_INTERNAL.COMPLETION_TIME_FROM_JUPYTER' + CompletionTimeFromJupyter = 'DS_INTERNAL.COMPLETION_TIME_FROM_JUPYTER', + NotebookLanguage = 'DATASCIENCE.NOTEBOOK_LANGUAGE', + KernelSpecNotFound = 'DS_INTERNAL.KERNEL_SPEC_NOT_FOUND', + KernelRegisterFailed = 'DS_INTERNAL.KERNEL_REGISTER_FAILED', + KernelEnumeration = 'DS_INTERNAL.KERNEL_ENUMERATION', + JupyterInstallFailed = 'DS_INTERNAL.JUPYTER_INSTALL_FAILED', + UserInstalledModule = 'DATASCIENCE.USER_INSTALLED_MODULE', + JupyterCommandLineNonDefault = 'DS_INTERNAL.JUPYTER_CUSTOM_COMMAND_LINE' } export enum NativeKeyboardCommandTelemetry { diff --git a/src/client/datascience/interactive-ipynb/nativeEditor.ts b/src/client/datascience/interactive-ipynb/nativeEditor.ts index 79bf289b00cd..8cdb2480432d 100644 --- a/src/client/datascience/interactive-ipynb/nativeEditor.ts +++ b/src/client/datascience/interactive-ipynb/nativeEditor.ts @@ -24,7 +24,7 @@ import { StopWatch } from '../../common/utils/stopWatch'; import { EXTENSION_ROOT_DIR } from '../../constants'; import { IInterpreterService } from '../../interpreter/contracts'; import { captureTelemetry, sendTelemetryEvent } from '../../telemetry'; -import { EditorContexts, Identifiers, NativeKeyboardCommandTelemetryLookup, NativeMouseCommandTelemetryLookup, Telemetry } from '../constants'; +import { EditorContexts, Identifiers, KnownNotebookLanguages, NativeKeyboardCommandTelemetryLookup, NativeMouseCommandTelemetryLookup, Telemetry } from '../constants'; import { InteractiveBase } from '../interactive-common/interactiveBase'; import { IEditCell, @@ -327,7 +327,12 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor { return this.setDirty(); } - protected addSysInfo(_reason: SysInfoReason): Promise { + protected addSysInfo(reason: SysInfoReason): Promise { + // We need to send a message when restarting + if (reason === SysInfoReason.Restart || reason === SysInfoReason.New) { + this.postMessage(InteractiveWindowMessages.RestartKernel).ignoreErrors(); + } + // These are not supported. return Promise.resolve(); } @@ -398,7 +403,7 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor { } } - @captureTelemetry(Telemetry.ExecuteNativeCell, undefined, false) + @captureTelemetry(Telemetry.ExecuteNativeCell, undefined, true) // tslint:disable-next-line:no-any protected async reexecuteCell(info: ISubmitNewCell): Promise { try { @@ -588,6 +593,9 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor { // Then save the contents. We'll stick our cells back into this format when we save if (json) { this.notebookJson = json; + + // Log language or kernel telemetry + this.sendLanguageTelemetry(this.notebookJson); } this.contentsLoadedPromise.resolve(); @@ -609,6 +617,27 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor { ); } + private sendLanguageTelemetry(notebookJson: Partial) { + try { + // See if we have a language + let language = ''; + if (notebookJson.metadata?.language_info?.name) { + language = notebookJson.metadata?.language_info?.name; + } else if (notebookJson.metadata?.kernelspec?.language) { + language = notebookJson.metadata?.kernelspec?.language.toString(); + } + if (language && !KnownNotebookLanguages.includes(language.toLowerCase())) { + language = 'unknown'; + } + if (language) { + sendTelemetryEvent(Telemetry.NotebookLanguage, undefined, { language }); + } + } catch { + // If this fails, doesn't really matter + noop(); + } + } + private async loadCells(cells: ICell[], forceDirty: boolean): Promise { // Make sure cells have at least 1 if (cells.length === 0) { diff --git a/src/client/datascience/jupyter/interpreter/jupyterCommand.ts b/src/client/datascience/jupyter/interpreter/jupyterCommand.ts index ba393a1351a1..c81bf28bf1f2 100644 --- a/src/client/datascience/jupyter/interpreter/jupyterCommand.ts +++ b/src/client/datascience/jupyter/interpreter/jupyterCommand.ts @@ -201,31 +201,52 @@ export class InterpreterJupyterKernelSpecCommand extends InterpreterJupyterComma return output; } - // We're only interested in `python -m jupyter kernelspec list --json` - const interpreter = await this.interpreter(); - if ( - !interpreter || - this.moduleName.toLowerCase() !== 'jupyter' || - this.args.join(' ').toLowerCase() !== `-m jupyter ${JupyterCommands.KernelSpecCommand}`.toLowerCase() || - args.join(' ').toLowerCase() !== 'list --json' - ) { + const defaultAction = () => { if (exception) { + traceError(`Exception attempting to enumerate kernelspecs: `, exception); throw exception; } return output; + }; + + // We're only interested in `python -m jupyter kernelspec` + const interpreter = await this.interpreter(); + if (!interpreter || this.moduleName.toLowerCase() !== 'jupyter' || this.args.join(' ').toLowerCase() !== `-m jupyter ${JupyterCommands.KernelSpecCommand}`.toLowerCase()) { + return defaultAction(); } + + // Otherwise try running a script instead. try { - // Try getting kernels using python script, if that fails (even if there's output in stderr) rethrow original exception. - const activatedEnv = await this.pythonExecutionFactory.createActivatedEnvironment({ interpreter, bypassCondaExecution: true }); - return activatedEnv.exec([path.join(EXTENSION_ROOT_DIR, 'pythonFiles', 'datascience', 'getJupyterKernels.py')], { ...options, throwOnStdErr: true }); + if (args.join(' ').toLowerCase() === 'list --json') { + // Try getting kernels using python script, if that fails (even if there's output in stderr) rethrow original exception. + output = await this.getKernelSpecList(interpreter, options); + return output; + } else if (args.join(' ').toLowerCase() === '--version') { + // Try getting kernelspec version using python script, if that fails (even if there's output in stderr) rethrow original exception. + output = await this.getKernelSpecVersion(interpreter, options); + return output; + } } catch (innerEx) { traceError('Failed to get a list of the kernelspec using python script', innerEx); - // Rethrow original exception. - if (exception) { - throw exception; - } - return output; } + return defaultAction(); + } + + private async getKernelSpecList(interpreter: PythonInterpreter, options: SpawnOptions) { + // Try getting kernels using python script, if that fails (even if there's output in stderr) rethrow original exception. + const activatedEnv = await this.pythonExecutionFactory.createActivatedEnvironment({ + interpreter, + bypassCondaExecution: true + }); + return activatedEnv.exec([path.join(EXTENSION_ROOT_DIR, 'pythonFiles', 'datascience', 'getJupyterKernels.py')], { ...options, throwOnStdErr: true }); + } + private async getKernelSpecVersion(interpreter: PythonInterpreter, options: SpawnOptions) { + // Try getting kernels using python script, if that fails (even if there's output in stderr) rethrow original exception. + const activatedEnv = await this.pythonExecutionFactory.createActivatedEnvironment({ + interpreter, + bypassCondaExecution: true + }); + return activatedEnv.exec([path.join(EXTENSION_ROOT_DIR, 'pythonFiles', 'datascience', 'getJupyterKernelspecVersion.py')], { ...options, throwOnStdErr: true }); } } diff --git a/src/client/datascience/jupyter/interpreter/jupyterCommandInterpreterDependencyService.ts b/src/client/datascience/jupyter/interpreter/jupyterCommandInterpreterDependencyService.ts index 94f73889bf50..02967215910c 100644 --- a/src/client/datascience/jupyter/interpreter/jupyterCommandInterpreterDependencyService.ts +++ b/src/client/datascience/jupyter/interpreter/jupyterCommandInterpreterDependencyService.ts @@ -9,6 +9,7 @@ import { ProductNames } from '../../../common/installer/productNames'; import { IInstallationChannelManager } from '../../../common/installer/types'; import { Product } from '../../../common/types'; import { DataScience } from '../../../common/utils/localize'; +import { StopWatch } from '../../../common/utils/stopWatch'; import { sendTelemetryEvent } from '../../../telemetry'; import { Telemetry } from '../../constants'; import { IJupyterInterpreterDependencyManager } from '../../types'; @@ -29,12 +30,28 @@ export class JupyterCommandInterpreterDependencyService implements IJupyterInter // If Conda is available, always pick it as the user must have a Conda Environment const installer = installers.find(ins => ins.name === 'Conda'); const product = ProductNames.get(Product.jupyter); + const stopWatch = new StopWatch(); if (installer && product) { - sendTelemetryEvent(Telemetry.UserInstalledJupyter); - installer.installModule(product).catch(e => this.applicationShell.showErrorMessage(e.message, DataScience.pythonInteractiveHelpLink())); + installer + .installModule(product) + .then(() => { + sendTelemetryEvent(Telemetry.UserInstalledJupyter, stopWatch.elapsedTime); + }) + .catch(e => { + sendTelemetryEvent(Telemetry.JupyterInstallFailed, undefined, { product }); + this.applicationShell.showErrorMessage(e.message, DataScience.pythonInteractiveHelpLink()); + }); } else if (installers[0] && product) { - installers[0].installModule(product).catch(e => this.applicationShell.showErrorMessage(e.message, DataScience.pythonInteractiveHelpLink())); + installers[0] + .installModule(product) + .then(() => { + sendTelemetryEvent(Telemetry.UserInstalledJupyter, stopWatch.elapsedTime); + }) + .catch(e => { + sendTelemetryEvent(Telemetry.JupyterInstallFailed, undefined, { product }); + this.applicationShell.showErrorMessage(e.message, DataScience.pythonInteractiveHelpLink()); + }); } } } else if (response === DataScience.notebookCheckForImportNo()) { diff --git a/src/client/datascience/jupyter/interpreter/jupyterInterpreterDependencyService.ts b/src/client/datascience/jupyter/interpreter/jupyterInterpreterDependencyService.ts index 34ef6f01aaae..362238a869ad 100644 --- a/src/client/datascience/jupyter/interpreter/jupyterInterpreterDependencyService.ts +++ b/src/client/datascience/jupyter/interpreter/jupyterInterpreterDependencyService.ts @@ -8,13 +8,14 @@ import { CancellationToken } from 'vscode'; import { IApplicationShell } from '../../../common/application/types'; import { Cancellation, createPromiseFromCancellation, wrapCancellationTokens } from '../../../common/cancellation'; import { ProductNames } from '../../../common/installer/productNames'; -import { IPythonExecutionFactory } from '../../../common/process/types'; +import { traceError } from '../../../common/logger'; import { IInstaller, InstallerResponse, Product } from '../../../common/types'; import { Common, DataScience } from '../../../common/utils/localize'; import { noop } from '../../../common/utils/misc'; import { PythonInterpreter } from '../../../interpreter/contracts'; import { sendTelemetryEvent } from '../../../telemetry'; -import { Telemetry } from '../../constants'; +import { HelpLinks, JupyterCommands, Telemetry } from '../../constants'; +import { IJupyterCommandFactory } from '../../types'; import { JupyterInstallError } from '../jupyterInstallError'; export enum JupyterInterpreterDependencyResponse { @@ -56,7 +57,7 @@ function sortProductsInOrderForInstallation(products: Product[]) { * @param {Product[]} products * @returns {string} */ -export function getMessageForLibrariesNotInstalled(products: Product[]): string { +export function getMessageForLibrariesNotInstalled(products: Product[], interpreterName?: string): string { // Even though kernelspec cannot be installed, display it so user knows what is missing. const names = products .map(product => ProductNames.get(product)) @@ -67,10 +68,14 @@ export function getMessageForLibrariesNotInstalled(products: Product[]): string case 0: return ''; case 1: - return DataScience.libraryRequiredToLaunchJupyterNotInstalled().format(names[0]); + return interpreterName + ? DataScience.libraryRequiredToLaunchJupyterNotInstalledInterpreter().format(interpreterName, names[0]) + : DataScience.libraryRequiredToLaunchJupyterNotInstalled().format(names[0]); default: { const lastItem = names.pop(); - return DataScience.librariesRequiredToLaunchJupyterNotInstalled().format(`${names.join(', ')} ${Common.and()} ${lastItem}`); + return interpreterName + ? DataScience.librariesRequiredToLaunchJupyterNotInstalledInterpreter().format(interpreterName, `${names.join(', ')} ${Common.and()} ${lastItem}`) + : DataScience.librariesRequiredToLaunchJupyterNotInstalled().format(`${names.join(', ')} ${Common.and()} ${lastItem}`); } } } @@ -104,7 +109,7 @@ export class JupyterInterpreterDependencyService { constructor( @inject(IApplicationShell) private readonly applicationShell: IApplicationShell, @inject(IInstaller) private readonly installer: IInstaller, - @inject(IPythonExecutionFactory) private readonly pythonExecFactory: IPythonExecutionFactory + @inject(IJupyterCommandFactory) private readonly commandFactory: IJupyterCommandFactory ) {} /** * Configures the python interpreter to ensure it can run Jupyter server by installing any missing dependencies. @@ -129,15 +134,14 @@ export class JupyterInterpreterDependencyService { return JupyterInterpreterDependencyResponse.ok; } - const message = getMessageForLibrariesNotInstalled(missingProducts); + const message = getMessageForLibrariesNotInstalled(missingProducts, interpreter.displayName); sendTelemetryEvent(Telemetry.JupyterNotInstalledErrorShown); const selection = await this.applicationShell.showErrorMessage( - // tslint:disable-next-line: messages-must-be-localized - `${message}\r\n${DataScience.markdownHelpInstallingMissingDependencies()}`, + message, DataScience.jupyterInstall(), DataScience.selectDifferentJupyterInterpreter(), - Common.cancel() + DataScience.pythonInteractiveHelpLink() ); if (Cancellation.isCanceled(token)) { @@ -178,6 +182,12 @@ export class JupyterInterpreterDependencyService { return JupyterInterpreterDependencyResponse.selectAnotherInterpreter; } + case DataScience.pythonInteractiveHelpLink(): { + this.applicationShell.openUrl(HelpLinks.PythonInteractiveHelpLink); + sendTelemetryEvent(Telemetry.UserDidNotInstallJupyter); + return JupyterInterpreterDependencyResponse.cancel; + } + default: sendTelemetryEvent(Telemetry.UserDidNotInstallJupyter); return JupyterInterpreterDependencyResponse.cancel; @@ -261,15 +271,16 @@ export class JupyterInterpreterDependencyService { * @returns {Promise} * @memberof JupyterInterpreterConfigurationService */ - private async isKernelSpecAvailable(interpreter: PythonInterpreter, token?: CancellationToken): Promise { - const execService = await this.pythonExecFactory.createActivatedEnvironment({ interpreter, allowEnvironmentFetchExceptions: true, bypassCondaExecution: true }); - if (Cancellation.isCanceled(token)) { - return false; - } - return execService - .execModule('jupyter', ['kernelspec', '--version'], { throwOnStdErr: true }) + private async isKernelSpecAvailable(interpreter: PythonInterpreter, _token?: CancellationToken): Promise { + const command = this.commandFactory.createInterpreterCommand(JupyterCommands.KernelSpecCommand, 'jupyter', ['-m', 'jupyter', 'kernelspec'], interpreter, false); + return command + .exec(['--version'], { throwOnStdErr: true }) .then(() => true) - .catch(() => false); + .catch(e => { + traceError(`Kernel spec not found: `, e); + sendTelemetryEvent(Telemetry.KernelSpecNotFound); + return false; + }); } /** @@ -286,9 +297,10 @@ export class JupyterInterpreterDependencyService { */ private async checkKernelSpecAvailability(interpreter: PythonInterpreter, token?: CancellationToken): Promise { if (await this.isKernelSpecAvailable(interpreter)) { - sendTelemetryEvent(Telemetry.JupyterInstalledButNotKernelSpecModule); return JupyterInterpreterDependencyResponse.ok; } + // Indicate no kernel spec module. + sendTelemetryEvent(Telemetry.JupyterInstalledButNotKernelSpecModule); if (Cancellation.isCanceled(token)) { return JupyterInterpreterDependencyResponse.cancel; } diff --git a/src/client/datascience/jupyter/interpreter/jupyterInterpreterService.ts b/src/client/datascience/jupyter/interpreter/jupyterInterpreterService.ts index d503a70f3793..2a6fc4bfebfa 100644 --- a/src/client/datascience/jupyter/interpreter/jupyterInterpreterService.ts +++ b/src/client/datascience/jupyter/interpreter/jupyterInterpreterService.ts @@ -8,6 +8,7 @@ import { Event, EventEmitter } from 'vscode'; import { CancellationToken } from 'vscode-jsonrpc'; import { createPromiseFromCancellation } from '../../../common/cancellation'; import '../../../common/extensions'; +import { noop } from '../../../common/utils/misc'; import { IInterpreterService, PythonInterpreter } from '../../../interpreter/contracts'; import { sendTelemetryEvent } from '../../../telemetry'; import { Telemetry } from '../../constants'; @@ -19,8 +20,8 @@ import { JupyterInterpreterStateStore } from './jupyterInterpreterStateStore'; @injectable() export class JupyterInterpreterService { private _selectedInterpreter?: PythonInterpreter; - private _selectedInterpreterPath?: string; private _onDidChangeInterpreter = new EventEmitter(); + private getInitialInterpreterPromise: Promise | undefined; public get onDidChangeInterpreter(): Event { return this._onDidChangeInterpreter.event; } @@ -40,40 +41,30 @@ export class JupyterInterpreterService { * @memberof JupyterInterpreterService */ public async getSelectedInterpreter(token?: CancellationToken): Promise { - if (this._selectedInterpreter) { - return this._selectedInterpreter; - } + // Before we return _selected interpreter make sure that we have run our initial set interpreter once + // because _selectedInterpreter can be changed by other function and at other times, this promise + // is cached to only run once + await this.setInitialInterpreter(token); - const resolveToUndefinedWhenCancelled = createPromiseFromCancellation({ cancelAction: 'resolve', defaultValue: undefined, token }); - // For backwards compatiblity check if we have a cached interpreter (older version of extension). - // If that interpreter has everything we need then use that. - let interpreter = await Promise.race([this.getInterpreterFromChangeOfOlderVersionOfExtension(), resolveToUndefinedWhenCancelled]); - if (interpreter) { - return interpreter; - } + return this._selectedInterpreter; + } - const pythonPath = this._selectedInterpreterPath || this.interpreterSelectionState.selectedPythonPath; - if (!pythonPath) { - // Check if current interpreter has all of the required dependencies. - // If yes, then use that. - interpreter = await this.interpreterService.getActiveInterpreter(undefined); - if (!interpreter) { - return; - } - // Use this interpreter going forward. - if (await this.interpreterConfiguration.areDependenciesInstalled(interpreter)) { - this.setAsSelectedInterpreter(interpreter); - return interpreter; - } - return; + // To be run one initial time. Check our saved locations and then current interpreter to try to start off + // with a valid jupyter interpreter + public async setInitialInterpreter(token?: CancellationToken): Promise { + if (!this.getInitialInterpreterPromise) { + this.getInitialInterpreterPromise = this.getInitialInterpreterImpl(token).then(result => { + // Set ourselves as a valid interpreter if we found something + if (result) { + this.changeSelectedInterpreterProperty(result); + } + return result; + }); } - const interpreterDetails = await Promise.race([this.interpreterService.getInterpreterDetails(pythonPath, undefined), resolveToUndefinedWhenCancelled]); - if (interpreterDetails) { - this._selectedInterpreter = interpreterDetails; - } - return interpreterDetails; + return this.getInitialInterpreterPromise; } + /** * Selects and interpreter to run jupyter server. * Validates and configures the interpreter. @@ -94,7 +85,7 @@ export class JupyterInterpreterService { const result = await this.interpreterConfiguration.installMissingDependencies(interpreter, undefined, token); switch (result) { case JupyterInterpreterDependencyResponse.ok: { - this.setAsSelectedInterpreter(interpreter); + await this.setAsSelectedInterpreter(interpreter); return interpreter; } case JupyterInterpreterDependencyResponse.cancel: @@ -104,30 +95,91 @@ export class JupyterInterpreterService { return this.selectInterpreter(token); } } - private async getInterpreterFromChangeOfOlderVersionOfExtension(): Promise { + + // Check the location that we stored jupyter launch path in the old version + // if it's there, return it and clear the location + private getInterpreterFromChangeOfOlderVersionOfExtension(): string | undefined { const pythonPath = this.oldVersionCacheStateStore.getCachedInterpreterPath(); if (!pythonPath) { return; } + + // Clear the cache to not check again + this.oldVersionCacheStateStore.clearCache().ignoreErrors(); + return pythonPath; + } + + // Set the specified interpreter as our current selected interpreter + private async setAsSelectedInterpreter(interpreter: PythonInterpreter): Promise { + // Make sure that our initial set has happened before we allow a set so that + // calculation of the initial interpreter doesn't clobber the existing one + await this.setInitialInterpreter(); + this.changeSelectedInterpreterProperty(interpreter); + } + + private changeSelectedInterpreterProperty(interpreter: PythonInterpreter) { + this._selectedInterpreter = interpreter; + this._onDidChangeInterpreter.fire(interpreter); + this.interpreterSelectionState.updateSelectedPythonPath(interpreter.path); + sendTelemetryEvent(Telemetry.SelectJupyterInterpreter, undefined, { result: 'selected' }); + } + + // For a given python path check if it can run jupyter for us + // if so, return the interpreter + private async validateInterpreterPath(pythonPath: string, token?: CancellationToken): Promise { try { - const interpreter = await this.interpreterService.getInterpreterDetails(pythonPath, undefined); + const resolveToUndefinedWhenCancelled = createPromiseFromCancellation({ + cancelAction: 'resolve', + defaultValue: undefined, + token + }); + + // First see if we can get interpreter details + const interpreter = await Promise.race([this.interpreterService.getInterpreterDetails(pythonPath, undefined), resolveToUndefinedWhenCancelled]); + if (interpreter) { + // Then check that dependencies are installed + if (await this.interpreterConfiguration.areDependenciesInstalled(interpreter, token)) { + return interpreter; + } + } + } catch (_err) { + // For any errors we are ok with just returning undefined for an invalid interpreter + noop(); + } + return undefined; + } + + private async getInitialInterpreterImpl(token?: CancellationToken): Promise { + let interpreter: PythonInterpreter | undefined; + + // Check the old version location first, we will clear it if we find it here + const oldVersionPythonPath = this.getInterpreterFromChangeOfOlderVersionOfExtension(); + if (oldVersionPythonPath) { + interpreter = await this.validateInterpreterPath(oldVersionPythonPath, token); + } + + // Next check the saved global path + if (!interpreter && this.interpreterSelectionState.selectedPythonPath) { + interpreter = await this.validateInterpreterPath(this.interpreterSelectionState.selectedPythonPath, token); + + // If we had a global path, but it's not valid, trash it if (!interpreter) { - return; + this.interpreterSelectionState.updateSelectedPythonPath(undefined); } - if (await this.interpreterConfiguration.areDependenciesInstalled(interpreter)) { - this.setAsSelectedInterpreter(interpreter); - return interpreter; + } + + // Nothing saved found, so check our current interpreter + if (!interpreter) { + const currentInterpreter = await this.interpreterService.getActiveInterpreter(undefined); + + if (currentInterpreter) { + // Ask and give a chance to install dependencies in current interpreter + if (await this.interpreterConfiguration.areDependenciesInstalled(currentInterpreter, token)) { + interpreter = currentInterpreter; + } } - // If dependencies are not installed, then ignore it. lets continue with the current logic. - } finally { - // Don't perform this check again, just clear the cache. - this.oldVersionCacheStateStore.clearCache().ignoreErrors(); } - } - private setAsSelectedInterpreter(interpreter: PythonInterpreter): void { - this._selectedInterpreter = interpreter; - this._onDidChangeInterpreter.fire(interpreter); - this.interpreterSelectionState.updateSelectedPythonPath((this._selectedInterpreterPath = interpreter.path)); - sendTelemetryEvent(Telemetry.SelectJupyterInterpreter, undefined, { result: 'selected' }); + + return interpreter; } } diff --git a/src/client/datascience/jupyter/interpreter/jupyterInterpreterStateStore.ts b/src/client/datascience/jupyter/interpreter/jupyterInterpreterStateStore.ts index d4e3585b2c5c..3fecb01848db 100644 --- a/src/client/datascience/jupyter/interpreter/jupyterInterpreterStateStore.ts +++ b/src/client/datascience/jupyter/interpreter/jupyterInterpreterStateStore.ts @@ -11,11 +11,11 @@ import { noop } from '../../../common/utils/misc'; const key = 'INTERPRETER_PATH_SELECTED_FOR_JUPYTER_SERVER'; const keySelected = 'INTERPRETER_PATH_WAS_SELECTED_FOR_JUPYTER_SERVER'; /** - * Keeps track of whether the user ever selected an interpreter to be used as the gloabl jupyter interpreter. + * Keeps track of whether the user ever selected an interpreter to be used as the global jupyter interpreter. * Keeps track of the interpreter path of the interpreter used as the global jupyter interpreter. * * @export - * @class JupyterInterpreterFinderEverSet + * @class JupyterInterpreterStateStore */ @injectable() export class JupyterInterpreterStateStore { @@ -27,7 +27,6 @@ export class JupyterInterpreterStateStore { * * @readonly * @type {Promise} - * @memberof JupyterInterpreterFinderEverSet */ public get interpreterSetAtleastOnce(): boolean { return !!this.selectedPythonPath || this.memento.get(keySelected, false); @@ -35,7 +34,7 @@ export class JupyterInterpreterStateStore { public get selectedPythonPath(): string | undefined { return this._interpreterPath || this.memento.get(key, undefined); } - public updateSelectedPythonPath(value: string) { + public updateSelectedPythonPath(value: string | undefined) { this._interpreterPath = value; this.memento.update(key, value).then(noop, noop); this.memento.update(keySelected, true).then(noop, noop); diff --git a/src/client/datascience/jupyter/interpreter/jupyterInterpreterSubCommandExecutionService.ts b/src/client/datascience/jupyter/interpreter/jupyterInterpreterSubCommandExecutionService.ts index 13c91dc2670c..6596e5189dc8 100644 --- a/src/client/datascience/jupyter/interpreter/jupyterInterpreterSubCommandExecutionService.ts +++ b/src/client/datascience/jupyter/interpreter/jupyterInterpreterSubCommandExecutionService.ts @@ -15,7 +15,8 @@ import { DataScience } from '../../../common/utils/localize'; import { noop } from '../../../common/utils/misc'; import { EXTENSION_ROOT_DIR } from '../../../constants'; import { IInterpreterService, PythonInterpreter } from '../../../interpreter/contracts'; -import { JUPYTER_OUTPUT_CHANNEL, PythonDaemonModule } from '../../constants'; +import { sendTelemetryEvent } from '../../../telemetry'; +import { JUPYTER_OUTPUT_CHANNEL, PythonDaemonModule, Telemetry } from '../../constants'; import { IJupyterInterpreterDependencyManager, IJupyterSubCommandExecutionService } from '../../types'; import { JupyterServerInfo } from '../jupyterConnection'; import { JupyterInstallError } from '../jupyterInstallError'; @@ -85,7 +86,7 @@ export class JupyterInterpreterSubCommandExecutionService implements IJupyterSub return DataScience.jupyterKernelSpecModuleNotFound(); } - return getMessageForLibrariesNotInstalled(productsNotInstalled); + return getMessageForLibrariesNotInstalled(productsNotInstalled, interpreter.displayName); } public async getSelectedInterpreter(token?: CancellationToken): Promise { return this.jupyterInterpreter.getSelectedInterpreter(token); @@ -153,6 +154,7 @@ export class JupyterInterpreterSubCommandExecutionService implements IJupyterSub .execModule('jupyter', ['kernelspec', 'list', '--json'], spawnOptions) .then(output => output.stdout) .catch(daemonEx => { + sendTelemetryEvent(Telemetry.KernelSpecNotFound); traceError('Failed to list kernels from daemon', daemonEx); return ''; }); diff --git a/src/client/datascience/jupyter/jupyterExecution.ts b/src/client/datascience/jupyter/jupyterExecution.ts index 5a7ad184f48a..3fbe3fdf1cd3 100644 --- a/src/client/datascience/jupyter/jupyterExecution.ts +++ b/src/client/datascience/jupyter/jupyterExecution.ts @@ -192,7 +192,7 @@ export class JupyterExecutionBase implements IJupyterExecution { if (selection === selectKernel) { const sessionManagerFactory = this.serviceContainer.get(IJupyterSessionManagerFactory); const sessionManager = await sessionManagerFactory.create(connection); - const kernelInterpreter = await this.kernelSelector.selectLocalKernel(sessionManager, cancelToken, launchInfo.kernelSpec); + const kernelInterpreter = await this.kernelSelector.selectLocalKernel(new StopWatch(), sessionManager, cancelToken, launchInfo.kernelSpec); if (Object.keys(kernelInterpreter).length > 0) { launchInfo.interpreter = kernelInterpreter.interpreter; launchInfo.kernelSpec = kernelInterpreter.kernelSpec || kernelInterpreter.kernelModel; diff --git a/src/client/datascience/jupyter/jupyterVariables.ts b/src/client/datascience/jupyter/jupyterVariables.ts index cff731c78e20..b4b86d7a968e 100644 --- a/src/client/datascience/jupyter/jupyterVariables.ts +++ b/src/client/datascience/jupyter/jupyterVariables.ts @@ -30,7 +30,7 @@ const DocStringRegex = /.*?\[.*?;31mDocstring:.*?\[0m\s+(.*)/; const CountRegex = /.*?\[.*?;31mLength:.*?\[0m\s+(.*)/; const ShapeRegex = /^\s+\[(\d+) rows x (\d+) columns\]/m; -const DataViewableTypes: Set = new Set(['DataFrame', 'list', 'dict', 'np.array', 'Series']); +const DataViewableTypes: Set = new Set(['DataFrame', 'list', 'dict', 'ndarray', 'Series']); interface INotebookState { currentExecutionCount: number; @@ -98,8 +98,9 @@ export class JupyterVariables implements IJupyterVariables { return defaultValue; } - // Prep our targetVariable to send over - const variableString = JSON.stringify(targetVariable).replace(/\\n/g, '\\\\n'); + // Prep our targetVariable to send over. Remove the 'value' as it's not necessary for getting df info and can have invalid data in it + const pruned = { ...targetVariable, value: '' }; + const variableString = JSON.stringify(pruned); // Setup a regex const regexPattern = extraReplacements.length === 0 ? '_VSCode_JupyterTestValue' : ['_VSCode_JupyterTestValue', ...extraReplacements.map(v => v.key)].join('|'); diff --git a/src/client/datascience/jupyter/kernels/kernelSelector.ts b/src/client/datascience/jupyter/kernels/kernelSelector.ts index d91b9427b48e..43457168c804 100644 --- a/src/client/datascience/jupyter/kernels/kernelSelector.ts +++ b/src/client/datascience/jupyter/kernels/kernelSelector.ts @@ -15,7 +15,7 @@ import { noop } from '../../../common/utils/misc'; import { StopWatch } from '../../../common/utils/stopWatch'; import { IInterpreterService, PythonInterpreter } from '../../../interpreter/contracts'; import { IEventNamePropertyMapping, sendTelemetryEvent } from '../../../telemetry'; -import { Telemetry } from '../../constants'; +import { KnownNotebookLanguages, Telemetry } from '../../constants'; import { reportAction } from '../../progress/decorator'; import { ReportableAction } from '../../progress/types'; import { IJupyterKernelSpec, IJupyterSessionManager } from '../../types'; @@ -90,13 +90,14 @@ export class KernelSelector { * @memberof KernelSelector */ public async selectRemoteKernel( + stopWatch: StopWatch, session: IJupyterSessionManager, cancelToken?: CancellationToken, currentKernel?: IJupyterKernelSpec | LiveKernelModel ): Promise { let suggestions = await this.selectionProvider.getKernelSelectionsForRemoteSession(session, cancelToken); suggestions = suggestions.filter(item => !this.kernelIdsToHide.has(item.selection.kernelModel?.id || '')); - return this.selectKernel(suggestions, session, cancelToken, currentKernel); + return this.selectKernel(stopWatch, Telemetry.SelectRemoteJupyterKernel, suggestions, session, cancelToken, currentKernel); } /** * Select a kernel from a local session. @@ -107,13 +108,14 @@ export class KernelSelector { * @memberof KernelSelector */ public async selectLocalKernel( + stopWatch: StopWatch, session?: IJupyterSessionManager, cancelToken?: CancellationToken, currentKernel?: IJupyterKernelSpec | LiveKernelModel ): Promise { let suggestions = await this.selectionProvider.getKernelSelectionsForLocalSession(session, cancelToken); suggestions = suggestions.filter(item => !this.kernelIdsToHide.has(item.selection.kernelModel?.id || '')); - return this.selectKernel(suggestions, session, cancelToken, currentKernel); + return this.selectKernel(stopWatch, Telemetry.SelectLocalJupyterKernel, suggestions, session, cancelToken, currentKernel); } /** * Gets a kernel that needs to be used with a local session. @@ -151,7 +153,7 @@ export class KernelSelector { selection = await this.useInterpreterAsKernel(activeInterpreter, notebookMetadata.kernelspec.display_name, sessionManager, disableUI, cancelToken); } else { telemetryProps.promptedToSelect = true; - selection = await this.selectLocalKernel(sessionManager, cancelToken); + selection = await this.selectLocalKernel(stopWatch, sessionManager, cancelToken); } } } else { @@ -239,12 +241,15 @@ export class KernelSelector { }; } private async selectKernel( + stopWatch: StopWatch, + telemetryEvent: Telemetry, suggestions: IKernelSpecQuickPickItem[], session?: IJupyterSessionManager, cancelToken?: CancellationToken, currentKernel?: IJupyterKernelSpec | LiveKernelModel ) { const placeHolder = localize.DataScience.selectKernel() + (currentKernel ? ` (current: ${currentKernel.display_name || currentKernel.name})` : ''); + sendTelemetryEvent(telemetryEvent, stopWatch.elapsedTime); const selection = await this.applicationShell.showQuickPick(suggestions, { placeHolder }, cancelToken); if (!selection?.selection) { return {}; @@ -254,12 +259,16 @@ export class KernelSelector { sendTelemetryEvent(Telemetry.SwitchToInterpreterAsKernel); return this.useInterpreterAsKernel(selection.selection.interpreter, undefined, session, false, cancelToken); } else if (selection.selection.kernelModel) { - sendTelemetryEvent(Telemetry.SwitchToExistingKernel); + sendTelemetryEvent(Telemetry.SwitchToExistingKernel, undefined, { + language: this.computeLanguage(selection.selection.kernelModel.language) + }); // tslint:disable-next-line: no-any const interpreter = selection.selection.kernelModel ? await this.kernelService.findMatchingInterpreter(selection.selection.kernelModel, cancelToken) : undefined; return { kernelSpec: selection.selection.kernelSpec, interpreter, kernelModel: selection.selection.kernelModel }; } else if (selection.selection.kernelSpec) { - sendTelemetryEvent(Telemetry.SwitchToExistingKernel); + sendTelemetryEvent(Telemetry.SwitchToExistingKernel, undefined, { + language: this.computeLanguage(selection.selection.kernelSpec.language) + }); const interpreter = selection.selection.kernelSpec ? await this.kernelService.findMatchingInterpreter(selection.selection.kernelSpec, cancelToken) : undefined; return { kernelSpec: selection.selection.kernelSpec, interpreter }; } else { @@ -308,7 +317,12 @@ export class KernelSelector { } // Try an install this interpreter as a kernel. - kernelSpec = await this.kernelService.registerKernel(interpreter, disableUI, cancelToken); + try { + kernelSpec = await this.kernelService.registerKernel(interpreter, disableUI, cancelToken); + } catch (e) { + sendTelemetryEvent(Telemetry.KernelRegisterFailed); + throw e; + } // If we have a display name of a kernel that could not be found, // then notify user that we're using current interpreter instead. @@ -324,4 +338,11 @@ export class KernelSelector { return { kernelSpec, interpreter }; } + + private computeLanguage(language: string | undefined): string { + if (language && KnownNotebookLanguages.includes(language.toLowerCase())) { + return language; + } + return 'unknown'; + } } diff --git a/src/client/datascience/jupyter/kernels/kernelService.ts b/src/client/datascience/jupyter/kernels/kernelService.ts index a56e7f8fdf50..aee36b7050f9 100644 --- a/src/client/datascience/jupyter/kernels/kernelService.ts +++ b/src/client/datascience/jupyter/kernels/kernelService.ts @@ -354,7 +354,17 @@ export class KernelService { return []; } const specs: IJupyterKernelSpec[] = await enumerator; - return specs.filter(item => !!item); + const result = specs.filter(item => !!item); + + // Send telemetry on this enumeration. + const anyPython = result.find(k => k.language === 'python') !== undefined; + sendTelemetryEvent(Telemetry.KernelEnumeration, undefined, { + count: result.length, + isPython: anyPython, + source: sessionManager ? 'connection' : 'cli' + }); + + return result; } /** * Not all characters are allowed in a kernel name. diff --git a/src/client/datascience/jupyter/kernels/kernelSwitcher.ts b/src/client/datascience/jupyter/kernels/kernelSwitcher.ts index 177d05a49323..7f2527e26f98 100644 --- a/src/client/datascience/jupyter/kernels/kernelSwitcher.ts +++ b/src/client/datascience/jupyter/kernels/kernelSwitcher.ts @@ -8,8 +8,8 @@ import { ProgressLocation, ProgressOptions } from 'vscode'; import { IApplicationShell } from '../../../common/application/types'; import { IConfigurationService } from '../../../common/types'; import { Common, DataScience } from '../../../common/utils/localize'; -import { captureTelemetry } from '../../../telemetry'; -import { Commands, Settings, Telemetry } from '../../constants'; +import { StopWatch } from '../../../common/utils/stopWatch'; +import { Commands, Settings } from '../../constants'; import { IConnection, IJupyterKernelSpec, IJupyterSessionManagerFactory, INotebook } from '../../types'; import { JupyterSessionStartError } from '../jupyterSession'; import { KernelSelector, KernelSpecInterpreter } from './kernelSelector'; @@ -49,15 +49,14 @@ export class KernelSwitcher { return kernel; } - @captureTelemetry(Telemetry.SelectLocalJupyterKernel) private async selectLocalJupyterKernel(currentKernel?: IJupyterKernelSpec | LiveKernelModel): Promise { - return this.kernelSelector.selectLocalKernel(undefined, undefined, currentKernel); + return this.kernelSelector.selectLocalKernel(new StopWatch(), undefined, undefined, currentKernel); } - @captureTelemetry(Telemetry.SelectRemoteJupyuterKernel) private async selectRemoteJupyterKernel(connInfo: IConnection, currentKernel?: IJupyterKernelSpec | LiveKernelModel): Promise { + const stopWatch = new StopWatch(); const session = await this.jupyterSessionManagerFactory.create(connInfo); - return this.kernelSelector.selectRemoteKernel(session, undefined, currentKernel); + return this.kernelSelector.selectRemoteKernel(stopWatch, session, undefined, currentKernel); } private async switchKernelWithRetry(notebook: INotebook, kernel: KernelSpecInterpreter): Promise { const settings = this.configService.getSettings(); diff --git a/src/client/telemetry/index.ts b/src/client/telemetry/index.ts index fbe9fca4b98b..4d8ae0be241c 100644 --- a/src/client/telemetry/index.ts +++ b/src/client/telemetry/index.ts @@ -1441,7 +1441,7 @@ export interface IEventNamePropertyMapping { [Telemetry.RegisterAndUseInterpreterAsKernel]: never | undefined; [Telemetry.UseInterpreterAsKernel]: never | undefined; [Telemetry.UseExistingKernel]: never | undefined; - [Telemetry.SwitchToExistingKernel]: never | undefined; + [Telemetry.SwitchToExistingKernel]: { language: string }; [Telemetry.SwitchToInterpreterAsKernel]: never | undefined; [Telemetry.ConvertToPythonFile]: never | undefined; [Telemetry.CopySourceCode]: never | undefined; @@ -1510,7 +1510,7 @@ export interface IEventNamePropertyMapping { [Telemetry.SelfCertsMessageEnabled]: never | undefined; [Telemetry.SelectJupyterURI]: never | undefined; [Telemetry.SelectLocalJupyterKernel]: never | undefined; - [Telemetry.SelectRemoteJupyuterKernel]: never | undefined; + [Telemetry.SelectRemoteJupyterKernel]: never | undefined; [Telemetry.SessionIdleTimeout]: never | undefined; [Telemetry.JupyterNotInstalledErrorShown]: never | undefined; [Telemetry.JupyterCommandSearch]: { where: 'activeInterpreter' | 'otherInterpreter' | 'path' | 'nowhere'; command: JupyterCommands }; @@ -1722,4 +1722,75 @@ export interface IEventNamePropertyMapping { * @memberof IEventNamePropertyMapping */ [Telemetry.CompletionTimeFromJupyter]: undefined | never; + /** + * Telemetry event sent to indicate the language used in a notebook + * + * @type { language: string } + * @memberof IEventNamePropertyMapping + */ + [Telemetry.NotebookLanguage]: { + /** + * Language found in the notebook if a known language. Otherwise 'unknown' + */ + language: string; + }; + /** + * Telemetry event sent to indicate 'jupyter kernelspec' is not possible. + * + * @type {(undefined | never)} + * @memberof IEventNamePropertyMapping + */ + [Telemetry.KernelSpecNotFound]: undefined | never; + /** + * Telemetry event sent to indicate registering a kernel with jupyter failed. + * + * @type {(undefined | never)} + * @memberof IEventNamePropertyMapping + */ + [Telemetry.KernelRegisterFailed]: undefined | never; + /** + * Telemetry event sent to every time a kernel enumeration is done + * + * @type {...} + * @memberof IEventNamePropertyMapping + */ + [Telemetry.KernelEnumeration]: { + /** + * Count of the number of kernels found + */ + count: number; + /** + * Boolean indicating if any are python or not + */ + isPython: boolean; + /** + * Indicates how the enumeration was acquired. + */ + source: 'cli' | 'connection'; + }; + /** + * Telemetry event sent if there's an error installing a jupyter required dependency + * + * @type { product: string } + * @memberof IEventNamePropertyMapping + */ + [Telemetry.JupyterInstallFailed]: { + /** + * Product being installed (jupyter or ipykernel or other) + */ + product: string; + }; + /** + * Telemetry event sent when installing a jupyter dependency + * + * @type {product: string} + * @memberof IEventNamePropertyMapping + */ + [Telemetry.UserInstalledModule]: { product: string }; + /** + * Telemetry event sent to when user customizes the jupyter command line + * @type {(undefined | never)} + * @memberof IEventNamePropertyMapping + */ + [Telemetry.JupyterCommandLineNonDefault]: undefined | never; } diff --git a/src/datascience-ui/history-react/interactivePanel.tsx b/src/datascience-ui/history-react/interactivePanel.tsx index 6c7aa04b3f5f..3eccd238d084 100644 --- a/src/datascience-ui/history-react/interactivePanel.tsx +++ b/src/datascience-ui/history-react/interactivePanel.tsx @@ -3,6 +3,7 @@ 'use strict'; import * as React from 'react'; import { connect } from 'react-redux'; +import { noop } from '../../client/common/utils/misc'; import { Identifiers } from '../../client/datascience/constants'; import { ContentPanel, IContentPanelProps } from '../interactive-common/contentPanel'; import { handleLinkClick } from '../interactive-common/handlers'; @@ -75,13 +76,20 @@ export class InteractivePanel extends React.Component {

{this.renderContentPanel(this.props.baseTheme)}
-
); } + // Make the entire footer focus our input, instead of having to click directly on the monaco editor + private footerPanelClick = (_event: React.MouseEvent) => { + // This does nothing in release bits. Not necessary for point release. + noop(); + }; + + // tslint:disable-next-line: max-func-body-length private renderToolbarPanel() { const variableExplorerTooltip = this.props.variableState.visible ? getLocString('DataScience.collapseVariableExplorerTooltip', 'Hide variables active in jupyter kernel') diff --git a/src/datascience-ui/interactive-common/redux/reducers/variables.ts b/src/datascience-ui/interactive-common/redux/reducers/variables.ts index caeb3e76006d..d4691a93ccb9 100644 --- a/src/datascience-ui/interactive-common/redux/reducers/variables.ts +++ b/src/datascience-ui/interactive-common/redux/reducers/variables.ts @@ -106,16 +106,21 @@ function handleResponse(arg: VariableReducerArg): IVa } function handleRestarted(arg: VariableReducerArg): IVariableState { - // If the variables are visible, refresh them - if (arg.prevState.visible) { - const result = handleRequest({ ...arg, payload: { executionCount: 0, sortColumn: 'name', sortAscending: true, startIndex: 0, pageSize: arg.prevState.pageSize } }); - return { - ...result, - currentExecutionCount: 0, - variables: [] - }; - } - return arg.prevState; + const result = handleRequest({ + ...arg, + payload: { + executionCount: 0, + sortColumn: 'name', + sortAscending: true, + startIndex: 0, + pageSize: arg.prevState.pageSize + } + }); + return { + ...result, + currentExecutionCount: 0, + variables: [] + }; } function handleFinishCell(arg: VariableReducerArg): IVariableState { diff --git a/src/test/datascience/activation.unit.test.ts b/src/test/datascience/activation.unit.test.ts index 2758ca891e0e..2e8f57724588 100644 --- a/src/test/datascience/activation.unit.test.ts +++ b/src/test/datascience/activation.unit.test.ts @@ -47,6 +47,7 @@ suite('Data Science - Activation', () => { activator = new Activation(instance(notebookProvider), instance(jupyterInterpreterService), instance(executionFactory), [], instance(contextService)); when(jupyterInterpreterService.getSelectedInterpreter()).thenResolve(interpreter); when(jupyterInterpreterService.getSelectedInterpreter(anything())).thenResolve(interpreter); + when(jupyterInterpreterService.setInitialInterpreter()).thenResolve(interpreter); await activator.activate(); }); teardown(() => fakeTimer.uninstall()); diff --git a/src/test/datascience/jupyter/interpreter/jupyterInterpreterDependencyService.unit.test.ts b/src/test/datascience/jupyter/interpreter/jupyterInterpreterDependencyService.unit.test.ts index a230f6607b1e..386451cd3e86 100644 --- a/src/test/datascience/jupyter/interpreter/jupyterInterpreterDependencyService.unit.test.ts +++ b/src/test/datascience/jupyter/interpreter/jupyterInterpreterDependencyService.unit.test.ts @@ -4,25 +4,26 @@ 'use strict'; import { assert } from 'chai'; -import { anything, deepEqual, instance, mock, verify, when } from 'ts-mockito'; +import { anything, instance, mock, verify, when } from 'ts-mockito'; import { ApplicationShell } from '../../../../client/common/application/applicationShell'; import { IApplicationShell } from '../../../../client/common/application/types'; import { ProductInstaller } from '../../../../client/common/installer/productInstaller'; -import { PythonExecutionFactory } from '../../../../client/common/process/pythonExecutionFactory'; -import { PythonExecutionService } from '../../../../client/common/process/pythonProcess'; -import { IPythonExecutionService } from '../../../../client/common/process/types'; import { IInstaller, InstallerResponse, Product } from '../../../../client/common/types'; -import { Common, DataScience } from '../../../../client/common/utils/localize'; +import { DataScience } from '../../../../client/common/utils/localize'; import { Architecture } from '../../../../client/common/utils/platform'; +import { InterpreterJupyterKernelSpecCommand, JupyterCommandFactory } from '../../../../client/datascience/jupyter/interpreter/jupyterCommand'; import { JupyterInterpreterDependencyResponse, JupyterInterpreterDependencyService } from '../../../../client/datascience/jupyter/interpreter/jupyterInterpreterDependencyService'; +import { IJupyterCommand, IJupyterCommandFactory } from '../../../../client/datascience/types'; import { InterpreterType, PythonInterpreter } from '../../../../client/interpreter/contracts'; -// tslint:disable-next-line: max-func-body-length +// tslint:disable: max-func-body-length no-any + suite('Data Science - Jupyter Interpreter Configuration', () => { let configuration: JupyterInterpreterDependencyService; let appShell: IApplicationShell; let installer: IInstaller; - let pythonExecService: IPythonExecutionService; + let commandFactory: IJupyterCommandFactory; + let command: IJupyterCommand; const pythonInterpreter: PythonInterpreter = { path: '', architecture: Architecture.Unknown, @@ -33,14 +34,14 @@ suite('Data Science - Jupyter Interpreter Configuration', () => { setup(() => { appShell = mock(ApplicationShell); installer = mock(ProductInstaller); - pythonExecService = mock(PythonExecutionService); - const pythonExecFactory = mock(PythonExecutionFactory); - when(pythonExecFactory.createActivatedEnvironment(anything())).thenResolve(instance(pythonExecService)); - // tslint:disable-next-line: no-any - instance(pythonExecService as any).then = undefined; - when(pythonExecService.execModule('jupyter', deepEqual(['kernelspec', '--version']), anything())).thenResolve({ stdout: '' }); + commandFactory = mock(JupyterCommandFactory); + command = mock(InterpreterJupyterKernelSpecCommand); + instance(commandFactory as any).then = undefined; + instance(command as any).then = undefined; + when(commandFactory.createInterpreterCommand(anything(), anything(), anything(), anything(), anything())).thenReturn(instance(command)); + when(command.exec(anything(), anything())).thenResolve({ stdout: '' }); - configuration = new JupyterInterpreterDependencyService(instance(appShell), instance(installer), instance(pythonExecFactory)); + configuration = new JupyterInterpreterDependencyService(instance(appShell), instance(installer), instance(commandFactory)); }); test('Return ok if all dependencies are installed', async () => { when(installer.isInstalled(Product.jupyter, pythonInterpreter)).thenResolve(true); @@ -57,7 +58,9 @@ suite('Data Science - Jupyter Interpreter Configuration', () => { const response = await configuration.installMissingDependencies(pythonInterpreter); - verify(appShell.showErrorMessage(anything(), DataScience.jupyterInstall(), DataScience.selectDifferentJupyterInterpreter(), Common.cancel())).once(); + verify( + appShell.showErrorMessage(anything(), DataScience.jupyterInstall(), DataScience.selectDifferentJupyterInterpreter(), DataScience.pythonInteractiveHelpLink()) + ).once(); assert.equal(response, JupyterInterpreterDependencyResponse.cancel); } test('Prompt to install if Jupyter is not installed', async () => testPromptIfModuleNotInstalled(false, true)); @@ -70,7 +73,7 @@ suite('Data Science - Jupyter Interpreter Configuration', () => { // tslint:disable-next-line: no-any DataScience.jupyterInstall() as any ); - when(pythonExecService.execModule('jupyter', deepEqual(['kernelspec', '--version']), anything())).thenReject(new Error('Not found')); + when(command.exec(anything(), anything())).thenReject(new Error('Not found')); when(installer.install(anything(), anything(), anything())).thenResolve(InstallerResponse.Installed); const response = await configuration.installMissingDependencies(pythonInterpreter); diff --git a/src/test/datascience/jupyter/interpreter/jupyterInterpreterService.unit.test.ts b/src/test/datascience/jupyter/interpreter/jupyterInterpreterService.unit.test.ts index 647a60a34267..e6a208c69980 100644 --- a/src/test/datascience/jupyter/interpreter/jupyterInterpreterService.unit.test.ts +++ b/src/test/datascience/jupyter/interpreter/jupyterInterpreterService.unit.test.ts @@ -4,7 +4,7 @@ 'use strict'; import { assert } from 'chai'; -import { anything, instance, mock, verify, when } from 'ts-mockito'; +import { anyString, anything, instance, mock, verify, when } from 'ts-mockito'; import { Memento } from 'vscode'; import { Architecture } from '../../../../client/common/utils/platform'; import { JupyterInterpreterDependencyResponse, JupyterInterpreterDependencyService } from '../../../../client/datascience/jupyter/interpreter/jupyterInterpreterDependencyService'; @@ -16,6 +16,7 @@ import { IInterpreterService, InterpreterType, PythonInterpreter } from '../../. import { InterpreterService } from '../../../../client/interpreter/interpreterService'; import { MockMemento } from '../../../mocks/mementos'; +// tslint:disable-next-line: max-func-body-length suite('Data Science - Jupyter Interpreter Service', () => { let jupyterInterpreterService: JupyterInterpreterService; let interpreterSelector: JupyterInterpreterSelector; @@ -107,4 +108,32 @@ suite('Data Science - Jupyter Interpreter Service', () => { assert.equal(selectedInterpreter, secondPythonInterpreter); }); + test('setInitialInterpreter if older version is set should use and clear', async () => { + when(oldVersionCacheStateStore.getCachedInterpreterPath()).thenReturn(pythonInterpreter.path); + when(oldVersionCacheStateStore.clearCache()).thenResolve(); + when(interpreterConfiguration.areDependenciesInstalled(pythonInterpreter, anything())).thenResolve(true); + const initialInterpreter = await jupyterInterpreterService.setInitialInterpreter(undefined); + verify(oldVersionCacheStateStore.clearCache()).once(); + assert.equal(initialInterpreter, pythonInterpreter); + }); + test('setInitialInterpreter use saved interpreter if valid', async () => { + when(oldVersionCacheStateStore.getCachedInterpreterPath()).thenReturn(undefined); + when(interpreterSelectionState.selectedPythonPath).thenReturn(pythonInterpreter.path); + when(interpreterConfiguration.areDependenciesInstalled(pythonInterpreter, anything())).thenResolve(true); + const initialInterpreter = await jupyterInterpreterService.setInitialInterpreter(undefined); + assert.equal(initialInterpreter, pythonInterpreter); + }); + test('setInitialInterpreter saved interpreter invalid, clear it and use active interpreter', async () => { + when(oldVersionCacheStateStore.getCachedInterpreterPath()).thenReturn(undefined); + when(interpreterSelectionState.selectedPythonPath).thenReturn(secondPythonInterpreter.path); + when(interpreterConfiguration.areDependenciesInstalled(secondPythonInterpreter, anything())).thenResolve(false); + when(interpreterService.getActiveInterpreter(anything())).thenResolve(pythonInterpreter); + when(interpreterConfiguration.areDependenciesInstalled(pythonInterpreter, anything())).thenResolve(true); + const initialInterpreter = await jupyterInterpreterService.setInitialInterpreter(undefined); + assert.equal(initialInterpreter, pythonInterpreter); + // Make sure we set our saved interpreter to the new active interpreter + // it should have been cleared to undefined, then set to a new value + verify(interpreterSelectionState.updateSelectedPythonPath(undefined)).once(); + verify(interpreterSelectionState.updateSelectedPythonPath(anyString())).once(); + }); }); diff --git a/src/test/datascience/jupyter/interpreter/jupyterInterpreterSubCommandExecutionService.unit.test.ts b/src/test/datascience/jupyter/interpreter/jupyterInterpreterSubCommandExecutionService.unit.test.ts index f462f43ab9dd..f7d80baaa9d4 100644 --- a/src/test/datascience/jupyter/interpreter/jupyterInterpreterSubCommandExecutionService.unit.test.ts +++ b/src/test/datascience/jupyter/interpreter/jupyterInterpreterSubCommandExecutionService.unit.test.ts @@ -107,13 +107,19 @@ suite('Data Science - Jupyter InterpreterSubCommandExecutionService', () => { assert.equal(reason, DataScience.selectJupyterInterpreter()); }); test('Jupyter cannot be started because jupyter is not installed', async () => { - const expectedReason = DataScience.libraryRequiredToLaunchJupyterNotInstalled().format(ProductNames.get(Product.jupyter)!); + const expectedReason = DataScience.libraryRequiredToLaunchJupyterNotInstalledInterpreter().format( + activePythonInterpreter.displayName!, + ProductNames.get(Product.jupyter)! + ); when(jupyterDependencyService.getDependenciesNotInstalled(activePythonInterpreter, undefined)).thenResolve([Product.jupyter]); const reason = await jupyterInterpreterExecutionService.getReasonForJupyterNotebookNotBeingSupported(undefined); assert.equal(reason, expectedReason); }); test('Jupyter cannot be started because notebook is not installed', async () => { - const expectedReason = DataScience.libraryRequiredToLaunchJupyterNotInstalled().format(ProductNames.get(Product.notebook)!); + const expectedReason = DataScience.libraryRequiredToLaunchJupyterNotInstalledInterpreter().format( + activePythonInterpreter.displayName!, + ProductNames.get(Product.notebook)! + ); when(jupyterDependencyService.getDependenciesNotInstalled(activePythonInterpreter, undefined)).thenResolve([Product.notebook]); const reason = await jupyterInterpreterExecutionService.getReasonForJupyterNotebookNotBeingSupported(undefined); assert.equal(reason, expectedReason); @@ -122,31 +128,41 @@ suite('Data Science - Jupyter InterpreterSubCommandExecutionService', () => { const promise = jupyterInterpreterExecutionService.startNotebook([], {}); when(jupyterDependencyService.getDependenciesNotInstalled(activePythonInterpreter, undefined)).thenResolve([Product.notebook]); - await expect(promise).to.eventually.be.rejectedWith(DataScience.libraryRequiredToLaunchJupyterNotInstalled().format(ProductNames.get(Product.notebook)!)); + await expect(promise).to.eventually.be.rejectedWith( + DataScience.libraryRequiredToLaunchJupyterNotInstalledInterpreter().format(activePythonInterpreter.displayName!, ProductNames.get(Product.notebook)!) + ); }); test('Cannot launch notebook file in jupyter notebook', async () => { const promise = jupyterInterpreterExecutionService.openNotebook('some.ipynb'); when(jupyterDependencyService.getDependenciesNotInstalled(activePythonInterpreter, undefined)).thenResolve([Product.notebook]); - await expect(promise).to.eventually.be.rejectedWith(DataScience.libraryRequiredToLaunchJupyterNotInstalled().format(ProductNames.get(Product.notebook)!)); + await expect(promise).to.eventually.be.rejectedWith( + DataScience.libraryRequiredToLaunchJupyterNotInstalledInterpreter().format(activePythonInterpreter.displayName!, ProductNames.get(Product.notebook)!) + ); }); test('Cannot export notebook to python', async () => { const promise = jupyterInterpreterExecutionService.exportNotebookToPython('somefile.ipynb'); when(jupyterDependencyService.getDependenciesNotInstalled(activePythonInterpreter, undefined)).thenResolve([Product.notebook]); - await expect(promise).to.eventually.be.rejectedWith(DataScience.libraryRequiredToLaunchJupyterNotInstalled().format(ProductNames.get(Product.notebook)!)); + await expect(promise).to.eventually.be.rejectedWith( + DataScience.libraryRequiredToLaunchJupyterNotInstalledInterpreter().format(activePythonInterpreter.displayName!, ProductNames.get(Product.notebook)!) + ); }); test('Cannot get a list of running jupyter servers', async () => { const promise = jupyterInterpreterExecutionService.getRunningJupyterServers(undefined); when(jupyterDependencyService.getDependenciesNotInstalled(activePythonInterpreter, undefined)).thenResolve([Product.notebook]); - await expect(promise).to.eventually.be.rejectedWith(DataScience.libraryRequiredToLaunchJupyterNotInstalled().format(ProductNames.get(Product.notebook)!)); + await expect(promise).to.eventually.be.rejectedWith( + DataScience.libraryRequiredToLaunchJupyterNotInstalledInterpreter().format(activePythonInterpreter.displayName!, ProductNames.get(Product.notebook)!) + ); }); test('Cannot get kernelspecs', async () => { const promise = jupyterInterpreterExecutionService.getKernelSpecs(undefined); when(jupyterDependencyService.getDependenciesNotInstalled(activePythonInterpreter, undefined)).thenResolve([Product.notebook]); - await expect(promise).to.eventually.be.rejectedWith(DataScience.libraryRequiredToLaunchJupyterNotInstalled().format(ProductNames.get(Product.notebook)!)); + await expect(promise).to.eventually.be.rejectedWith( + DataScience.libraryRequiredToLaunchJupyterNotInstalledInterpreter().format(activePythonInterpreter.displayName!, ProductNames.get(Product.notebook)!) + ); }); }); // tslint:disable-next-line: max-func-body-length @@ -181,7 +197,10 @@ suite('Data Science - Jupyter InterpreterSubCommandExecutionService', () => { verify(jupyterDependencyService.installMissingDependencies(selectedJupyterInterpreter, undefined)).once(); }); test('Jupyter cannot be started because jupyter is not installed', async () => { - const expectedReason = DataScience.libraryRequiredToLaunchJupyterNotInstalled().format(ProductNames.get(Product.jupyter)!); + const expectedReason = DataScience.libraryRequiredToLaunchJupyterNotInstalledInterpreter().format( + selectedJupyterInterpreter.displayName!, + ProductNames.get(Product.jupyter)! + ); when(jupyterDependencyService.getDependenciesNotInstalled(selectedJupyterInterpreter, undefined)).thenResolve([Product.jupyter]); const reason = await jupyterInterpreterExecutionService.getReasonForJupyterNotebookNotBeingSupported(undefined); @@ -189,7 +208,10 @@ suite('Data Science - Jupyter InterpreterSubCommandExecutionService', () => { assert.equal(reason, expectedReason); }); test('Jupyter cannot be started because notebook is not installed', async () => { - const expectedReason = DataScience.libraryRequiredToLaunchJupyterNotInstalled().format(ProductNames.get(Product.notebook)!); + const expectedReason = DataScience.libraryRequiredToLaunchJupyterNotInstalledInterpreter().format( + selectedJupyterInterpreter.displayName!, + ProductNames.get(Product.notebook)! + ); when(jupyterDependencyService.getDependenciesNotInstalled(selectedJupyterInterpreter, undefined)).thenResolve([Product.notebook]); const reason = await jupyterInterpreterExecutionService.getReasonForJupyterNotebookNotBeingSupported(undefined); diff --git a/src/test/datascience/jupyter/kernels/kernelSelector.unit.test.ts b/src/test/datascience/jupyter/kernels/kernelSelector.unit.test.ts index 1b6d2206a634..cf29aaddde5a 100644 --- a/src/test/datascience/jupyter/kernels/kernelSelector.unit.test.ts +++ b/src/test/datascience/jupyter/kernels/kernelSelector.unit.test.ts @@ -14,6 +14,7 @@ import { IInstaller, Product } from '../../../../client/common/types'; import * as localize from '../../../../client/common/utils/localize'; import { noop } from '../../../../client/common/utils/misc'; import { Architecture } from '../../../../client/common/utils/platform'; +import { StopWatch } from '../../../../client/common/utils/stopWatch'; import { JupyterSessionManager } from '../../../../client/datascience/jupyter/jupyterSessionManager'; import { KernelSelectionProvider } from '../../../../client/datascience/jupyter/kernels/kernelSelections'; import { KernelSelector } from '../../../../client/datascience/jupyter/kernels/kernelSelector'; @@ -64,7 +65,7 @@ suite('Data Science - KernelSelector', () => { when(kernelSelectionProvider.getKernelSelectionsForRemoteSession(instance(sessionManager), anything())).thenResolve([]); when(appShell.showQuickPick(anything(), anything(), anything())).thenResolve(); - const kernel = await kernelSelector.selectRemoteKernel(instance(sessionManager)); + const kernel = await kernelSelector.selectRemoteKernel(new StopWatch(), instance(sessionManager)); assert.isEmpty(kernel); verify(kernelSelectionProvider.getKernelSelectionsForRemoteSession(instance(sessionManager), anything())).once(); @@ -74,7 +75,7 @@ suite('Data Science - KernelSelector', () => { when(kernelSelectionProvider.getKernelSelectionsForLocalSession(instance(sessionManager), anything())).thenResolve([]); when(appShell.showQuickPick(anything(), anything(), anything())).thenResolve(); - const kernel = await kernelSelector.selectLocalKernel(instance(sessionManager)); + const kernel = await kernelSelector.selectLocalKernel(new StopWatch(), instance(sessionManager)); assert.isEmpty(kernel); verify(kernelSelectionProvider.getKernelSelectionsForLocalSession(instance(sessionManager), anything())).once(); @@ -86,7 +87,7 @@ suite('Data Science - KernelSelector', () => { // tslint:disable-next-line: no-any when(appShell.showQuickPick(anything(), anything(), anything())).thenResolve({ selection: { kernelSpec } } as any); - const kernel = await kernelSelector.selectRemoteKernel(instance(sessionManager)); + const kernel = await kernelSelector.selectRemoteKernel(new StopWatch(), instance(sessionManager)); assert.isOk(kernel.kernelSpec === kernelSpec); assert.isOk(kernel.interpreter === interpreter); @@ -121,7 +122,7 @@ suite('Data Science - KernelSelector', () => { kernelSelector.addKernelToIgnoreList({ id: 'id2' } as any); // tslint:disable-next-line: no-any kernelSelector.addKernelToIgnoreList({ clientId: 'id4' } as any); - const kernel = await kernelSelector.selectRemoteKernel(instance(sessionManager)); + const kernel = await kernelSelector.selectRemoteKernel(new StopWatch(), instance(sessionManager)); assert.isEmpty(kernel); verify(kernelSelectionProvider.getKernelSelectionsForRemoteSession(instance(sessionManager), anything())).once(); @@ -157,7 +158,7 @@ suite('Data Science - KernelSelector', () => { kernelSelector.addKernelToIgnoreList({ id: 'id2' } as any); // tslint:disable-next-line: no-any kernelSelector.addKernelToIgnoreList({ clientId: 'id4' } as any); - const kernel = await kernelSelector.selectLocalKernel(instance(sessionManager)); + const kernel = await kernelSelector.selectLocalKernel(new StopWatch(), instance(sessionManager)); assert.isEmpty(kernel); verify(kernelSelectionProvider.getKernelSelectionsForLocalSession(instance(sessionManager), anything())).once(); @@ -176,7 +177,7 @@ suite('Data Science - KernelSelector', () => { // tslint:disable-next-line: no-any when(appShell.showQuickPick(anything(), anything(), anything())).thenResolve({ selection: { kernelSpec } } as any); - const kernel = await kernelSelector.selectLocalKernel(instance(sessionManager)); + const kernel = await kernelSelector.selectLocalKernel(new StopWatch(), instance(sessionManager)); assert.isOk(kernel.kernelSpec === kernelSpec); assert.isOk(kernel.interpreter === interpreter); @@ -192,7 +193,7 @@ suite('Data Science - KernelSelector', () => { // tslint:disable-next-line: no-any when(appShell.showQuickPick(anything(), anything(), anything())).thenResolve({ selection: { interpreter, kernelSpec } } as any); - const kernel = await kernelSelector.selectLocalKernel(instance(sessionManager)); + const kernel = await kernelSelector.selectLocalKernel(new StopWatch(), instance(sessionManager)); assert.isOk(kernel.kernelSpec === kernelSpec); verify(installer.isInstalled(Product.ipykernel, interpreter)).once(); @@ -212,7 +213,7 @@ suite('Data Science - KernelSelector', () => { // tslint:disable-next-line: no-any when(appShell.showQuickPick(anything(), anything(), anything())).thenResolve({ selection: { interpreter, kernelSpec } } as any); - const kernel = await kernelSelector.selectLocalKernel(instance(sessionManager)); + const kernel = await kernelSelector.selectLocalKernel(new StopWatch(), instance(sessionManager)); assert.isOk(kernel.kernelSpec === kernelSpec); assert.isOk(kernel.interpreter === interpreter); @@ -231,7 +232,7 @@ suite('Data Science - KernelSelector', () => { // tslint:disable-next-line: no-any when(appShell.showQuickPick(anything(), anything(), anything())).thenResolve({ selection: { interpreter, kernelSpec } } as any); - const kernel = await kernelSelector.selectLocalKernel(instance(sessionManager)); + const kernel = await kernelSelector.selectLocalKernel(new StopWatch(), instance(sessionManager)); assert.isOk(kernel.kernelSpec === kernelSpec); verify(installer.isInstalled(Product.ipykernel, interpreter)).once(); @@ -251,7 +252,7 @@ suite('Data Science - KernelSelector', () => { // tslint:disable-next-line: no-any let nbMetadata: nbformat.INotebookMetadata = {} as any; let selectLocalKernelStub: sinon.SinonStub< - [(IJupyterSessionManager | undefined)?, (CancellationToken | undefined)?, (IJupyterKernelSpec | LiveKernelModel)?], + [StopWatch, (IJupyterSessionManager | undefined)?, (CancellationToken | undefined)?, (IJupyterKernelSpec | LiveKernelModel)?], // tslint:disable-next-line: no-any Promise >; diff --git a/src/test/datascience/jupyter/kernels/kernelSwitcher.unit.test.ts b/src/test/datascience/jupyter/kernels/kernelSwitcher.unit.test.ts index ff3b69fef86b..ad736b2299ab 100644 --- a/src/test/datascience/jupyter/kernels/kernelSwitcher.unit.test.ts +++ b/src/test/datascience/jupyter/kernels/kernelSwitcher.unit.test.ts @@ -97,14 +97,14 @@ suite('Data Science - Kernel Switcher', () => { verify(notebook.getKernelSpec()).once(); if (isLocalConnection) { - verify(kernelSelector.selectLocalKernel(undefined, undefined, currentKernelInfo.currentKernel)).once(); + verify(kernelSelector.selectLocalKernel(anything(), undefined, undefined, currentKernelInfo.currentKernel)).once(); } else { - verify(kernelSelector.selectRemoteKernel(anything(), anything(), anything())).once(); + verify(kernelSelector.selectRemoteKernel(anything(), anything(), anything(), anything())).once(); } }); test('Prompt to select local kernel', async () => { - when(kernelSelector.selectLocalKernel(undefined, undefined, currentKernelInfo.currentKernel)).thenResolve({}); + when(kernelSelector.selectLocalKernel(anything(), undefined, undefined, currentKernelInfo.currentKernel)).thenResolve({}); const selection = await kernelSwitcher.switchKernel(instance(notebook)); @@ -114,13 +114,13 @@ suite('Data Science - Kernel Switcher', () => { suite('Kernel Selected', () => { setup(() => { if (isLocalConnection) { - when(kernelSelector.selectLocalKernel(undefined, undefined, currentKernelInfo.currentKernel)).thenResolve({ + when(kernelSelector.selectLocalKernel(anything(), undefined, undefined, currentKernelInfo.currentKernel)).thenResolve({ kernelModel: selectedKernel, kernelSpec: undefined, interpreter: selectedInterpreter }); } else { - when(kernelSelector.selectRemoteKernel(anything(), anything(), anything())).thenResolve({ + when(kernelSelector.selectRemoteKernel(anything(), anything(), anything(), anything())).thenResolve({ kernelModel: selectedKernel, kernelSpec: undefined, interpreter: selectedInterpreter @@ -212,7 +212,7 @@ suite('Data Science - Kernel Switcher', () => { return; } }); - when(kernelSelector.selectLocalKernel(undefined, anything(), anything())).thenCall(() => { + when(kernelSelector.selectLocalKernel(anything(), undefined, anything(), anything())).thenCall(() => { // When selecting a kernel the second time, then return a different selection. firstTimeSelectingAKernel = false; return { @@ -221,8 +221,10 @@ suite('Data Science - Kernel Switcher', () => { interpreter: selectedInterpreter }; }); - // tslint:disable-next-line: no-any - when(appShell.showErrorMessage(anything(), anything(), anything())).thenResolve(DataScience.selectDifferentKernel() as any); + when(appShell.showErrorMessage(anything(), anything(), anything())).thenResolve( + // tslint:disable-next-line: no-any + DataScience.selectDifferentKernel() as any + ); const selection = await kernelSwitcher.switchKernel(instance(notebook)); @@ -234,7 +236,7 @@ suite('Data Science - Kernel Switcher', () => { verify(notebook.setInterpreter(selectedInterpreter)).once(); verify(appShell.showErrorMessage(anything(), DataScience.selectDifferentKernel(), Common.cancel())).once(); // first time when user select a kernel, second time is when user selects after failing to switch to the first kernel. - verify(kernelSelector.selectLocalKernel(anything(), anything(), anything())).twice(); + verify(kernelSelector.selectLocalKernel(anything(), anything(), anything(), anything())).twice(); }); }); }); diff --git a/src/test/datascience/notebook.functional.test.ts b/src/test/datascience/notebook.functional.test.ts index e99f5f29fdd7..4e04465ecb52 100644 --- a/src/test/datascience/notebook.functional.test.ts +++ b/src/test/datascience/notebook.functional.test.ts @@ -1224,7 +1224,7 @@ plt.show()`, threw = true; // When using old command finder, the error is `Not Supported` (directly from stdout). - can be deprecated when jupyterCommandFinder.ts is deleted. // When using new approach, we inform user that some packages are not installed. - const expectedErrorMsg = getMessageForLibrariesNotInstalled([Product.jupyter, Product.notebook]); + const expectedErrorMsg = getMessageForLibrariesNotInstalled([Product.jupyter, Product.notebook], 'Python'); assert.ok(e.message.includes('Not supported') || e.message.includes(expectedErrorMsg), `Wrong error thrown when notebook is created. Error is ${e.message}`); } diff --git a/src/test/datascience/variableexplorer.functional.test.tsx b/src/test/datascience/variableexplorer.functional.test.tsx index 813cd9411e1b..c93a2e03110a 100644 --- a/src/test/datascience/variableexplorer.functional.test.tsx +++ b/src/test/datascience/variableexplorer.functional.test.tsx @@ -184,7 +184,16 @@ myDict = {'a': 1}`; { name: 'myDict', value: "{'a': 1}", supportsDataExplorer: true, type: 'dict', size: 54, shape: '', count: 0, truncated: false }, { name: 'myList', value: '[1, 2, 3]', supportsDataExplorer: true, type: 'list', size: 54, shape: '', count: 0, truncated: false }, // Set can vary between python versions, so just don't both to check the value, just see that we got it - { name: 'mySet', value: undefined, supportsDataExplorer: true, type: 'set', size: 54, shape: '', count: 0, truncated: false } + { + name: 'mySet', + value: undefined, + supportsDataExplorer: false, + type: 'set', + size: 54, + shape: '', + count: 0, + truncated: false + } ]; verifyVariables(wrapper, targetVariables); }, @@ -356,18 +365,29 @@ function verifyRow(rowWrapper: ReactWrapper, React.Component>, if (targetVariable.value) { verifyCell(rowCells.at(3), targetVariable.value, targetVariable.name); } + + verifyCell(rowCells.at(4), targetVariable.supportsDataExplorer, targetVariable.name); } // Verify a single cell value against a specific target value -function verifyCell(cellWrapper: ReactWrapper, React.Component>, value: string, targetName: string) { +function verifyCell(cellWrapper: ReactWrapper, React.Component>, value: string | boolean, targetName: string) { const cellHTML = parse(cellWrapper.html()) as any; - // tslint:disable-next-line:no-string-literal - const match = /value="([\s\S]+?)"\s+/.exec(cellHTML.innerHTML); - expect(match).to.not.be.equal(null, `${targetName} does not have a value attribute`); - - // Eliminate whitespace differences - const actualValueNormalized = match![1].replace(/^\s*|\s(?=\s)|\s*$/g, '').replace(/\r\n/g, '\n'); - const expectedValueNormalized = value.replace(/^\s*|\s(?=\s)|\s*$/g, '').replace(/\r\n/g, '\n'); - - expect(actualValueNormalized).to.be.equal(expectedValueNormalized, `${targetName} has an unexpected value ${cellHTML.innerHTML} in variable explorer cell`); + const innerHTML = cellHTML.innerHTML; + if (typeof value === 'string') { + // tslint:disable-next-line:no-string-literal + const match = /value="([\s\S]+?)"\s+/.exec(innerHTML); + expect(match).to.not.be.equal(null, `${targetName} does not have a value attribute`); + + // Eliminate whitespace differences + const actualValueNormalized = match![1].replace(/^\s*|\s(?=\s)|\s*$/g, '').replace(/\r\n/g, '\n'); + const expectedValueNormalized = value.replace(/^\s*|\s(?=\s)|\s*$/g, '').replace(/\r\n/g, '\n'); + + expect(actualValueNormalized).to.be.equal(expectedValueNormalized, `${targetName} has an unexpected value ${innerHTML} in variable explorer cell`); + } else { + if (value) { + expect(innerHTML).to.include('image-button-image', `Image class not found in ${targetName}`); + } else { + expect(innerHTML).to.not.include('image-button-image', `Image class was found ${targetName}`); + } + } } From 933101a8fcab39ccf67b7da238cb563d527f6de0 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Tue, 18 Feb 2020 14:54:11 -0800 Subject: [PATCH 22/30] Cherry pick more fixes for feb point2 (#10183) * Ensure DS auto start code is non-blocking (#10171) * Perf fixes * Add news entry * Include interperter name in message (#10174) For #10071 Fix to ensure interpreter is included in message, here's the actual message seen by the user. Error: Jupyter cannot be started. Error attempting to locate jupyter: 'Kernelspec' module not installed in the selected interpreter ({0}). Note the {0} * Ignore display name when searching interpreters (#10175) Partial fix for #10173 Comparing against path of interpreter alone is sufficient. Figured there's no harm in trying to minimise occurrences of dup kernels (basically just compare against python executable path, as thats sufficient and always accurate) Display name: Can change from version to version of Python extension (i.e. it shouldn't have been used as a unique identifier) Display name can change after extension loads and more information about interpreter is available. * Track cold/warm times to execute notebook cells (#10180) For #10176 --- news/2 Fixes/10170.md | 1 + news/3 Code Health/10176.md | 1 + src/client/datascience/activation.ts | 2 +- .../interactive-ipynb/nativeEditor.ts | 17 ++++++++++++++++- ...yterInterpreterSubCommandExecutionService.ts | 2 +- .../jupyter/kernels/kernelService.ts | 3 --- src/client/telemetry/index.ts | 12 ++++++++++-- ...reterSubCommandExecutionService.unit.test.ts | 2 +- 8 files changed, 31 insertions(+), 9 deletions(-) create mode 100644 news/2 Fixes/10170.md create mode 100644 news/3 Code Health/10176.md diff --git a/news/2 Fixes/10170.md b/news/2 Fixes/10170.md new file mode 100644 index 000000000000..f9cc91fb8d8c --- /dev/null +++ b/news/2 Fixes/10170.md @@ -0,0 +1 @@ +Perf improvements to executing startup code for `Data Science` features when extension loads. diff --git a/news/3 Code Health/10176.md b/news/3 Code Health/10176.md new file mode 100644 index 000000000000..28237633c5b2 --- /dev/null +++ b/news/3 Code Health/10176.md @@ -0,0 +1 @@ +Track cold/warm times to execute notebook cells. diff --git a/src/client/datascience/activation.ts b/src/client/datascience/activation.ts index 7e73b10dd1a3..f2b7fbd012c6 100644 --- a/src/client/datascience/activation.ts +++ b/src/client/datascience/activation.ts @@ -30,7 +30,7 @@ export class Activation implements IExtensionSingleActivationService { this.disposables.push(this.jupyterInterpreterService.onDidChangeInterpreter(this.onDidChangeInterpreter, this)); // Warm up our selected interpreter for the extension this.jupyterInterpreterService.setInitialInterpreter().ignoreErrors(); - await this.contextService.activate(); + this.contextService.activate().ignoreErrors(); } private onDidOpenNotebookEditor(_: INotebookEditor) { diff --git a/src/client/datascience/interactive-ipynb/nativeEditor.ts b/src/client/datascience/interactive-ipynb/nativeEditor.ts index 8cdb2480432d..04f25608d803 100644 --- a/src/client/datascience/interactive-ipynb/nativeEditor.ts +++ b/src/client/datascience/interactive-ipynb/nativeEditor.ts @@ -77,6 +77,7 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor { public get onDidChangeViewState(): Event { return this._onDidChangeViewState.event; } + private sentExecuteCellTelemetry: boolean = false; private _onDidChangeViewState = new EventEmitter(); private closedEvent: EventEmitter = new EventEmitter(); private executedEvent: EventEmitter = new EventEmitter(); @@ -362,8 +363,10 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor { } protected submitCode(code: string, file: string, line: number, id?: string, editor?: TextEditor, debug?: boolean): Promise { + const stopWatch = new StopWatch(); + const submitCodePromise = super.submitCode(code, file, line, id, editor, debug).finally(() => this.sendPerceivedCellExecute(stopWatch)); // When code is executed, update the version number in the metadata. - return super.submitCode(code, file, line, id, editor, debug).then(value => { + return submitCodePromise.then(value => { this.updateVersionInfoInNotebook() .then(() => { this.metadataUpdatedEvent.fire(this); @@ -513,6 +516,18 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor { // Actually don't close, just let the error bubble out } + private sendPerceivedCellExecute(runningStopWatch?: StopWatch) { + if (runningStopWatch) { + const props = { notebook: true }; + if (!this.sentExecuteCellTelemetry) { + this.sentExecuteCellTelemetry = true; + sendTelemetryEvent(Telemetry.ExecuteCellPerceivedCold, runningStopWatch.elapsedTime, props); + } else { + sendTelemetryEvent(Telemetry.ExecuteCellPerceivedWarm, runningStopWatch.elapsedTime, props); + } + } + } + /** * Update the Python Version number in the notebook data. * diff --git a/src/client/datascience/jupyter/interpreter/jupyterInterpreterSubCommandExecutionService.ts b/src/client/datascience/jupyter/interpreter/jupyterInterpreterSubCommandExecutionService.ts index 6596e5189dc8..83bc261d1431 100644 --- a/src/client/datascience/jupyter/interpreter/jupyterInterpreterSubCommandExecutionService.ts +++ b/src/client/datascience/jupyter/interpreter/jupyterInterpreterSubCommandExecutionService.ts @@ -83,7 +83,7 @@ export class JupyterInterpreterSubCommandExecutionService implements IJupyterSub } if (productsNotInstalled.length === 1 && productsNotInstalled[0] === Product.kernelspec) { - return DataScience.jupyterKernelSpecModuleNotFound(); + return DataScience.jupyterKernelSpecModuleNotFound().format(interpreter.path); } return getMessageForLibrariesNotInstalled(productsNotInstalled, interpreter.displayName); diff --git a/src/client/datascience/jupyter/kernels/kernelService.ts b/src/client/datascience/jupyter/kernels/kernelService.ts index aee36b7050f9..2fe79ba5bfb7 100644 --- a/src/client/datascience/jupyter/kernels/kernelService.ts +++ b/src/client/datascience/jupyter/kernels/kernelService.ts @@ -99,9 +99,6 @@ export class KernelService { if (item.language.toLowerCase() !== PYTHON_LANGUAGE.toLowerCase()) { return false; } - if (item.display_name !== option.displayName) { - return false; - } return this.fileSystem.arePathsSame(item.argv[0], option.path) || this.fileSystem.arePathsSame(item.metadata?.interpreter?.path || '', option.path); }); } else { diff --git a/src/client/telemetry/index.ts b/src/client/telemetry/index.ts index 4d8ae0be241c..c0c212d3abb2 100644 --- a/src/client/telemetry/index.ts +++ b/src/client/telemetry/index.ts @@ -1459,8 +1459,16 @@ export interface IEventNamePropertyMapping { [Telemetry.DisableInteractiveShiftEnter]: never | undefined; [Telemetry.EnableInteractiveShiftEnter]: never | undefined; [Telemetry.ExecuteCell]: never | undefined; - [Telemetry.ExecuteCellPerceivedCold]: never | undefined; - [Telemetry.ExecuteCellPerceivedWarm]: never | undefined; + /** + * Telemetry sent to capture first time execution of a cell. + * If `notebook = true`, this its telemetry for native editor/notebooks. + */ + [Telemetry.ExecuteCellPerceivedCold]: undefined | { notebook: boolean }; + /** + * Telemetry sent to capture subsequent execution of a cell. + * If `notebook = true`, this its telemetry for native editor/notebooks. + */ + [Telemetry.ExecuteCellPerceivedWarm]: undefined | { notebook: boolean }; [Telemetry.ExecuteNativeCell]: never | undefined; [Telemetry.ExpandAll]: never | undefined; [Telemetry.ExportNotebook]: never | undefined; diff --git a/src/test/datascience/jupyter/interpreter/jupyterInterpreterSubCommandExecutionService.unit.test.ts b/src/test/datascience/jupyter/interpreter/jupyterInterpreterSubCommandExecutionService.unit.test.ts index f7d80baaa9d4..1a37eb1111ce 100644 --- a/src/test/datascience/jupyter/interpreter/jupyterInterpreterSubCommandExecutionService.unit.test.ts +++ b/src/test/datascience/jupyter/interpreter/jupyterInterpreterSubCommandExecutionService.unit.test.ts @@ -223,7 +223,7 @@ suite('Data Science - Jupyter InterpreterSubCommandExecutionService', () => { const reason = await jupyterInterpreterExecutionService.getReasonForJupyterNotebookNotBeingSupported(undefined); - assert.equal(reason, DataScience.jupyterKernelSpecModuleNotFound()); + assert.equal(reason, DataScience.jupyterKernelSpecModuleNotFound().format(selectedJupyterInterpreter.path)); }); test('Can start jupyer notebook', async () => { const output = await jupyterInterpreterExecutionService.startNotebook([], {}); From ea89876151e5077baa724a5efcea7713bb4e531e Mon Sep 17 00:00:00 2001 From: Ian Huff Date: Tue, 18 Feb 2020 15:20:49 -0800 Subject: [PATCH 23/30] fix SVG mimetype name (#10181) (#10185) --- news/2 Fixes/10168.md | 1 + src/datascience-ui/interactive-common/transforms.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 news/2 Fixes/10168.md diff --git a/news/2 Fixes/10168.md b/news/2 Fixes/10168.md new file mode 100644 index 000000000000..cf00c00c0f5d --- /dev/null +++ b/news/2 Fixes/10168.md @@ -0,0 +1 @@ +Fix svg mimetype so it shows up correctly in richest mimetype order. \ No newline at end of file diff --git a/src/datascience-ui/interactive-common/transforms.tsx b/src/datascience-ui/interactive-common/transforms.tsx index d4b3a86d511a..8b77b0fdab14 100644 --- a/src/datascience-ui/interactive-common/transforms.tsx +++ b/src/datascience-ui/interactive-common/transforms.tsx @@ -65,7 +65,7 @@ const mimeTypeToImport: TransformData[] = [ const module = await import(/* webpackChunkName: "plotly" */ '@nteract/transform-plotly'); return module.PlotlyTransform; }), - new TransformData('image/svg', async () => { + new TransformData('image/svg+xml', async () => { const module = await import(/* webpackChunkName: "nteract_transforms" */ '@nteract/transforms'); return module.SVGTransform; }), From 7a01a9a18c22c8316331dc3c79824d17a178a2f9 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Wed, 19 Feb 2020 08:34:41 -0800 Subject: [PATCH 24/30] Update change log --- CHANGELOG.md | 6 ++++++ news/2 Fixes/10168.md | 1 - news/2 Fixes/10170.md | 1 - news/3 Code Health/10176.md | 1 - 4 files changed, 6 insertions(+), 3 deletions(-) delete mode 100644 news/2 Fixes/10168.md delete mode 100644 news/2 Fixes/10170.md delete mode 100644 news/3 Code Health/10176.md diff --git a/CHANGELOG.md b/CHANGELOG.md index b3063ba7db68..e28e586470ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ ([#10074](https://github.com/Microsoft/vscode-python/issues/10074)) 1. Fix data viewer not opening on certain data frames. ([#10075](https://github.com/Microsoft/vscode-python/issues/10075)) +1. Fix svg mimetype so it shows up correctly in richest mimetype order. + ([#10168](https://github.com/Microsoft/vscode-python/issues/10168)) +1. Perf improvements to executing startup code for `Data Science` features when extension loads. + ([#10170](https://github.com/Microsoft/vscode-python/issues/10170)) ### Code Health @@ -23,6 +27,8 @@ ([#9883](https://github.com/Microsoft/vscode-python/issues/9883)) 1. Change select kernel telemetry to track duration till quick pick appears. ([#10049](https://github.com/Microsoft/vscode-python/issues/10049)) +1. Track cold/warm times to execute notebook cells. + ([#10176](https://github.com/Microsoft/vscode-python/issues/10176)) ### Thanks diff --git a/news/2 Fixes/10168.md b/news/2 Fixes/10168.md deleted file mode 100644 index cf00c00c0f5d..000000000000 --- a/news/2 Fixes/10168.md +++ /dev/null @@ -1 +0,0 @@ -Fix svg mimetype so it shows up correctly in richest mimetype order. \ No newline at end of file diff --git a/news/2 Fixes/10170.md b/news/2 Fixes/10170.md deleted file mode 100644 index f9cc91fb8d8c..000000000000 --- a/news/2 Fixes/10170.md +++ /dev/null @@ -1 +0,0 @@ -Perf improvements to executing startup code for `Data Science` features when extension loads. diff --git a/news/3 Code Health/10176.md b/news/3 Code Health/10176.md deleted file mode 100644 index 28237633c5b2..000000000000 --- a/news/3 Code Health/10176.md +++ /dev/null @@ -1 +0,0 @@ -Track cold/warm times to execute notebook cells. From 71642d3815418a8b4c16d78e93a626c5e1efc88f Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Wed, 19 Feb 2020 13:27:04 -0800 Subject: [PATCH 25/30] Some more ds telemetry (#10218) * Add telemetry to capture perceived time taken to start jupyter and run cell (#10217) * Add telemetry * Only for nb For #10098 For #10212 * Fix change log * Fix linter --- CHANGELOG.md | 4 ++++ src/client/datascience/constants.ts | 3 +++ .../interactive-common/interactiveBase.ts | 15 +++++++++++++-- .../datascience/jupyter/jupyterExecution.ts | 5 +++++ src/client/telemetry/index.ts | 12 ++++++++++++ 5 files changed, 37 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e28e586470ee..e231721de64e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,10 @@ ([#10049](https://github.com/Microsoft/vscode-python/issues/10049)) 1. Track cold/warm times to execute notebook cells. ([#10176](https://github.com/Microsoft/vscode-python/issues/10176)) +1. Telemetry to capture connections to `localhost` using the connect to remote Jupyter server feature. + ([#10098](https://github.com/Microsoft/vscode-python/issues/10098)) +1. Telemetry to capture perceived startup times of Jupyter and time to execute a cell. + ([#10212](https://github.com/Microsoft/vscode-python/issues/10212)) ### Thanks diff --git a/src/client/datascience/constants.ts b/src/client/datascience/constants.ts index 07f4e8959013..6bd07eeed2c5 100644 --- a/src/client/datascience/constants.ts +++ b/src/client/datascience/constants.ts @@ -160,6 +160,7 @@ export enum Telemetry { SubmitCellThroughInput = 'DATASCIENCE.SUBMITCELLFROMREPL', ConnectLocalJupyter = 'DS_INTERNAL.CONNECTLOCALJUPYTER', ConnectRemoteJupyter = 'DS_INTERNAL.CONNECTREMOTEJUPYTER', + ConnectRemoteJupyterViaLocalHost = 'DS_INTERNAL.CONNECTREMOTEJUPYTER_VIA_LOCALHOST', ConnectFailedJupyter = 'DS_INTERNAL.CONNECTFAILEDJUPYTER', ConnectRemoteFailedJupyter = 'DS_INTERNAL.CONNECTREMOTEFAILEDJUPYTER', StartSessionFailedJupyter = 'DS_INTERNAL.START_SESSION_FAILED_JUPYTER', @@ -209,6 +210,8 @@ export enum Telemetry { ExecuteCell = 'DATASCIENCE.EXECUTE_CELL_TIME', ExecuteCellPerceivedCold = 'DS_INTERNAL.EXECUTE_CELL_PERCEIVED_COLD', ExecuteCellPerceivedWarm = 'DS_INTERNAL.EXECUTE_CELL_PERCEIVED_WARM', + PerceivedJupyterStartupNotebook = 'DS_INTERNAL.PERCEIVED_JUPYTER_STARTUP_NOTEBOOK', + StartExecuteNotebookCellPerceivedCold = 'DS_INTERNAL.START_EXECUTE_NOTEBOOK_CELL_PERCEIVED_COLD', WebviewStartup = 'DS_INTERNAL.WEBVIEW_STARTUP', VariableExplorerFetchTime = 'DS_INTERNAL.VARIABLE_EXPLORER_FETCH_TIME', WebviewStyleUpdate = 'DS_INTERNAL.WEBVIEW_STYLE_UPDATE', diff --git a/src/client/datascience/interactive-common/interactiveBase.ts b/src/client/datascience/interactive-common/interactiveBase.ts index 7c89937cefb9..a678ac389400 100644 --- a/src/client/datascience/interactive-common/interactiveBase.ts +++ b/src/client/datascience/interactive-common/interactiveBase.ts @@ -20,6 +20,7 @@ import { IFileSystem } from '../../common/platform/types'; import { IConfigurationService, IDisposableRegistry, IExperimentsManager } from '../../common/types'; import { createDeferred, Deferred } from '../../common/utils/async'; import * as localize from '../../common/utils/localize'; +import { StopWatch } from '../../common/utils/stopWatch'; import { IInterpreterService, PythonInterpreter } from '../../interpreter/contracts'; import { captureTelemetry, sendTelemetryEvent } from '../../telemetry'; import { generateCellRangesFromDocument } from '../cellFactory'; @@ -78,6 +79,7 @@ import { InteractiveWindowMessageListener } from './interactiveWindowMessageList export abstract class InteractiveBase extends WebViewHost implements IInteractiveBase { private unfinishedCells: ICell[] = []; private restartingKernel: boolean = false; + private perceivedJupyterStartupTelemetryCaptured: boolean = false; private potentiallyUnfinishedStatus: Disposable[] = []; private addSysInfoPromise: Deferred | undefined; private _notebook: INotebook | undefined; @@ -457,8 +459,8 @@ export abstract class InteractiveBase extends WebViewHost { traceInfo(`Submitting code for ${this.id}`); + const stopWatch = this._notebook && !this.perceivedJupyterStartupTelemetryCaptured ? new StopWatch() : undefined; let result = true; - // Do not execute or render empty code cells const cellMatcher = new CellMatcher(this.configService.getSettings().datascience); if (cellMatcher.stripFirstMarker(code).length === 0) { @@ -511,7 +513,16 @@ export abstract class InteractiveBase extends WebViewHost { + if (e === ServerStatus.Busy) { + sendTelemetryEvent(Telemetry.StartExecuteNotebookCellPerceivedCold, stopWatch?.elapsedTime); + disposable.dispose(); + } + }); + } const observable = this._notebook.executeObservable(code, file, line, id, false); // Indicate we executed some code diff --git a/src/client/datascience/jupyter/jupyterExecution.ts b/src/client/datascience/jupyter/jupyterExecution.ts index 3fbe3fdf1cd3..312018fdcdd8 100644 --- a/src/client/datascience/jupyter/jupyterExecution.ts +++ b/src/client/datascience/jupyter/jupyterExecution.ts @@ -31,6 +31,8 @@ import { JupyterWaitForIdleError } from './jupyterWaitForIdleError'; import { KernelSelector, KernelSpecInterpreter } from './kernels/kernelSelector'; import { NotebookStarter } from './notebookStarter'; +const LocalHosts = ['localhost', '127.0.0.1', '::1']; + export class JupyterExecutionBase implements IJupyterExecution { private usablePythonInterpreter: PythonInterpreter | undefined; private eventEmitter: EventEmitter = new EventEmitter(); @@ -143,6 +145,9 @@ export class JupyterExecutionBase implements IJupyterExecution { try { // Start or connect to the process [connection, kernelSpecInterpreter] = await Promise.all([this.startOrConnect(options, cancelToken), kernelSpecInterpreterPromise]); + if (!connection.localLaunch && LocalHosts.includes(connection.hostName.toLowerCase())) { + sendTelemetryEvent(Telemetry.ConnectRemoteJupyterViaLocalHost); + } // Create a server tha t we will then attempt to connect to. result = this.serviceContainer.get(INotebookServer); diff --git a/src/client/telemetry/index.ts b/src/client/telemetry/index.ts index c0c212d3abb2..d280af20dade 100644 --- a/src/client/telemetry/index.ts +++ b/src/client/telemetry/index.ts @@ -1436,6 +1436,10 @@ export interface IEventNamePropertyMapping { [Telemetry.ConnectFailedJupyter]: never | undefined; [Telemetry.ConnectLocalJupyter]: never | undefined; [Telemetry.ConnectRemoteJupyter]: never | undefined; + /** + * Connecting to an existing Jupyter server, but connecting to localhost. + */ + [Telemetry.ConnectRemoteJupyterViaLocalHost]: never | undefined; [Telemetry.ConnectRemoteFailedJupyter]: never | undefined; [Telemetry.ConnectRemoteSelfCertFailedJupyter]: never | undefined; [Telemetry.RegisterAndUseInterpreterAsKernel]: never | undefined; @@ -1469,6 +1473,14 @@ export interface IEventNamePropertyMapping { * If `notebook = true`, this its telemetry for native editor/notebooks. */ [Telemetry.ExecuteCellPerceivedWarm]: undefined | { notebook: boolean }; + /** + * Time take for jupyter server to start and be ready to run first user cell. + */ + [Telemetry.PerceivedJupyterStartupNotebook]: never | undefined; + /** + * Time take for jupyter server to be busy from the time user first hit `run` cell until jupyter reports it is busy running a cell. + */ + [Telemetry.StartExecuteNotebookCellPerceivedCold]: never | undefined; [Telemetry.ExecuteNativeCell]: never | undefined; [Telemetry.ExpandAll]: never | undefined; [Telemetry.ExportNotebook]: never | undefined; From a3f09328770d4945d4ce59bc0bb7782a8403a17b Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Wed, 19 Feb 2020 14:45:32 -0800 Subject: [PATCH 26/30] Update date in change log --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e28e586470ee..fa97b7e3df86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 2020.2.2 (18 February 2020) +## 2020.2.2 (19 February 2020) ### Fixes From 9bcce5e270c7e332cc4b9af25f845c8c439c471d Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Fri, 21 Feb 2020 10:35:33 -0800 Subject: [PATCH 27/30] Point release with fix for Issue 10250 (#10254) * Fix to return env variables of interpreter that is not current interpreter (#10251) For #10250 * Bug fix * Update change log * Fix date * Oops * Fix linter --- CHANGELOG.md | 60 ++++++++++ package.json | 2 +- src/client/common/logger.ts | 2 +- src/client/interpreter/activation/service.ts | 36 ++++-- .../activation/service.unit.test.ts | 103 ++++++++++++++---- 5 files changed, 173 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 139b22a79769..a0ab79d9d231 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,65 @@ # Changelog +## 2020.2.3 (21 February 2020) + +### Fixes + +1. Ensure to correctly return env variables of the activated interpreter, when dealing with non-workspace interpreters. + ([#10250](https://github.com/Microsoft/vscode-python/issues/10250)) + +### Thanks + +Thanks to the following projects which we fully rely on to provide some of +our features: + +- [isort](https://pypi.org/project/isort/) +- [jedi](https://pypi.org/project/jedi/) + and [parso](https://pypi.org/project/parso/) +- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) +- [ptvsd](https://pypi.org/project/ptvsd/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) + +Also thanks to the various projects we provide integrations with which help +make this extension useful: + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [bandit](https://pypi.org/project/bandit/), + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +And finally thanks to the [Python](https://www.python.org/) development team and +community for creating a fantastic programming language and community to be a +part of! + ## 2020.2.2 (19 February 2020) ### Fixes diff --git a/package.json b/package.json index 8e11ca5be90e..8768b25f01b0 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "python", "displayName": "Python", "description": "Linting, Debugging (multi-threaded, remote), Intellisense, Jupyter Notebooks, code formatting, refactoring, unit tests, snippets, and more.", - "version": "2020.2.2", + "version": "2020.2.3", "languageServerVersion": "0.5.30", "publisher": "ms-python", "author": { diff --git a/src/client/common/logger.ts b/src/client/common/logger.ts index 3c75f1abf0a2..88a88a05199d 100644 --- a/src/client/common/logger.ts +++ b/src/client/common/logger.ts @@ -285,7 +285,7 @@ function trace(message: string, options: LogOptions = LogOptions.None, logLevel? // tslint:disable-next-line:no-any function writeToLog(elapsedTime: number, returnValue?: any, ex?: Error) { const messagesToLog = [message]; - messagesToLog.push(`Class name = ${className}, completed in ${elapsedTime}ms`); + messagesToLog.push(`Class name = ${className}, completed in ${elapsedTime}ms, has a ${returnValue ? 'truthy' : 'falsy'} return value`); if ((options && LogOptions.Arguments) === LogOptions.Arguments) { messagesToLog.push(argsToLogString(args)); } diff --git a/src/client/interpreter/activation/service.ts b/src/client/interpreter/activation/service.ts index 8311f329c6cf..bb27a8fc65cc 100644 --- a/src/client/interpreter/activation/service.ts +++ b/src/client/interpreter/activation/service.ts @@ -6,19 +6,20 @@ import '../../common/extensions'; import { inject, injectable } from 'inversify'; import * as path from 'path'; +import { IWorkspaceService } from '../../common/application/types'; import { PYTHON_WARNINGS } from '../../common/constants'; import { LogOptions, traceDecorators, traceError, traceVerbose } from '../../common/logger'; import { IPlatformService } from '../../common/platform/types'; import { IProcessServiceFactory } from '../../common/process/types'; import { ITerminalHelper, TerminalShellType } from '../../common/terminal/types'; import { ICurrentProcess, IDisposable, Resource } from '../../common/types'; -import { cacheResourceSpecificInterpreterData, clearCachedResourceSpecificIngterpreterData } from '../../common/utils/decorators'; +import { InMemoryCache } from '../../common/utils/cacheUtils'; import { OSType } from '../../common/utils/platform'; import { IEnvironmentVariablesProvider } from '../../common/variables/types'; import { EXTENSION_ROOT_DIR } from '../../constants'; import { captureTelemetry, sendTelemetryEvent } from '../../telemetry'; import { EventName } from '../../telemetry/constants'; -import { PythonInterpreter } from '../contracts'; +import { IInterpreterService, PythonInterpreter } from '../contracts'; import { IEnvironmentActivationService } from './types'; const getEnvironmentPrefix = 'e8b39361-0157-4923-80e1-22d70d46dee6'; @@ -36,14 +37,19 @@ const defaultShells = { @injectable() export class EnvironmentActivationService implements IEnvironmentActivationService, IDisposable { private readonly disposables: IDisposable[] = []; + private readonly activatedEnvVariablesCache = new Map>(); constructor( @inject(ITerminalHelper) private readonly helper: ITerminalHelper, @inject(IPlatformService) private readonly platform: IPlatformService, @inject(IProcessServiceFactory) private processServiceFactory: IProcessServiceFactory, @inject(ICurrentProcess) private currentProcess: ICurrentProcess, + @inject(IWorkspaceService) private workspace: IWorkspaceService, + @inject(IInterpreterService) private interpreterService: IInterpreterService, @inject(IEnvironmentVariablesProvider) private readonly envVarsService: IEnvironmentVariablesProvider ) { - this.envVarsService.onDidEnvironmentVariablesChange(this.onDidEnvironmentVariablesChange, this, this.disposables); + this.envVarsService.onDidEnvironmentVariablesChange(() => this.activatedEnvVariablesCache.clear(), this, this.disposables); + + this.interpreterService.onDidChangeInterpreter(() => this.activatedEnvVariablesCache.clear(), this, this.disposables); } public dispose(): void { @@ -51,8 +57,26 @@ export class EnvironmentActivationService implements IEnvironmentActivationServi } @traceDecorators.verbose('getActivatedEnvironmentVariables', LogOptions.Arguments) @captureTelemetry(EventName.PYTHON_INTERPRETER_ACTIVATION_ENVIRONMENT_VARIABLES, { failed: false }, true) - @cacheResourceSpecificInterpreterData('ActivatedEnvironmentVariables', cacheDuration) public async getActivatedEnvironmentVariables(resource: Resource, interpreter?: PythonInterpreter, allowExceptions?: boolean): Promise { + // Cache key = resource + interpreter. + const workspaceKey = this.workspace.getWorkspaceFolderIdentifier(resource); + const interpreterPath = this.platform.isWindows ? interpreter?.path.toLowerCase() : interpreter?.path; + const cacheKey = `${workspaceKey}_${interpreterPath}`; + + if (this.activatedEnvVariablesCache.get(cacheKey)?.hasData) { + return this.activatedEnvVariablesCache.get(cacheKey)!.data; + } + + // Cache only if successful, else keep trying & failing if necessary. + const cache = new InMemoryCache(cacheDuration, ''); + return this.getActivatedEnvironmentVariablesImpl(resource, interpreter, allowExceptions).then(vars => { + cache.data = vars; + this.activatedEnvVariablesCache.set(cacheKey, cache); + return vars; + }); + } + + public async getActivatedEnvironmentVariablesImpl(resource: Resource, interpreter?: PythonInterpreter, allowExceptions?: boolean): Promise { const shellInfo = defaultShells[this.platform.osType]; if (!shellInfo) { return; @@ -115,9 +139,7 @@ export class EnvironmentActivationService implements IEnvironmentActivationServi } } } - protected onDidEnvironmentVariablesChange(affectedResource: Resource) { - clearCachedResourceSpecificIngterpreterData('ActivatedEnvironmentVariables', affectedResource); - } + protected fixActivationCommands(commands: string[]): string[] { // Replace 'source ' with '. ' as that works in shell exec return commands.map(cmd => cmd.replace(/^source\s+/, '. ')); diff --git a/src/test/interpreters/activation/service.unit.test.ts b/src/test/interpreters/activation/service.unit.test.ts index d01db1f13565..41ca137097c0 100644 --- a/src/test/interpreters/activation/service.unit.test.ts +++ b/src/test/interpreters/activation/service.unit.test.ts @@ -7,8 +7,9 @@ import { EOL } from 'os'; import * as path from 'path'; import { SemVer } from 'semver'; import { anything, capture, instance, mock, verify, when } from 'ts-mockito'; -import * as typemoq from 'typemoq'; -import { EventEmitter, Uri, workspace as workspaceType, WorkspaceConfiguration } from 'vscode'; +import { EventEmitter, Uri } from 'vscode'; +import { IWorkspaceService } from '../../../client/common/application/types'; +import { WorkspaceService } from '../../../client/common/application/workspace'; import { PlatformService } from '../../../client/common/platform/platformService'; import { IPlatformService } from '../../../client/common/platform/types'; import { CurrentProcess } from '../../../client/common/process/currentProcess'; @@ -18,15 +19,14 @@ import { IProcessService, IProcessServiceFactory } from '../../../client/common/ import { TerminalHelper } from '../../../client/common/terminal/helper'; import { ITerminalHelper } from '../../../client/common/terminal/types'; import { ICurrentProcess } from '../../../client/common/types'; -import { clearCache } from '../../../client/common/utils/cacheUtils'; import { getNamesAndValues } from '../../../client/common/utils/enum'; import { Architecture, OSType } from '../../../client/common/utils/platform'; import { EnvironmentVariablesProvider } from '../../../client/common/variables/environmentVariablesProvider'; import { IEnvironmentVariablesProvider } from '../../../client/common/variables/types'; import { EXTENSION_ROOT_DIR } from '../../../client/constants'; import { EnvironmentActivationService } from '../../../client/interpreter/activation/service'; -import { InterpreterType, PythonInterpreter } from '../../../client/interpreter/contracts'; -import { mockedVSCodeNamespaces } from '../../vscode-mock'; +import { IInterpreterService, InterpreterType, PythonInterpreter } from '../../../client/interpreter/contracts'; +import { InterpreterService } from '../../../client/interpreter/interpreterService'; const getEnvironmentPrefix = 'e8b39361-0157-4923-80e1-22d70d46dee6'; const defaultShells = { @@ -45,8 +45,10 @@ suite('Interpreters Activation - Python Environment Variables', () => { let processService: IProcessService; let currentProcess: ICurrentProcess; let envVarsService: IEnvironmentVariablesProvider; - let workspace: typemoq.IMock; - + let workspace: IWorkspaceService; + let interpreterService: IInterpreterService; + let onDidChangeEnvVariables: EventEmitter; + let onDidChangeInterpreter: EventEmitter; const pythonInterpreter: PythonInterpreter = { path: '/foo/bar/python.exe', version: new SemVer('3.6.6-final'), @@ -63,21 +65,22 @@ suite('Interpreters Activation - Python Environment Variables', () => { processService = mock(ProcessService); currentProcess = mock(CurrentProcess); envVarsService = mock(EnvironmentVariablesProvider); - workspace = mockedVSCodeNamespaces.workspace!; - when(envVarsService.onDidEnvironmentVariablesChange).thenReturn(new EventEmitter().event); - service = new EnvironmentActivationService(instance(helper), instance(platform), instance(processServiceFactory), instance(currentProcess), instance(envVarsService)); - - const cfg = typemoq.Mock.ofType(); - workspace.setup(w => w.getConfiguration(typemoq.It.isValue('python'), typemoq.It.isAny())).returns(() => cfg.object); - workspace.setup(w => w.workspaceFolders).returns(() => []); - cfg.setup(c => c.inspect(typemoq.It.isValue('pythonPath'))).returns(() => { - return { globalValue: 'GlobalValuepython' } as any; - }); - clearCache(); + interpreterService = mock(InterpreterService); + workspace = mock(WorkspaceService); + onDidChangeEnvVariables = new EventEmitter(); + onDidChangeInterpreter = new EventEmitter(); + when(envVarsService.onDidEnvironmentVariablesChange).thenReturn(onDidChangeEnvVariables.event); + when(interpreterService.onDidChangeInterpreter).thenReturn(onDidChangeInterpreter.event); + service = new EnvironmentActivationService( + instance(helper), + instance(platform), + instance(processServiceFactory), + instance(currentProcess), + instance(workspace), + instance(interpreterService), + instance(envVarsService) + ); } - teardown(() => { - mockedVSCodeNamespaces.workspace!.reset(); - }); function title(resource?: Uri, interpreter?: PythonInterpreter) { return `${resource ? 'With a resource' : 'Without a resource'}${interpreter ? ' and an interpreter' : ''}`; @@ -218,6 +221,64 @@ suite('Interpreters Activation - Python Environment Variables', () => { verify(envVarsService.getEnvironmentVariables(resource)).once(); verify(processService.shellExec(anything(), anything())).once(); }); + test('Cache Variables', async () => { + const cmd = ['1', '2']; + const varsFromEnv = { one: '11', two: '22', HELLO: 'xxx' }; + const stdout = `${getEnvironmentPrefix}${EOL}${JSON.stringify(varsFromEnv)}`; + when(platform.osType).thenReturn(osType.value); + when(helper.getEnvironmentActivationShellCommands(resource, anything(), interpreter)).thenResolve(cmd); + when(processServiceFactory.create(resource)).thenResolve(instance(processService)); + when(envVarsService.getEnvironmentVariables(resource)).thenResolve({}); + when(processService.shellExec(anything(), anything())).thenResolve({ stdout: stdout }); + + const env = await service.getActivatedEnvironmentVariables(resource, interpreter); + const env2 = await service.getActivatedEnvironmentVariables(resource, interpreter); + const env3 = await service.getActivatedEnvironmentVariables(resource, interpreter); + + expect(env).to.deep.equal(varsFromEnv); + // All same objects. + expect(env) + .to.equal(env2) + .to.equal(env3); + + // All methods invoked only once. + verify(helper.getEnvironmentActivationShellCommands(resource, anything(), interpreter)).once(); + verify(processServiceFactory.create(resource)).once(); + verify(envVarsService.getEnvironmentVariables(resource)).once(); + verify(processService.shellExec(anything(), anything())).once(); + }); + async function testClearingCache(bustCache: Function) { + const cmd = ['1', '2']; + const varsFromEnv = { one: '11', two: '22', HELLO: 'xxx' }; + const stdout = `${getEnvironmentPrefix}${EOL}${JSON.stringify(varsFromEnv)}`; + when(platform.osType).thenReturn(osType.value); + when(helper.getEnvironmentActivationShellCommands(resource, anything(), interpreter)).thenResolve(cmd); + when(processServiceFactory.create(resource)).thenResolve(instance(processService)); + when(envVarsService.getEnvironmentVariables(resource)).thenResolve({}); + when(processService.shellExec(anything(), anything())).thenResolve({ stdout: stdout }); + + const env = await service.getActivatedEnvironmentVariables(resource, interpreter); + bustCache(); + const env2 = await service.getActivatedEnvironmentVariables(resource, interpreter); + + expect(env).to.deep.equal(varsFromEnv); + // Objects are different (not same reference). + expect(env).to.not.equal(env2); + // However variables are the same. + expect(env).to.deep.equal(env2); + + // All methods invoked twice as cache was blown. + verify(helper.getEnvironmentActivationShellCommands(resource, anything(), interpreter)).twice(); + verify(processServiceFactory.create(resource)).twice(); + verify(envVarsService.getEnvironmentVariables(resource)).twice(); + verify(processService.shellExec(anything(), anything())).twice(); + } + test('Cache Variables get cleared when changing interpreter', async () => { + await testClearingCache(onDidChangeInterpreter.fire.bind(onDidChangeInterpreter)); + }); + test('Cache Variables get cleared when changing env variables file', async () => { + await testClearingCache(onDidChangeEnvVariables.fire.bind(onDidChangeEnvVariables)); + }); }); }); }); From 3059c1825d8879e86ae31ed6d15f68b89a32704e Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Fri, 21 Feb 2020 13:02:14 -0800 Subject: [PATCH 28/30] Clean up --- news/2 Fixes/10071.md | 1 - news/2 Fixes/10072.md | 2 -- news/2 Fixes/10074.md | 1 - news/2 Fixes/10075.md | 1 - news/2 Fixes/10168.md | 1 - news/2 Fixes/10170.md | 1 - news/2 Fixes/10250.md | 1 - news/2 Fixes/9693.md | 1 - news/2 Fixes/9740.md | 1 - news/2 Fixes/9796.md | 2 -- news/2 Fixes/9901.md | 1 - news/2 Fixes/9904.md | 1 - news/2 Fixes/9926.md | 1 - news/2 Fixes/9933.md | 1 - news/2 Fixes/9976.md | 1 - news/2 Fixes/9991.md | 1 - news/3 Code Health/10049.md | 1 - news/3 Code Health/10098.md | 1 - news/3 Code Health/10176.md | 1 - news/3 Code Health/10212.md | 1 - news/3 Code Health/9819.md | 1 - news/3 Code Health/9883.md | 1 - 22 files changed, 24 deletions(-) delete mode 100644 news/2 Fixes/10071.md delete mode 100644 news/2 Fixes/10072.md delete mode 100644 news/2 Fixes/10074.md delete mode 100644 news/2 Fixes/10075.md delete mode 100644 news/2 Fixes/10168.md delete mode 100644 news/2 Fixes/10170.md delete mode 100644 news/2 Fixes/10250.md delete mode 100644 news/2 Fixes/9693.md delete mode 100644 news/2 Fixes/9740.md delete mode 100644 news/2 Fixes/9796.md delete mode 100644 news/2 Fixes/9901.md delete mode 100644 news/2 Fixes/9904.md delete mode 100644 news/2 Fixes/9926.md delete mode 100644 news/2 Fixes/9933.md delete mode 100644 news/2 Fixes/9976.md delete mode 100644 news/2 Fixes/9991.md delete mode 100644 news/3 Code Health/10049.md delete mode 100644 news/3 Code Health/10098.md delete mode 100644 news/3 Code Health/10176.md delete mode 100644 news/3 Code Health/10212.md delete mode 100644 news/3 Code Health/9819.md delete mode 100644 news/3 Code Health/9883.md diff --git a/news/2 Fixes/10071.md b/news/2 Fixes/10071.md deleted file mode 100644 index 842c8c2786d1..000000000000 --- a/news/2 Fixes/10071.md +++ /dev/null @@ -1 +0,0 @@ -Re-install `Jupyter` instead of installing `kernelspec` if `kernelspec` cannot be found in the python environment. diff --git a/news/2 Fixes/10072.md b/news/2 Fixes/10072.md deleted file mode 100644 index 195bfad15543..000000000000 --- a/news/2 Fixes/10072.md +++ /dev/null @@ -1,2 +0,0 @@ -Fix zh-tw localization file loading issue. -(thanks to [ChenKB91](https://github.com/ChenKB91/)) diff --git a/news/2 Fixes/10074.md b/news/2 Fixes/10074.md deleted file mode 100644 index 31bbcd2fe6db..000000000000 --- a/news/2 Fixes/10074.md +++ /dev/null @@ -1 +0,0 @@ -Fixes problem with showing ndarrays in the data viewer. \ No newline at end of file diff --git a/news/2 Fixes/10075.md b/news/2 Fixes/10075.md deleted file mode 100644 index 1b4d7f29dbbf..000000000000 --- a/news/2 Fixes/10075.md +++ /dev/null @@ -1 +0,0 @@ -Fix data viewer not opening on certain data frames. \ No newline at end of file diff --git a/news/2 Fixes/10168.md b/news/2 Fixes/10168.md deleted file mode 100644 index cf00c00c0f5d..000000000000 --- a/news/2 Fixes/10168.md +++ /dev/null @@ -1 +0,0 @@ -Fix svg mimetype so it shows up correctly in richest mimetype order. \ No newline at end of file diff --git a/news/2 Fixes/10170.md b/news/2 Fixes/10170.md deleted file mode 100644 index f9cc91fb8d8c..000000000000 --- a/news/2 Fixes/10170.md +++ /dev/null @@ -1 +0,0 @@ -Perf improvements to executing startup code for `Data Science` features when extension loads. diff --git a/news/2 Fixes/10250.md b/news/2 Fixes/10250.md deleted file mode 100644 index e3ed4fd36c48..000000000000 --- a/news/2 Fixes/10250.md +++ /dev/null @@ -1 +0,0 @@ -Ensure to correctly return env variables of the activated interpreter, when dealing with non-workspace interpreters. diff --git a/news/2 Fixes/9693.md b/news/2 Fixes/9693.md deleted file mode 100644 index 0f682d4babaa..000000000000 --- a/news/2 Fixes/9693.md +++ /dev/null @@ -1 +0,0 @@ -Pressing ctrl + 1/ctrl + 2 to focus on the interactive window will give focus to the input box. diff --git a/news/2 Fixes/9740.md b/news/2 Fixes/9740.md deleted file mode 100644 index 30bb6f62d107..000000000000 --- a/news/2 Fixes/9740.md +++ /dev/null @@ -1 +0,0 @@ -Make sure to clear variable list on restart kernel. \ No newline at end of file diff --git a/news/2 Fixes/9796.md b/news/2 Fixes/9796.md deleted file mode 100644 index 82ff822bd1c7..000000000000 --- a/news/2 Fixes/9796.md +++ /dev/null @@ -1,2 +0,0 @@ -Silently skip rendering mimetypes related to scrapbook. -Html won't crash if we find a mimetype that we don't support. diff --git a/news/2 Fixes/9901.md b/news/2 Fixes/9901.md deleted file mode 100644 index 3f04054b0926..000000000000 --- a/news/2 Fixes/9901.md +++ /dev/null @@ -1 +0,0 @@ -Ignore errors coming from stat(), where appropriate. diff --git a/news/2 Fixes/9904.md b/news/2 Fixes/9904.md deleted file mode 100644 index c41cbc380ec9..000000000000 --- a/news/2 Fixes/9904.md +++ /dev/null @@ -1 +0,0 @@ -Improve error messaging when the jupyter notebook cannot be started. \ No newline at end of file diff --git a/news/2 Fixes/9926.md b/news/2 Fixes/9926.md deleted file mode 100644 index c609b86c388b..000000000000 --- a/news/2 Fixes/9926.md +++ /dev/null @@ -1 +0,0 @@ -Use the autoStart server when available. diff --git a/news/2 Fixes/9933.md b/news/2 Fixes/9933.md deleted file mode 100644 index 371d3ed72c85..000000000000 --- a/news/2 Fixes/9933.md +++ /dev/null @@ -1 +0,0 @@ -Correct the server and kernel text for when not connected to a server. \ No newline at end of file diff --git a/news/2 Fixes/9976.md b/news/2 Fixes/9976.md deleted file mode 100644 index 6b79ac7b945b..000000000000 --- a/news/2 Fixes/9976.md +++ /dev/null @@ -1 +0,0 @@ -add --ip=127.0.0.1 argument of jupyter server when running in k8s container diff --git a/news/2 Fixes/9991.md b/news/2 Fixes/9991.md deleted file mode 100644 index 1296552cc995..000000000000 --- a/news/2 Fixes/9991.md +++ /dev/null @@ -1 +0,0 @@ -Clear variables in notebooks and interactive-window when restarting. \ No newline at end of file diff --git a/news/3 Code Health/10049.md b/news/3 Code Health/10049.md deleted file mode 100644 index 8db350b7860d..000000000000 --- a/news/3 Code Health/10049.md +++ /dev/null @@ -1 +0,0 @@ -Change select kernel telemetry to track duration till quick pick appears. \ No newline at end of file diff --git a/news/3 Code Health/10098.md b/news/3 Code Health/10098.md deleted file mode 100644 index 057ae06fa5e2..000000000000 --- a/news/3 Code Health/10098.md +++ /dev/null @@ -1 +0,0 @@ -Telemetry to capture connections to `localhost` using the connect to remote Jupyter server feature. diff --git a/news/3 Code Health/10176.md b/news/3 Code Health/10176.md deleted file mode 100644 index 28237633c5b2..000000000000 --- a/news/3 Code Health/10176.md +++ /dev/null @@ -1 +0,0 @@ -Track cold/warm times to execute notebook cells. diff --git a/news/3 Code Health/10212.md b/news/3 Code Health/10212.md deleted file mode 100644 index 4bf0014f1470..000000000000 --- a/news/3 Code Health/10212.md +++ /dev/null @@ -1 +0,0 @@ -Telemetry to capture perceived startup times of Jupyter and time to execute a cell. diff --git a/news/3 Code Health/9819.md b/news/3 Code Health/9819.md deleted file mode 100644 index 76445586b312..000000000000 --- a/news/3 Code Health/9819.md +++ /dev/null @@ -1 +0,0 @@ -Add telemetry to track notebook languages \ No newline at end of file diff --git a/news/3 Code Health/9883.md b/news/3 Code Health/9883.md deleted file mode 100644 index bf4fc2168a21..000000000000 --- a/news/3 Code Health/9883.md +++ /dev/null @@ -1 +0,0 @@ -Telemetry around kernels not working and installs not working. \ No newline at end of file From 78ead84ca6e85e938a5146a9d4ba9560de1a8ea3 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Fri, 21 Feb 2020 13:11:14 -0800 Subject: [PATCH 29/30] More clean up --- .../jupyter/interpreter/jupyterCommand.ts | 2 -- .../jupyter/liveshare/hostJupyterServer.ts | 23 ------------- .../history-react/interactivePanel.tsx | 1 - .../platform/filesystem.functional.test.ts | 25 --------------- .../common/platform/filesystem.unit.test.ts | 32 ------------------- ...rInterpreterDependencyService.unit.test.ts | 1 - 6 files changed, 84 deletions(-) diff --git a/src/client/datascience/jupyter/interpreter/jupyterCommand.ts b/src/client/datascience/jupyter/interpreter/jupyterCommand.ts index a246500493bd..49e5a970bd82 100644 --- a/src/client/datascience/jupyter/interpreter/jupyterCommand.ts +++ b/src/client/datascience/jupyter/interpreter/jupyterCommand.ts @@ -240,8 +240,6 @@ export class InterpreterJupyterKernelSpecCommand extends InterpreterJupyterComma return defaultAction(); } - // Otherwise try running a script instead. - // Otherwise try running a script instead. try { if (args.join(' ').toLowerCase() === 'list --json') { diff --git a/src/client/datascience/jupyter/liveshare/hostJupyterServer.ts b/src/client/datascience/jupyter/liveshare/hostJupyterServer.ts index 36de65fe4f52..b510f2be3e13 100644 --- a/src/client/datascience/jupyter/liveshare/hostJupyterServer.ts +++ b/src/client/datascience/jupyter/liveshare/hostJupyterServer.ts @@ -193,30 +193,7 @@ export class HostJupyterServer extends LiveShareParticipantHost(JupyterServerBas this.configService.getSettings(resource).datascience.jupyterLaunchTimeout ); } - // Create a copy of launch info, cuz we're modifying it here. - // This launch info contains the server connection info (that could be shared across other nbs). - // However the kernel info is different. The kernel info is stored as a property of this, hence create a separate instance for each nb. - launchInfo = { - ...launchInfo - }; - - // Find a kernel that can be used. - // Do this only if kernel information has been provided in the metadata, else use the default. - let defaultKernelInfoToUse = launchInfo.kernelSpec; - if (notebookMetadata?.kernelspec) { - const kernelInfo = await (launchInfo.connectionInfo.localLaunch - ? this.kernelSelector.getKernelForLocalConnection(sessionManager, notebookMetadata, false, cancelToken) - : this.kernelSelector.getKernelForRemoteConnection(sessionManager, notebookMetadata, cancelToken)); - const kernelInfoToUse = kernelInfo?.kernelSpec || kernelInfo?.kernelModel; - if (kernelInfoToUse) { - defaultKernelInfoToUse = kernelInfoToUse; - } - if (possibleSession && kernelInfoToUse) { - await possibleSession.changeKernel(kernelInfoToUse, this.configService.getSettings().datascience.jupyterLaunchTimeout); - } - launchInfo.kernelSpec = defaultKernelInfoToUse; - } // Start a session (or use the existing one) const session = possibleSession || (await sessionManager.startNew(info.kernelSpec, cancelToken)); traceInfo(`Started session ${this.id}`); diff --git a/src/datascience-ui/history-react/interactivePanel.tsx b/src/datascience-ui/history-react/interactivePanel.tsx index 43d085f6c05b..44d7e05c31a1 100644 --- a/src/datascience-ui/history-react/interactivePanel.tsx +++ b/src/datascience-ui/history-react/interactivePanel.tsx @@ -2,7 +2,6 @@ // Licensed under the MIT License. import * as React from 'react'; import { connect } from 'react-redux'; -import { noop } from '../../client/common/utils/misc'; import { Identifiers } from '../../client/datascience/constants'; import { buildSettingsCss } from '../interactive-common/buildSettingsCss'; import { ContentPanel, IContentPanelProps } from '../interactive-common/contentPanel'; diff --git a/src/test/common/platform/filesystem.functional.test.ts b/src/test/common/platform/filesystem.functional.test.ts index 32a7aaffffce..2b80f4157e06 100644 --- a/src/test/common/platform/filesystem.functional.test.ts +++ b/src/test/common/platform/filesystem.functional.test.ts @@ -209,31 +209,6 @@ suite('FileSystem - raw', () => { fileSystem.statSync(DOES_NOT_EXIST); }).to.throw(); }); - - test('ignores errors from getFileType()', async function() { - if (WINDOWS) { - // tslint:disable-next-line:no-invalid-this - this.skip(); - } - const dirname = await fix.createDirectory('x/y/z'); - const file1 = await fix.createFile('x/y/z/__init__.py', ''); - const file2 = await fix.createFile('x/y/z/spam.py', '...'); - const file3 = await fix.createFile('x/y/z/eggs.py', '...'); - await fs.chmod(dirname, 0o400); - - let entries: [string, FileType][]; - try { - entries = await fileSystem.listdir(dirname); - } finally { - await fs.chmod(dirname, 0o755); - } - - expect(entries.sort()).to.deep.equal([ - [file1, FileType.Unknown], - [file3, FileType.Unknown], - [file2, FileType.Unknown] - ]); - }); }); suite('readTextSync', () => { diff --git a/src/test/common/platform/filesystem.unit.test.ts b/src/test/common/platform/filesystem.unit.test.ts index e903b95b151e..ed7fba870a7f 100644 --- a/src/test/common/platform/filesystem.unit.test.ts +++ b/src/test/common/platform/filesystem.unit.test.ts @@ -678,38 +678,6 @@ suite('Raw FileSystem', () => { await expect(promise).to.eventually.be.rejected; verifyAll(); }); - - test('ignores errors from getFileType()', async () => { - const dirname = 'x/y/z'; - const names = [ - // These match the items in "expected". - '__init__.py', - 'spam.py', - 'eggs.py' - ]; - const expected: [string, FileType][] = [ - ['x/y/z/__init__.py', FileType.File], - ['x/y/z/spam.py', FileType.File], - ['x/y/z/eggs.py', FileType.Unknown] - ]; - raw.setup(r => r.readdir(dirname)) // expect the specific filename - .returns(() => Promise.resolve(names)); - names.forEach((name, i) => { - const [filename, filetype] = expected[i]; - raw.setup(r => r.join(dirname, name)) // expect the specific filename - .returns(() => filename); - if (filetype === FileType.Unknown) { - raw.setup(r => r.lstat(filename)) // expect the specific filename - .throws(new Error('oops!')); - } else { - setupForFileType(filename, filetype); - } - }); - - const entries = await filesystem.listdir(dirname); - - expect(entries.sort()).to.deep.equal(expected.sort()); - }); }); suite('statSync', () => { diff --git a/src/test/datascience/jupyter/interpreter/jupyterInterpreterDependencyService.unit.test.ts b/src/test/datascience/jupyter/interpreter/jupyterInterpreterDependencyService.unit.test.ts index 33d38de834c4..fc5ff3e1bd9c 100644 --- a/src/test/datascience/jupyter/interpreter/jupyterInterpreterDependencyService.unit.test.ts +++ b/src/test/datascience/jupyter/interpreter/jupyterInterpreterDependencyService.unit.test.ts @@ -20,7 +20,6 @@ import { JupyterInterpreterDependencyService } from '../../../../client/datascience/jupyter/interpreter/jupyterInterpreterDependencyService'; import { IJupyterCommand, IJupyterCommandFactory } from '../../../../client/datascience/types'; -import { IJupyterCommand, IJupyterCommandFactory } from '../../../../client/datascience/types'; import { InterpreterType, PythonInterpreter } from '../../../../client/interpreter/contracts'; // tslint:disable: max-func-body-length no-any From 1b50305bd357a452f3b98683f08a5cfc12ea362c Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Fri, 21 Feb 2020 13:15:41 -0800 Subject: [PATCH 30/30] Some more text fixes --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0ab79d9d231..041a92163fde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -256,7 +256,7 @@ part of! 1. Update Chinese (Traditional) translation. (thanks [pan93412](https://github.com/pan93412)) ([#9548](https://github.com/Microsoft/vscode-python/issues/9548)) -1. Look for Conda interpreters in '~/opt/_conda_/' directory as well. +1. Look for Conda interpreters in `~/opt/*conda*/` directory as well. ([#9701](https://github.com/Microsoft/vscode-python/issues/9701)) ### Fixes