From 8c4449023bd44af94ab0a5e3bebb22c00d76e64f Mon Sep 17 00:00:00 2001 From: Ian Huff Date: Thu, 17 Sep 2020 13:43:08 -0700 Subject: [PATCH 1/9] Port ipykernel install fix to release (#13975) * Fix installing ipykernel into interpreters for raw kernel (#13959) * update news Co-authored-by: Ian Huff --- CHANGELOG.md | 2 + package.nls.json | 3 +- src/client/common/utils/localize.ts | 4 ++ .../jupyter/kernels/kernelSelector.ts | 29 +++++++++++++- .../kernel-launcher/kernelFinder.ts | 38 ++----------------- .../kernels/kernelSelector.unit.test.ts | 5 ++- .../datascience/kernelFinder.unit.test.ts | 8 +--- 7 files changed, 45 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f89e1e35e763..3a6881c00fdb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,8 @@ ([#13612](https://github.com/Microsoft/vscode-python/issues/13612)) 1. Fix the behavior of the 'python.showStartPage' setting. ([#13706](https://github.com/Microsoft/vscode-python/issues/13706)) +1. Correctly install ipykernel when launching from an interpreter. + ([#13956](https://github.com/Microsoft/vscode-python/issues/13956)) ### Code Health diff --git a/package.nls.json b/package.nls.json index ec6378814166..16a537b3a669 100644 --- a/package.nls.json +++ b/package.nls.json @@ -595,5 +595,6 @@ "DataScience.interactiveWindowModeBannerTitle": "Do you want to open a new Python Interactive window for this file? [More Information](command:workbench.action.openSettings?%5B%22python.dataScience.interactiveWindowMode%22%5D).", "DataScience.interactiveWindowModeBannerSwitchYes": "Yes", "DataScience.interactiveWindowModeBannerSwitchAlways": "Always", - "DataScience.interactiveWindowModeBannerSwitchNo": "No" + "DataScience.interactiveWindowModeBannerSwitchNo": "No", + "DataScience.ipykernelNotInstalled": "IPyKernel not installed into interpreter {0}" } diff --git a/src/client/common/utils/localize.ts b/src/client/common/utils/localize.ts index 8207de65015f..4a4981f8ae63 100644 --- a/src/client/common/utils/localize.ts +++ b/src/client/common/utils/localize.ts @@ -1116,6 +1116,10 @@ export namespace DataScience { ); export const connected = localize('DataScience.connected', 'Connected'); export const disconnected = localize('DataScience.disconnected', 'Disconnected'); + export const ipykernelNotInstalled = localize( + 'DataScience.ipykernelNotInstalled', + 'IPyKernel not installed into interpreter {0}' + ); } export namespace StartPage { diff --git a/src/client/datascience/jupyter/kernels/kernelSelector.ts b/src/client/datascience/jupyter/kernels/kernelSelector.ts index d2623d2df616..e398ded46d5f 100644 --- a/src/client/datascience/jupyter/kernels/kernelSelector.ts +++ b/src/client/datascience/jupyter/kernels/kernelSelector.ts @@ -27,7 +27,8 @@ import { IJupyterSessionManagerFactory, IKernelDependencyService, INotebookMetadataLive, - INotebookProviderConnection + INotebookProviderConnection, + KernelInterpreterDependencyResponse } from '../../types'; import { createDefaultKernelSpec, getDisplayNameOrNameOfKernelConnection } from './helpers'; import { KernelSelectionProvider } from './kernelSelections'; @@ -504,6 +505,8 @@ export class KernelSelector implements IKernelSelectionUsage { if (!kernelSpec && !activeInterpreter) { return; } else if (!kernelSpec && activeInterpreter) { + await this.installDependenciesIntoInterpreter(activeInterpreter, ignoreDependencyCheck, cancelToken); + // Return current interpreter. return { kind: 'startUsingPythonInterpreter', @@ -512,6 +515,11 @@ export class KernelSelector implements IKernelSelectionUsage { } else if (kernelSpec) { // Locate the interpreter that matches our kernelspec const interpreter = await this.kernelService.findMatchingInterpreter(kernelSpec, cancelToken); + + if (interpreter) { + await this.installDependenciesIntoInterpreter(interpreter, ignoreDependencyCheck, cancelToken); + } + return { kind: 'startUsingKernelSpec', kernelSpec, interpreter }; } } @@ -545,6 +553,25 @@ export class KernelSelector implements IKernelSelectionUsage { return { kernelSpec, interpreter, kind: 'startUsingPythonInterpreter' }; } + // If we need to install our dependencies now (for non-native scenarios) + // then install ipykernel into the interpreter or throw error + private async installDependenciesIntoInterpreter( + interpreter: PythonEnvironment, + ignoreDependencyCheck?: boolean, + cancelToken?: CancellationToken + ) { + if (!ignoreDependencyCheck) { + if ( + (await this.kernelDependencyService.installMissingDependencies(interpreter, cancelToken)) !== + KernelInterpreterDependencyResponse.ok + ) { + throw new Error( + localize.DataScience.ipykernelNotInstalled().format(interpreter.displayName || interpreter.path) + ); + } + } + } + /** * Use the provided interpreter as a kernel. * If `displayNameOfKernelNotFound` is provided, then display a message indicating we're using the `current interpreter`. diff --git a/src/client/datascience/kernel-launcher/kernelFinder.ts b/src/client/datascience/kernel-launcher/kernelFinder.ts index 4958ea42216d..5315c09caf05 100644 --- a/src/client/datascience/kernel-launcher/kernelFinder.ts +++ b/src/client/datascience/kernel-launcher/kernelFinder.ts @@ -5,13 +5,12 @@ import type { nbformat } from '@jupyterlab/coreutils'; import { inject, injectable, named } from 'inversify'; import * as path from 'path'; -import { CancellationToken, CancellationTokenSource } from 'vscode'; +import { CancellationToken } from 'vscode'; import { IWorkspaceService } from '../../common/application/types'; -import { wrapCancellationTokens } from '../../common/cancellation'; import { traceError, traceInfo } from '../../common/logger'; import { IPlatformService } from '../../common/platform/types'; import { IPythonExecutionFactory } from '../../common/process/types'; -import { IExtensionContext, IInstaller, InstallerResponse, IPathUtils, Product, Resource } from '../../common/types'; +import { IExtensionContext, IPathUtils, Resource } from '../../common/types'; import { IEnvironmentVariablesProvider } from '../../common/variables/types'; import { IInterpreterLocatorService, IInterpreterService, KNOWN_PATH_SERVICE } from '../../interpreter/contracts'; import { captureTelemetry } from '../../telemetry'; @@ -20,7 +19,6 @@ import { Telemetry } from '../constants'; import { defaultKernelSpecName } from '../jupyter/kernels/helpers'; import { JupyterKernelSpec } from '../jupyter/kernels/jupyterKernelSpec'; import { IDataScienceFileSystem, IJupyterKernelSpec } from '../types'; -import { getKernelInterpreter } from './helpers'; import { IKernelFinder } from './types'; // tslint:disable-next-line:no-require-imports no-var-requires const flatten = require('lodash/flatten') as typeof import('lodash/flatten'); @@ -56,7 +54,6 @@ export class KernelFinder implements IKernelFinder { @inject(IPlatformService) private platformService: IPlatformService, @inject(IDataScienceFileSystem) private fs: IDataScienceFileSystem, @inject(IPathUtils) private readonly pathUtils: IPathUtils, - @inject(IInstaller) private installer: IInstaller, @inject(IExtensionContext) private readonly context: IExtensionContext, @inject(IWorkspaceService) private readonly workspaceService: IWorkspaceService, @inject(IPythonExecutionFactory) private readonly exeFactory: IPythonExecutionFactory, @@ -65,9 +62,7 @@ export class KernelFinder implements IKernelFinder { @captureTelemetry(Telemetry.KernelFinderPerf) public async findKernelSpec( resource: Resource, - kernelSpecMetadata?: nbformat.IKernelspecMetadata, - cancelToken?: CancellationToken, - ignoreDependencyCheck?: boolean + kernelSpecMetadata?: nbformat.IKernelspecMetadata ): Promise { await this.readCache(); let foundKernel: IJupyterKernelSpec | undefined; @@ -108,8 +103,7 @@ export class KernelFinder implements IKernelFinder { this.writeCache().ignoreErrors(); - // Verify that ipykernel is installed into the given kernelspec interpreter - return ignoreDependencyCheck || !foundKernel ? foundKernel : this.verifyIpyKernel(foundKernel, cancelToken); + return foundKernel; } // Search all our local file system locations for installed kernel specs and return them @@ -318,30 +312,6 @@ export class KernelFinder implements IKernelFinder { return flatten(fullPathResults); } - // For the given kernelspec return back the kernelspec with ipykernel installed into it or error - private async verifyIpyKernel( - kernelSpec: IJupyterKernelSpec, - cancelToken?: CancellationToken - ): Promise { - const interpreter = await getKernelInterpreter(kernelSpec, this.interpreterService); - - if (await this.installer.isInstalled(Product.ipykernel, interpreter)) { - return kernelSpec; - } else { - const token = new CancellationTokenSource(); - const response = await this.installer.promptToInstall( - Product.ipykernel, - interpreter, - wrapCancellationTokens(cancelToken, token.token) - ); - if (response === InstallerResponse.Installed) { - return kernelSpec; - } - } - - throw new Error(`IPyKernel not installed into interpreter ${interpreter.displayName}`); - } - private async getKernelSpecFromActiveInterpreter( kernelName: string, resource: Resource diff --git a/src/test/datascience/jupyter/kernels/kernelSelector.unit.test.ts b/src/test/datascience/jupyter/kernels/kernelSelector.unit.test.ts index 515e6c4984de..2b15157b520b 100644 --- a/src/test/datascience/jupyter/kernels/kernelSelector.unit.test.ts +++ b/src/test/datascience/jupyter/kernels/kernelSelector.unit.test.ts @@ -31,7 +31,7 @@ import { LiveKernelModel } from '../../../../client/datascience/jupyter/kernels/types'; import { IKernelFinder } from '../../../../client/datascience/kernel-launcher/types'; -import { IJupyterSessionManager } from '../../../../client/datascience/types'; +import { IJupyterSessionManager, KernelInterpreterDependencyResponse } from '../../../../client/datascience/types'; import { IInterpreterService } from '../../../../client/interpreter/contracts'; import { InterpreterService } from '../../../../client/interpreter/interpreterService'; import { EnvironmentType, PythonEnvironment } from '../../../../client/pythonEnvironments/info'; @@ -72,6 +72,9 @@ suite('DataScience - KernelSelector', () => { kernelSelectionProvider = mock(KernelSelectionProvider); appShell = mock(ApplicationShell); dependencyService = mock(KernelDependencyService); + when(dependencyService.installMissingDependencies(anything(), anything())).thenResolve( + KernelInterpreterDependencyResponse.ok + ); interpreterService = mock(InterpreterService); kernelFinder = mock(); const jupyterSessionManagerFactory = mock(JupyterSessionManagerFactory); diff --git a/src/test/datascience/kernelFinder.unit.test.ts b/src/test/datascience/kernelFinder.unit.test.ts index 696864406153..bf37540a375c 100644 --- a/src/test/datascience/kernelFinder.unit.test.ts +++ b/src/test/datascience/kernelFinder.unit.test.ts @@ -11,7 +11,7 @@ import { Uri } from 'vscode'; import { IWorkspaceService } from '../../client/common/application/types'; import { IPlatformService } from '../../client/common/platform/types'; import { PythonExecutionFactory } from '../../client/common/process/pythonExecutionFactory'; -import { IExtensionContext, IInstaller, IPathUtils, Resource } from '../../client/common/types'; +import { IExtensionContext, IPathUtils, Resource } from '../../client/common/types'; import { Architecture } from '../../client/common/utils/platform'; import { IEnvironmentVariablesProvider } from '../../client/common/variables/types'; import { defaultKernelSpecName } from '../../client/datascience/jupyter/kernels/helpers'; @@ -30,7 +30,6 @@ suite('Kernel Finder', () => { let pathUtils: typemoq.IMock; let context: typemoq.IMock; let envVarsProvider: typemoq.IMock; - let installer: IInstaller; let workspaceService: IWorkspaceService; let kernelFinder: IKernelFinder; let activeInterpreter: PythonEnvironment; @@ -83,9 +82,6 @@ suite('Kernel Finder', () => { context.setup((c) => c.globalStoragePath).returns(() => './'); fileSystem = typemoq.Mock.ofType(); - installer = mock(); - when(installer.isInstalled(anything(), anything())).thenResolve(true); - platformService = typemoq.Mock.ofType(); platformService.setup((ps) => ps.isWindows).returns(() => true); platformService.setup((ps) => ps.isMac).returns(() => true); @@ -325,7 +321,6 @@ suite('Kernel Finder', () => { platformService.object, fileSystem.object, pathUtils.object, - instance(installer), context.object, instance(workspaceService), instance(executionFactory), @@ -408,7 +403,6 @@ suite('Kernel Finder', () => { platformService.object, fileSystem.object, pathUtils.object, - instance(installer), context.object, instance(workspaceService), instance(executionFactory), From b92203aae441d1b264a23ed1db584dc698f0c643 Mon Sep 17 00:00:00 2001 From: Rich Chiodo Date: Thu, 17 Sep 2020 14:40:12 -0700 Subject: [PATCH 2/9] Merge in changes to release (#13976) * Up release version for new release (#13928) * Up release version * Update changelog * Update changelog * Workaround test issue (#13930) * Try different version of VS code in release * Change to make it use the actual variable * Use a real version * More tests failing with gpu error (#13935) * Try different version of VS code in release * Change to make it use the actual variable * Use a real version * Two more version changes * Fix kernel and server name missing in certain situations (#13974) * Fix kernel name and server name * Fixup server name for remote situations * Add some functional tests * Add news entry * Delete news file --- CHANGELOG.md | 5 ++ build/ci/templates/globals.yml | 1 + .../interactive-common/interactiveBase.ts | 80 ++++++++++++------- .../interactive-ipynb/nativeEditor.ts | 4 +- .../datascience/jupyter/kernels/helpers.ts | 7 +- .../history-react/interactivePanel.tsx | 3 +- .../interactive-common/jupyterInfo.tsx | 42 +--------- .../interactive-common/mainState.ts | 8 +- .../redux/reducers/kernel.ts | 4 +- .../interactive-common/redux/store.ts | 4 +- src/datascience-ui/native-editor/toolbar.tsx | 1 - .../interactivePanel.functional.test.tsx | 4 +- .../nativeEditor.functional.test.tsx | 9 ++- .../nativeEditor.toolbar.functional.test.tsx | 8 +- src/test/datascience/testHelpers.tsx | 9 +++ src/test/debuggerTest.ts | 3 +- src/test/multiRootTest.ts | 4 +- src/test/standardTest.ts | 4 +- 18 files changed, 108 insertions(+), 92 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a6881c00fdb..cae1f6150600 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -84,6 +84,11 @@ ([#13729](https://github.com/Microsoft/vscode-python/issues/13729)) 1. Fix nighly failure with beakerx. ([#13734](https://github.com/Microsoft/vscode-python/issues/13734)) +## 2020.8.6 (15 September 2020) + +### Fixes + +1. Workaround problem caused by https://github.com/microsoft/vscode/issues/106547 ### Thanks diff --git a/build/ci/templates/globals.yml b/build/ci/templates/globals.yml index 03457023e99e..98bd51685dd0 100644 --- a/build/ci/templates/globals.yml +++ b/build/ci/templates/globals.yml @@ -11,3 +11,4 @@ variables: npm_config_cache: $(Pipeline.Workspace)/.npm vmImageMacOS: 'macOS-10.15' TS_NODE_FILES: true # Temporarily enabled to allow using types from vscode.proposed.d.ts from ts-node (for tests). + VSC_PYTHON_CI_TEST_VSC_CHANNEL: '1.48.0' # Enforce this until https://github.com/microsoft/vscode-test/issues/73 is fixed diff --git a/src/client/datascience/interactive-common/interactiveBase.ts b/src/client/datascience/interactive-common/interactiveBase.ts index 1290190964d3..5e0c1d11e16c 100644 --- a/src/client/datascience/interactive-common/interactiveBase.ts +++ b/src/client/datascience/interactive-common/interactiveBase.ts @@ -47,7 +47,7 @@ import { captureTelemetry, sendTelemetryEvent } from '../../telemetry'; import { generateCellRangesFromDocument } from '../cellFactory'; import { CellMatcher } from '../cellMatcher'; import { addToUriList, translateKernelLanguageToMonaco } from '../common'; -import { Commands, Identifiers, Telemetry } from '../constants'; +import { Commands, Identifiers, Settings, Telemetry } from '../constants'; import { ColumnWarningSize, IDataViewerFactory } from '../data-viewing/types'; import { IAddedSysInfo, @@ -865,9 +865,54 @@ export abstract class InteractiveBase extends WebviewPanelHost { + // If we don't have a server connection, make one if remote. We need the remote connection in order + // to compute the display name. However only do this if the user is allowing auto start. + if ( + !serverConnection && + this.configService.getSettings(this.owningResource).datascience.jupyterServerURI !== + Settings.JupyterServerLocalLaunch && + !this.configService.getSettings(this.owningResource).datascience.disableJupyterAutoStart + ) { + serverConnection = await this.notebookProvider.connect({ disableUI: true }); + } + + let displayName = + serverConnection?.displayName || + (!serverConnection?.localLaunch ? serverConnection?.url : undefined) || + (this.configService.getSettings().datascience.jupyterServerURI === Settings.JupyterServerLocalLaunch + ? localize.DataScience.localJupyterServer() + : localize.DataScience.serverNotStarted()); + + if (serverConnection) { + // Determine the connection URI of the connected server to display + if (serverConnection.localLaunch) { + displayName = localize.DataScience.localJupyterServer(); + } else { + // Log this remote URI into our MRU list + addToUriList( + this.globalStorage, + !isNil(serverConnection.url) ? serverConnection.url : serverConnection.displayName, + Date.now(), + serverConnection.displayName + ); + } + } + + return displayName; + } + private combineData( oldData: nbformat.ICodeCell | nbformat.IRawCell | nbformat.IMarkdownCell | undefined, cell: ICell @@ -1154,27 +1199,6 @@ export abstract class InteractiveBase extends WebviewPanelHost { const statusChangeHandler = async (status: ServerStatus) => { const connectionMetadata = notebook.getKernelConnection(); @@ -1182,8 +1206,8 @@ export abstract class InteractiveBase extends WebviewPanelHost } private renderKernelSelection() { - if (this.props.kernel.localizedUri === getLocString('DataScience.localJupyterServer', 'local')) { + if (this.props.kernel.serverName === getLocString('DataScience.localJupyterServer', 'local')) { return; } @@ -235,7 +235,6 @@ ${buildSettingsCss(this.props.settings)}`} selectServer={this.props.selectServer} selectKernel={this.props.selectKernel} shouldShowTrustMessage={false} - settings={this.props.settings} /> ); } diff --git a/src/datascience-ui/interactive-common/jupyterInfo.tsx b/src/datascience-ui/interactive-common/jupyterInfo.tsx index ec94902757f3..62d16d111053 100644 --- a/src/datascience-ui/interactive-common/jupyterInfo.tsx +++ b/src/datascience-ui/interactive-common/jupyterInfo.tsx @@ -1,9 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. 'use strict'; -import { isEmpty, isNil } from 'lodash'; import * as React from 'react'; -import { IDataScienceExtraSettings } from '../../client/datascience/types'; import { Image, ImageName } from '../react-common/image'; import { getLocString } from '../react-common/locReactSide'; import { IFont, IServerState, ServerStatus } from './mainState'; @@ -16,7 +14,6 @@ export interface IJupyterInfoProps { kernel: IServerState; isNotebookTrusted?: boolean; shouldShowTrustMessage: boolean; - settings?: IDataScienceExtraSettings | undefined; selectServer(): void; launchNotebookTrustPrompt?(): void; // Native editor-specific selectKernel(): void; @@ -37,17 +34,10 @@ export class JupyterInfo extends React.Component { } public render() { - let jupyterServerDisplayName: string = this.props.kernel.localizedUri; - if (!isNil(this.props.settings) && isEmpty(jupyterServerDisplayName)) { - const jupyterServerUriSetting: string = this.props.settings.jupyterServerURI; - if (!isEmpty(jupyterServerUriSetting) && this.isUriOfComputeInstance(jupyterServerUriSetting)) { - jupyterServerDisplayName = this.getComputeInstanceNameFromId(jupyterServerUriSetting); - } - } - + const jupyterServerDisplayName: string = this.props.kernel.serverName; const serverTextSize = getLocString('DataScience.jupyterServer', 'Jupyter Server').length + jupyterServerDisplayName.length + 4; // plus 4 for the icon - const displayNameTextSize = this.props.kernel.displayName.length + this.props.kernel.jupyterServerStatus.length; + const displayNameTextSize = this.props.kernel.kernelName.length + this.props.kernel.jupyterServerStatus.length; const dynamicFont: React.CSSProperties = { fontSize: 'var(--vscode-font-size)', // Use the same font and size as the menu fontFamily: 'var(--vscode-font-family)', @@ -98,11 +88,11 @@ export class JupyterInfo extends React.Component { role="button" aria-disabled={ariaDisabled} > - {this.props.kernel.displayName}: {this.props.kernel.jupyterServerStatus} + {this.props.kernel.kernelName}: {this.props.kernel.jupyterServerStatus} ); } else { - const displayName = this.props.kernel.displayName ?? getLocString('DataScience.noKernel', 'No Kernel'); + const displayName = this.props.kernel.kernelName ?? getLocString('DataScience.noKernel', 'No Kernel'); return (
{displayName}: {this.props.kernel.jupyterServerStatus} @@ -138,30 +128,6 @@ export class JupyterInfo extends React.Component { : getLocString('DataScience.connected', 'Connected'); } - private isUriOfComputeInstance(uri: string): boolean { - try { - const parsedUrl: URL = new URL(uri); - return parsedUrl.searchParams.get('id') === 'azureml_compute_instances'; - } catch (e) { - return false; - } - } - - private getComputeInstanceNameFromId(id: string | undefined): string { - if (isNil(id)) { - return ''; - } - - const res: string[] | null = id.match( - /\/providers\/Microsoft.MachineLearningServices\/workspaces\/[^\/]+\/computes\/([^\/]+)(\/)?/ - ); - if (isNil(res) || res.length < 2) { - return ''; - } - - return res[1]; - } - private selectServer(): void { this.props.selectServer(); } diff --git a/src/datascience-ui/interactive-common/mainState.ts b/src/datascience-ui/interactive-common/mainState.ts index 250831ac5c3a..f84713746568 100644 --- a/src/datascience-ui/interactive-common/mainState.ts +++ b/src/datascience-ui/interactive-common/mainState.ts @@ -134,8 +134,8 @@ export interface IFont { export interface IServerState { jupyterServerStatus: ServerStatus; - localizedUri: string; - displayName: string; + serverName: string; + kernelName: string; language: string; } @@ -192,8 +192,8 @@ export function generateTestState(filePath: string = '', editable: boolean = fal loaded: false, testMode: true, kernel: { - localizedUri: 'No Kernel', - displayName: 'Python', + serverName: '', + kernelName: 'Python', jupyterServerStatus: ServerStatus.NotStarted, language: PYTHON_LANGUAGE }, diff --git a/src/datascience-ui/interactive-common/redux/reducers/kernel.ts b/src/datascience-ui/interactive-common/redux/reducers/kernel.ts index 7f8f2a8ad95c..c4f3f1de1387 100644 --- a/src/datascience-ui/interactive-common/redux/reducers/kernel.ts +++ b/src/datascience-ui/interactive-common/redux/reducers/kernel.ts @@ -40,9 +40,9 @@ export namespace Kernel { return { ...arg.prevState, kernel: { - localizedUri: arg.payload.data.localizedUri, + serverName: arg.payload.data.serverName, jupyterServerStatus: arg.payload.data.jupyterServerStatus, - displayName: arg.payload.data.displayName, + kernelName: arg.payload.data.kernelName, language: arg.payload.data.language } }; diff --git a/src/datascience-ui/interactive-common/redux/store.ts b/src/datascience-ui/interactive-common/redux/store.ts index 345be932aa1f..7ee0e58627ee 100644 --- a/src/datascience-ui/interactive-common/redux/store.ts +++ b/src/datascience-ui/interactive-common/redux/store.ts @@ -68,8 +68,8 @@ function generateDefaultState( monacoReady: testMode, // When testing, monaco starts out ready loaded: false, kernel: { - displayName: getLocString('DataScience.noKernel', 'No Kernel'), - localizedUri: getLocString('DataScience.serverNotStarted', 'Not Started'), + kernelName: getLocString('DataScience.noKernel', 'No Kernel'), + serverName: getLocString('DataScience.serverNotStarted', 'Not Started'), jupyterServerStatus: ServerStatus.NotStarted, language: PYTHON_LANGUAGE }, diff --git a/src/datascience-ui/native-editor/toolbar.tsx b/src/datascience-ui/native-editor/toolbar.tsx index 63ffab3abf18..ecba9b191e02 100644 --- a/src/datascience-ui/native-editor/toolbar.tsx +++ b/src/datascience-ui/native-editor/toolbar.tsx @@ -268,7 +268,6 @@ export class Toolbar extends React.PureComponent { shouldShowTrustMessage={true} isNotebookTrusted={this.props.isNotebookTrusted} launchNotebookTrustPrompt={launchNotebookTrustPrompt} - settings={this.props.settings} />
diff --git a/src/test/datascience/interactivePanel.functional.test.tsx b/src/test/datascience/interactivePanel.functional.test.tsx index 0ef60f1e23cd..8f2e1179bc41 100644 --- a/src/test/datascience/interactivePanel.functional.test.tsx +++ b/src/test/datascience/interactivePanel.functional.test.tsx @@ -76,9 +76,9 @@ suite('DataScience Interactive Panel', () => { interruptKernel: noopAny, isAtBottom: false, kernel: { - displayName: '', + kernelName: '', jupyterServerStatus: ServerStatus.Busy, - localizedUri: '', + serverName: '', language: PYTHON_LANGUAGE }, knownDark: false, diff --git a/src/test/datascience/nativeEditor.functional.test.tsx b/src/test/datascience/nativeEditor.functional.test.tsx index 041b71198905..f2ec387bd364 100644 --- a/src/test/datascience/nativeEditor.functional.test.tsx +++ b/src/test/datascience/nativeEditor.functional.test.tsx @@ -83,7 +83,8 @@ import { typeCode, verifyCellIndex, verifyCellSource, - verifyHtmlOnCell + verifyHtmlOnCell, + verifyServerStatus } from './testHelpers'; import { ITestNativeEditorProvider } from './testNativeEditorProvider'; @@ -713,6 +714,8 @@ df.head()`; // Make sure it has a server assert.ok(editor.editor.notebook, 'Notebook did not start with a server'); + // Make sure it does have a name though + verifyServerStatus(editor.mount.wrapper, 'local'); } else { context.skip(); } @@ -721,6 +724,7 @@ df.head()`; runMountedTest('Server load skipped', async (context) => { if (ioc.mockJupyter) { ioc.getSettings().datascience.disableJupyterAutoStart = true; + ioc.getSettings().datascience.jupyterServerURI = 'https://remotetest'; await ioc.activate(); // Create an editor so something is listening to messages @@ -731,6 +735,9 @@ df.head()`; // Make sure it does not have a server assert.notOk(editor.editor.notebook, 'Notebook should not start with a server'); + + // Make sure it does have a name though + verifyServerStatus(editor.mount.wrapper, 'Not Started'); } else { context.skip(); } diff --git a/src/test/datascience/nativeEditor.toolbar.functional.test.tsx b/src/test/datascience/nativeEditor.toolbar.functional.test.tsx index b1e86f026daa..e51a44826a41 100644 --- a/src/test/datascience/nativeEditor.toolbar.functional.test.tsx +++ b/src/test/datascience/nativeEditor.toolbar.functional.test.tsx @@ -45,9 +45,9 @@ suite('DataScience Native Toolbar', () => { font: { family: '', size: 1 }, interruptKernel: sinon.stub(), kernel: { - displayName: '', + kernelName: '', jupyterServerStatus: ServerStatus.Busy, - localizedUri: '', + serverName: '', language: PYTHON_LANGUAGE }, restartKernel: sinon.stub(), @@ -245,9 +245,9 @@ suite('DataScience Native Toolbar', () => { font: { family: '', size: 1 }, interruptKernel: sinon.stub(), kernel: { - displayName: '', + kernelName: '', jupyterServerStatus: ServerStatus.Busy, - localizedUri: '', + serverName: '', language: PYTHON_LANGUAGE }, restartKernel: sinon.stub(), diff --git a/src/test/datascience/testHelpers.tsx b/src/test/datascience/testHelpers.tsx index d8c07d1236b6..88798f4334f9 100644 --- a/src/test/datascience/testHelpers.tsx +++ b/src/test/datascience/testHelpers.tsx @@ -221,6 +221,15 @@ export function verifyCellSource( assert.deepStrictEqual(inst.state.model?.getValue(), source, 'Source does not match on cell'); } +export function verifyServerStatus(wrapper: ReactWrapper, React.Component>, statusText: string) { + wrapper.update(); + + const foundResult = wrapper.find('div.kernel-status-server'); + assert.ok(foundResult.length >= 1, "Didn't find server status"); + const html = foundResult.html(); + assert.ok(html.includes(statusText), `${statusText} not found in server status`); +} + export function verifyHtmlOnCell( wrapper: ReactWrapper, React.Component>, cellType: 'NativeCell' | 'InteractiveCell', diff --git a/src/test/debuggerTest.ts b/src/test/debuggerTest.ts index c7fc3e1058d1..3720b0e662ed 100644 --- a/src/test/debuggerTest.ts +++ b/src/test/debuggerTest.ts @@ -10,6 +10,7 @@ import { EXTENSION_ROOT_DIR_FOR_TESTS } from './constants'; const workspacePath = path.join(__dirname, '..', '..', 'src', 'testMultiRootWkspc', 'multi.code-workspace'); process.env.IS_CI_SERVER_TEST_DEBUGGER = '1'; process.env.VSC_PYTHON_CI_TEST = '1'; +const channel = process.env.VSC_PYTHON_CI_TEST_VSC_CHANNEL || 'stable'; function start() { console.log('*'.repeat(100)); @@ -18,7 +19,7 @@ function start() { extensionDevelopmentPath: EXTENSION_ROOT_DIR_FOR_TESTS, extensionTestsPath: path.join(EXTENSION_ROOT_DIR_FOR_TESTS, 'out', 'test', 'index'), launchArgs: [workspacePath], - version: 'stable', + version: channel, extensionTestsEnv: { ...process.env, UITEST_DISABLE_INSIDERS: '1' } }).catch((ex) => { console.error('End Debugger tests (with errors)', ex); diff --git a/src/test/multiRootTest.ts b/src/test/multiRootTest.ts index 5859708a8e99..04631bd1b2ca 100644 --- a/src/test/multiRootTest.ts +++ b/src/test/multiRootTest.ts @@ -11,6 +11,8 @@ process.env.VSC_PYTHON_CI_TEST = '1'; initializeLogger(); +const channel = process.env.VSC_PYTHON_CI_TEST_VSC_CHANNEL || 'stable'; + function start() { console.log('*'.repeat(100)); console.log('Start Multiroot tests'); @@ -18,7 +20,7 @@ function start() { extensionDevelopmentPath: EXTENSION_ROOT_DIR_FOR_TESTS, extensionTestsPath: path.join(EXTENSION_ROOT_DIR_FOR_TESTS, 'out', 'test', 'index'), launchArgs: [workspacePath], - version: 'stable', + version: channel, extensionTestsEnv: { ...process.env, UITEST_DISABLE_INSIDERS: '1' } }).catch((ex) => { console.error('End Multiroot tests (with errors)', ex); diff --git a/src/test/standardTest.ts b/src/test/standardTest.ts index 4a6dd9f2e287..76739ae4b667 100644 --- a/src/test/standardTest.ts +++ b/src/test/standardTest.ts @@ -16,9 +16,7 @@ const extensionDevelopmentPath = process.env.CODE_EXTENSIONS_PATH ? process.env.CODE_EXTENSIONS_PATH : EXTENSION_ROOT_DIR_FOR_TESTS; -const channel = (process.env.VSC_PYTHON_CI_TEST_VSC_CHANNEL || '').toLowerCase().includes('insiders') - ? 'insiders' - : 'stable'; +const channel = process.env.VSC_PYTHON_CI_TEST_VSC_CHANNEL || 'stable'; function start() { console.log('*'.repeat(100)); From 8c4a0ec1ac0bfac255f9664c3a6201a7f2d28c28 Mon Sep 17 00:00:00 2001 From: Rich Chiodo Date: Fri, 18 Sep 2020 12:01:43 -0700 Subject: [PATCH 3/9] Port two fixes to the release branch (#13995) * Disable split views of custom editors (#13985) * Fix backup storage by looking at the options correctly (#13983) * Fix backup storage by looking at the options correctly * Fix backup by being more explicit * Only linux tests are failing. Hopefully fix them * Fixup changelog Co-authored-by: Don Jayamanne --- CHANGELOG.md | 2 + src/client/datascience/export/exportUtil.ts | 4 +- .../nativeEditorProviderOld.ts | 4 +- .../interactive-ipynb/trustCommandHandler.ts | 2 +- .../interactive-window/interactiveWindow.ts | 2 +- .../datascience/notebook/contentProvider.ts | 15 ++-- .../notebook/notebookEditorProvider.ts | 2 +- .../notebookStorage/nativeEditorProvider.ts | 37 +++++---- .../notebookStorage/nativeEditorStorage.ts | 82 ++++++------------- .../notebookStorageProvider.ts | 34 ++------ src/client/datascience/types.ts | 22 ++--- .../datascience/export/exportUtil.test.ts | 2 +- .../nativeEditorStorage.unit.test.ts | 20 ++--- .../datascience/mockCustomEditorService.ts | 2 +- .../notebook/contentProvider.ds.test.ts | 2 +- .../notebook/contentProvider.unit.test.ts | 8 +- 16 files changed, 95 insertions(+), 145 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cae1f6150600..38b5f71f1330 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,8 @@ ([#13706](https://github.com/Microsoft/vscode-python/issues/13706)) 1. Correctly install ipykernel when launching from an interpreter. ([#13956](https://github.com/Microsoft/vscode-python/issues/13956)) +1. Backup on custom editors is being ignored. + ([#13981](https://github.com/Microsoft/vscode-python/issues/13981)) ### Code Health diff --git a/src/client/datascience/export/exportUtil.ts b/src/client/datascience/export/exportUtil.ts index 237b93ff4ca1..9e9f2c9c97c8 100644 --- a/src/client/datascience/export/exportUtil.ts +++ b/src/client/datascience/export/exportUtil.ts @@ -57,7 +57,7 @@ export class ExportUtil { await this.jupyterExporter.exportToFile(cells, tempFile.filePath, false); const newPath = path.join(tempDir.path, '.ipynb'); await this.fs.copyLocal(tempFile.filePath, newPath); - model = await this.notebookStorage.getOrCreateModel(Uri.file(newPath)); + model = await this.notebookStorage.getOrCreateModel({ file: Uri.file(newPath) }); } finally { tempFile.dispose(); tempDir.dispose(); @@ -67,7 +67,7 @@ export class ExportUtil { } public async removeSvgs(source: Uri) { - const model = await this.notebookStorage.getOrCreateModel(source); + const model = await this.notebookStorage.getOrCreateModel({ file: source }); const newCells: ICell[] = []; for (const cell of model.cells) { diff --git a/src/client/datascience/interactive-ipynb/nativeEditorProviderOld.ts b/src/client/datascience/interactive-ipynb/nativeEditorProviderOld.ts index 9d7b37ffcd3d..99a857a61834 100644 --- a/src/client/datascience/interactive-ipynb/nativeEditorProviderOld.ts +++ b/src/client/datascience/interactive-ipynb/nativeEditorProviderOld.ts @@ -299,7 +299,7 @@ export class NativeEditorProviderOld extends NativeEditorProvider { this.activeEditors.set(e.file.fsPath, e); // Remove backup storage - this.loadModel(Uri.file(oldPath)) + this.loadModel({ file: Uri.file(oldPath) }) .then((m) => this.storage.deleteBackup(m)) .ignoreErrors(); } @@ -347,7 +347,7 @@ export class NativeEditorProviderOld extends NativeEditorProvider { * I.e. document is already opened in a VSC Notebook. */ private async isDocumentOpenedInVSCodeNotebook(document: TextDocument): Promise { - const model = await this.loadModel(document.uri); + const model = await this.loadModel({ file: document.uri }); // This is temporary code. return model instanceof VSCodeNotebookModel; } diff --git a/src/client/datascience/interactive-ipynb/trustCommandHandler.ts b/src/client/datascience/interactive-ipynb/trustCommandHandler.ts index 3718379cc804..b325032c8fc4 100644 --- a/src/client/datascience/interactive-ipynb/trustCommandHandler.ts +++ b/src/client/datascience/interactive-ipynb/trustCommandHandler.ts @@ -42,7 +42,7 @@ export class TrustCommandHandler implements IExtensionSingleActivationService { return; } - const model = await this.storageProvider.getOrCreateModel(uri); + const model = await this.storageProvider.getOrCreateModel({ file: uri }); if (model.isTrusted) { return; } diff --git a/src/client/datascience/interactive-window/interactiveWindow.ts b/src/client/datascience/interactive-window/interactiveWindow.ts index fd1b2388a161..3dd40ec874cd 100644 --- a/src/client/datascience/interactive-window/interactiveWindow.ts +++ b/src/client/datascience/interactive-window/interactiveWindow.ts @@ -256,7 +256,7 @@ export class InteractiveWindow extends InteractiveBase implements IInteractiveWi break; case InteractiveWindowMessages.ExportNotebookAs: - this.handleMessage(message, payload, this.exportAs); + this.handleMessage(message, payload, this.exportAs.bind); break; case InteractiveWindowMessages.HasCellResponse: diff --git a/src/client/datascience/notebook/contentProvider.ts b/src/client/datascience/notebook/contentProvider.ts index 12e3e0e9d41f..a94bc091a61c 100644 --- a/src/client/datascience/notebook/contentProvider.ts +++ b/src/client/datascience/notebook/contentProvider.ts @@ -70,9 +70,12 @@ export class NotebookContentProvider implements INotebookContentProvider { }; } // If there's no backup id, then skip loading dirty contents. - const model = await (openContext.backupId - ? this.notebookStorage.getOrCreateModel(uri, undefined, openContext.backupId, true) - : this.notebookStorage.getOrCreateModel(uri, undefined, true, true)); + const model = await this.notebookStorage.getOrCreateModel({ + file: uri, + backupId: openContext.backupId, + isNative: true, + skipLoadingDirtyContents: openContext.backupId === undefined + }); if (!(model instanceof VSCodeNotebookModel)) { throw new Error('Incorrect NotebookModel, expected VSCodeNotebookModel'); } @@ -82,7 +85,7 @@ export class NotebookContentProvider implements INotebookContentProvider { } @captureTelemetry(Telemetry.Save, undefined, true) public async saveNotebook(document: NotebookDocument, cancellation: CancellationToken) { - const model = await this.notebookStorage.getOrCreateModel(document.uri, undefined, undefined, true); + const model = await this.notebookStorage.getOrCreateModel({ file: document.uri, isNative: true }); if (cancellation.isCancellationRequested) { return; } @@ -94,7 +97,7 @@ export class NotebookContentProvider implements INotebookContentProvider { document: NotebookDocument, cancellation: CancellationToken ): Promise { - const model = await this.notebookStorage.getOrCreateModel(document.uri, undefined, undefined, true); + const model = await this.notebookStorage.getOrCreateModel({ file: document.uri, isNative: true }); if (!cancellation.isCancellationRequested) { await this.notebookStorage.saveAs(model, targetResource); } @@ -104,7 +107,7 @@ export class NotebookContentProvider implements INotebookContentProvider { _context: NotebookDocumentBackupContext, cancellation: CancellationToken ): Promise { - const model = await this.notebookStorage.getOrCreateModel(document.uri, undefined, undefined, true); + const model = await this.notebookStorage.getOrCreateModel({ file: document.uri, isNative: true }); const id = this.notebookStorage.generateBackupId(model); await this.notebookStorage.backup(model, cancellation, id); return { diff --git a/src/client/datascience/notebook/notebookEditorProvider.ts b/src/client/datascience/notebook/notebookEditorProvider.ts index 6ed78c1a62fa..1cc4b962ff96 100644 --- a/src/client/datascience/notebook/notebookEditorProvider.ts +++ b/src/client/datascience/notebook/notebookEditorProvider.ts @@ -145,7 +145,7 @@ export class NotebookEditorProvider implements INotebookEditorProvider { return; } const uri = doc.uri; - const model = await this.storage.getOrCreateModel(uri, undefined, undefined, true); + const model = await this.storage.getOrCreateModel({ file: uri, isNative: true }); if (model instanceof VSCodeNotebookModel) { model.associateNotebookDocument(doc); } diff --git a/src/client/datascience/notebookStorage/nativeEditorProvider.ts b/src/client/datascience/notebookStorage/nativeEditorProvider.ts index 5d166c119789..23fcaa04da53 100644 --- a/src/client/datascience/notebookStorage/nativeEditorProvider.ts +++ b/src/client/datascience/notebookStorage/nativeEditorProvider.ts @@ -51,6 +51,7 @@ import { IJupyterDebugger, IJupyterVariableDataProviderFactory, IJupyterVariables, + IModelLoadOptions, INotebookEditor, INotebookEditorProvider, INotebookExporter, @@ -119,7 +120,7 @@ export class NativeEditorProvider implements INotebookEditorProvider, CustomEdit enableFindWidget: true, retainContextWhenHidden: true }, - supportsMultipleEditorsPerDocument: true + supportsMultipleEditorsPerDocument: false }); } @@ -128,22 +129,26 @@ export class NativeEditorProvider implements INotebookEditorProvider, CustomEdit context: CustomDocumentOpenContext, // This has info about backups. right now we use our own data. _cancellation: CancellationToken ): Promise { - const model = await this.loadModel(uri, undefined, context.backupId); + const model = await this.loadModel({ + file: uri, + backupId: context.backupId, + skipLoadingDirtyContents: context.backupId === undefined + }); return { uri, dispose: () => model.dispose() }; } public async saveCustomDocument(document: CustomDocument, cancellation: CancellationToken): Promise { - const model = await this.loadModel(document.uri); + const model = await this.loadModel({ file: document.uri }); return this.storage.save(model, cancellation); } public async saveCustomDocumentAs(document: CustomDocument, targetResource: Uri): Promise { - const model = await this.loadModel(document.uri); + const model = await this.loadModel({ file: document.uri }); return this.storage.saveAs(model, targetResource); } public async revertCustomDocument(document: CustomDocument, cancellation: CancellationToken): Promise { - const model = await this.loadModel(document.uri); + const model = await this.loadModel({ file: document.uri }); return this.storage.revert(model, cancellation); } public async backupCustomDocument( @@ -151,7 +156,7 @@ export class NativeEditorProvider implements INotebookEditorProvider, CustomEdit _context: CustomDocumentBackupContext, cancellation: CancellationToken ): Promise { - const model = await this.loadModel(document.uri); + const model = await this.loadModel({ file: document.uri }); const id = this.storage.generateBackupId(model); await this.storage.backup(model, cancellation, id); return { @@ -167,7 +172,7 @@ export class NativeEditorProvider implements INotebookEditorProvider, CustomEdit public async resolveCustomDocument(document: CustomDocument): Promise { this.customDocuments.set(document.uri.fsPath, document); - await this.loadModel(document.uri); + await this.loadModel({ file: document.uri }); } public async open(file: Uri): Promise { @@ -199,30 +204,26 @@ export class NativeEditorProvider implements INotebookEditorProvider, CustomEdit } @captureTelemetry(Telemetry.CreateNewNotebook, undefined, false) - public async createNew(contents?: string, title?: string): Promise { + public async createNew(possibleContents?: string, title?: string): Promise { // Create a new URI for the dummy file using our root workspace path const uri = this.getNextNewNotebookUri(title); // Set these contents into the storage before the file opens. Make sure not // load from the memento storage though as this is an entirely brand new file. - await this.loadModel(uri, contents, true); + await this.loadModel({ file: uri, possibleContents, skipLoadingDirtyContents: true }); return this.open(uri); } - public async loadModel(file: Uri, contents?: string, skipDirtyContents?: boolean): Promise; - // tslint:disable-next-line: unified-signatures - public async loadModel(file: Uri, contents?: string, backupId?: string): Promise; - // tslint:disable-next-line: no-any - public async loadModel(file: Uri, contents?: string, options?: any): Promise { + public async loadModel(options: IModelLoadOptions): Promise { // Get the model that may match this file - let model = [...this.models.values()].find((m) => this.fs.arePathsSame(m.file, file)); + let model = [...this.models.values()].find((m) => this.fs.arePathsSame(m.file, options.file)); if (!model) { // Every time we load a new untitled file, up the counter past the max value for this counter - this.untitledCounter = getNextUntitledCounter(file, this.untitledCounter); + this.untitledCounter = getNextUntitledCounter(options.file, this.untitledCounter); // Load our model from our storage object. - model = await this.storage.getOrCreateModel(file, contents, options); + model = await this.storage.getOrCreateModel(options); // Make sure to listen to events on the model this.trackModel(model); @@ -273,7 +274,7 @@ export class NativeEditorProvider implements INotebookEditorProvider, CustomEdit protected async loadNotebookEditor(resource: Uri, panel?: WebviewPanel) { try { // Get the model - const model = await this.loadModel(resource); + const model = await this.loadModel({ file: resource }); // Load it (should already be visible) return this.createNotebookEditor(model, panel); diff --git a/src/client/datascience/notebookStorage/nativeEditorStorage.ts b/src/client/datascience/notebookStorage/nativeEditorStorage.ts index 0ca96a90bf9e..f3e71c597de0 100644 --- a/src/client/datascience/notebookStorage/nativeEditorStorage.ts +++ b/src/client/datascience/notebookStorage/nativeEditorStorage.ts @@ -17,6 +17,7 @@ import { CellState, IDataScienceFileSystem, IJupyterExecution, + IModelLoadOptions, INotebookModel, INotebookStorage, ITrustService @@ -75,27 +76,8 @@ export class NativeEditorStorage implements INotebookStorage { public get(_file: Uri): INotebookModel | undefined { return undefined; } - public getOrCreateModel( - file: Uri, - possibleContents?: string, - backupId?: string, - forVSCodeNotebook?: boolean - ): Promise; - public getOrCreateModel( - file: Uri, - possibleContents?: string, - // tslint:disable-next-line: unified-signatures - skipDirtyContents?: boolean, - forVSCodeNotebook?: boolean - ): Promise; - public getOrCreateModel( - file: Uri, - possibleContents?: string, - // tslint:disable-next-line: no-any - options?: any, - forVSCodeNotebook?: boolean - ): Promise { - return this.loadFromFile(file, possibleContents, options, forVSCodeNotebook); + public getOrCreateModel(options: IModelLoadOptions): Promise { + return this.loadFromFile(options); } public async save(model: INotebookModel, _cancellation: CancellationToken): Promise { const contents = model.getContent(); @@ -154,8 +136,8 @@ export class NativeEditorStorage implements INotebookStorage { } public async revert(model: INotebookModel, _cancellation: CancellationToken): Promise { - // Revert to what is in the hot exit file - await this.loadFromFile(model.file); + // Revert to what is in the real file. This is only used for the custom editor + await this.loadFromFile({ file: model.file, skipLoadingDirtyContents: true }); } public async deleteBackup(model: INotebookModel, backupId: string): Promise { @@ -253,54 +235,44 @@ export class NativeEditorStorage implements INotebookStorage { noop(); } } - private loadFromFile( - file: Uri, - possibleContents?: string, - backupId?: string, - forVSCodeNotebook?: boolean - ): Promise; - private loadFromFile( - file: Uri, - possibleContents?: string, - // tslint:disable-next-line: unified-signatures - skipDirtyContents?: boolean, - forVSCodeNotebook?: boolean - ): Promise; - private async loadFromFile( - file: Uri, - possibleContents?: string, - options?: boolean | string, - forVSCodeNotebook?: boolean - ): Promise { + private async loadFromFile(options: IModelLoadOptions): Promise { try { // Attempt to read the contents if a viable file - const contents = NativeEditorStorage.isUntitledFile(file) ? possibleContents : await this.fs.readFile(file); + const contents = NativeEditorStorage.isUntitledFile(options.file) + ? options.possibleContents + : await this.fs.readFile(options.file); - const skipDirtyContents = typeof options === 'boolean' ? options : !!options; - // Use backupId provided, else use static storage key. - const backupId = - typeof options === 'string' ? options : skipDirtyContents ? undefined : this.getStaticStorageKey(file); + // Get backup id from the options if available. + const backupId = options.backupId ? options.backupId : this.getStaticStorageKey(options.file); // If skipping dirty contents, delete the dirty hot exit file now - if (skipDirtyContents) { - await this.clearHotExit(file, backupId); + if (options.skipLoadingDirtyContents) { + await this.clearHotExit(options.file, backupId); } // See if this file was stored in storage prior to shutdown - const dirtyContents = skipDirtyContents ? undefined : await this.getStoredContents(file, backupId); + const dirtyContents = options.skipLoadingDirtyContents + ? undefined + : await this.getStoredContents(options.file, backupId); if (dirtyContents) { // This means we're dirty. Indicate dirty and load from this content - return this.loadContents(file, dirtyContents, true, forVSCodeNotebook); + return this.loadContents(options.file, dirtyContents, true, options.isNative); } else { // Load without setting dirty - return this.loadContents(file, contents, undefined, forVSCodeNotebook); + return this.loadContents(options.file, contents, undefined, options.isNative); } } catch (ex) { // May not exist at this time. Should always have a single cell though - traceError(`Failed to load notebook file ${file.toString()}`, ex); + traceError(`Failed to load notebook file ${options.file.toString()}`, ex); return this.factory.createModel( - { trusted: true, file, cells: [], crypto: this.crypto, globalMemento: this.globalStorage }, - forVSCodeNotebook + { + trusted: true, + file: options.file, + cells: [], + crypto: this.crypto, + globalMemento: this.globalStorage + }, + options.isNative ); } } diff --git a/src/client/datascience/notebookStorage/notebookStorageProvider.ts b/src/client/datascience/notebookStorage/notebookStorageProvider.ts index 4067751614cc..48e28f048c89 100644 --- a/src/client/datascience/notebookStorage/notebookStorageProvider.ts +++ b/src/client/datascience/notebookStorage/notebookStorageProvider.ts @@ -9,7 +9,7 @@ import { CancellationToken } from 'vscode-jsonrpc'; import { IWorkspaceService } from '../../common/application/types'; import { IDisposable, IDisposableRegistry } from '../../common/types'; import { generateNewNotebookUri } from '../common'; -import { INotebookModel, INotebookStorage } from '../types'; +import { IModelLoadOptions, INotebookModel, INotebookStorage } from '../types'; import { getNextUntitledCounter } from './nativeEditorStorage'; import { VSCodeNotebookModel } from './vscNotebookModel'; @@ -66,35 +66,15 @@ export class NotebookStorageProvider implements INotebookStorageProvider { return this.resolvedStorageAndModels.get(file.toString()); } - public getOrCreateModel( - file: Uri, - contents?: string, - backupId?: string, - forVSCodeNotebook?: boolean - ): Promise; - public getOrCreateModel( - file: Uri, - contents?: string, - // tslint:disable-next-line: unified-signatures - skipDirtyContents?: boolean, - forVSCodeNotebook?: boolean - ): Promise; - - public getOrCreateModel( - file: Uri, - contents?: string, - // tslint:disable-next-line: no-any - options?: any, - forVSCodeNotebook?: boolean - ): Promise { - const key = file.toString(); + public getOrCreateModel(options: IModelLoadOptions): Promise { + const key = options.file.toString(); if (!this.storageAndModels.has(key)) { // Every time we load a new untitled file, up the counter past the max value for this counter NotebookStorageProvider.untitledCounter = getNextUntitledCounter( - file, + options.file, NotebookStorageProvider.untitledCounter ); - const promise = this.storage.getOrCreateModel(file, contents, options, forVSCodeNotebook); + const promise = this.storage.getOrCreateModel(options); this.storageAndModels.set(key, promise.then(this.trackModel.bind(this))); } return this.storageAndModels.get(key)!; @@ -105,12 +85,12 @@ export class NotebookStorageProvider implements INotebookStorageProvider { } } - public async createNew(contents?: string, forVSCodeNotebooks?: boolean): Promise { + public async createNew(possibleContents?: string, forVSCodeNotebooks?: boolean): Promise { // Create a new URI for the dummy file using our root workspace path const uri = this.getNextNewNotebookUri(forVSCodeNotebooks); // Always skip loading from the hot exit file. When creating a new file we want a new file. - return this.getOrCreateModel(uri, contents, true, forVSCodeNotebooks); + return this.getOrCreateModel({ file: uri, possibleContents, skipLoadingDirtyContents: true }); } private getNextNewNotebookUri(forVSCodeNotebooks?: boolean): Uri { diff --git a/src/client/datascience/types.ts b/src/client/datascience/types.ts index 3a8b406a24ec..b651af2b7750 100644 --- a/src/client/datascience/types.ts +++ b/src/client/datascience/types.ts @@ -1106,6 +1106,14 @@ export interface INotebookModel { trust(): void; } +export interface IModelLoadOptions { + isNative?: boolean; + file: Uri; + possibleContents?: string; + backupId?: string; + skipLoadingDirtyContents?: boolean; +} + export const INotebookStorage = Symbol('INotebookStorage'); export interface INotebookStorage { @@ -1114,19 +1122,7 @@ export interface INotebookStorage { saveAs(model: INotebookModel, targetResource: Uri): Promise; backup(model: INotebookModel, cancellation: CancellationToken, backupId?: string): Promise; get(file: Uri): INotebookModel | undefined; - getOrCreateModel( - file: Uri, - contents?: string, - backupId?: string, - forVSCodeNotebook?: boolean - ): Promise; - getOrCreateModel( - file: Uri, - contents?: string, - // tslint:disable-next-line: unified-signatures - skipDirtyContents?: boolean, - forVSCodeNotebook?: boolean - ): Promise; + getOrCreateModel(options: IModelLoadOptions): Promise; revert(model: INotebookModel, cancellation: CancellationToken): Promise; deleteBackup(model: INotebookModel, backupId?: string): Promise; } diff --git a/src/test/datascience/export/exportUtil.test.ts b/src/test/datascience/export/exportUtil.test.ts index c59d133f3feb..1e80292e1829 100644 --- a/src/test/datascience/export/exportUtil.test.ts +++ b/src/test/datascience/export/exportUtil.test.ts @@ -37,7 +37,7 @@ suite('DataScience - Export Util', () => { ); await exportUtil.removeSvgs(file); - const model = await notebookStorage.getOrCreateModel(file); + const model = await notebookStorage.getOrCreateModel({ file }); // make sure no svg exists in model const SVG = 'image/svg+xml'; diff --git a/src/test/datascience/interactive-ipynb/nativeEditorStorage.unit.test.ts b/src/test/datascience/interactive-ipynb/nativeEditorStorage.unit.test.ts index ad5093ca7361..103d2d40b8ca 100644 --- a/src/test/datascience/interactive-ipynb/nativeEditorStorage.unit.test.ts +++ b/src/test/datascience/interactive-ipynb/nativeEditorStorage.unit.test.ts @@ -425,7 +425,7 @@ suite('DataScience - Native Editor Storage', () => { } test('Create new editor and add some cells', async () => { - model = await storage.getOrCreateModel(baseUri); + model = await storage.getOrCreateModel({ file: baseUri }); insertCell(0, '1'); const cells = model.cells; expect(cells).to.be.lengthOf(4); @@ -434,7 +434,7 @@ suite('DataScience - Native Editor Storage', () => { }); test('Move cells around', async () => { - model = await storage.getOrCreateModel(baseUri); + model = await storage.getOrCreateModel({ file: baseUri }); swapCells('NotebookImport#0', 'NotebookImport#1'); const cells = model.cells; expect(cells).to.be.lengthOf(3); @@ -443,7 +443,7 @@ suite('DataScience - Native Editor Storage', () => { }); test('Edit/delete cells', async () => { - model = await storage.getOrCreateModel(baseUri); + model = await storage.getOrCreateModel({ file: baseUri }); expect(model.isDirty).to.be.equal(false, 'Editor should not be dirty'); editCell( [ @@ -483,7 +483,7 @@ suite('DataScience - Native Editor Storage', () => { test('Editing a file and closing will keep contents', async () => { await filesConfig?.update('autoSave', 'off'); - model = await storage.getOrCreateModel(baseUri); + model = await storage.getOrCreateModel({ file: baseUri }); expect(model.isDirty).to.be.equal(false, 'Editor should not be dirty'); editCell( [ @@ -512,7 +512,7 @@ suite('DataScience - Native Editor Storage', () => { // Recreate storage = createStorage(); - model = await storage.getOrCreateModel(baseUri); + model = await storage.getOrCreateModel({ file: baseUri }); const cells = model.cells; expect(cells).to.be.lengthOf(3); @@ -522,7 +522,7 @@ suite('DataScience - Native Editor Storage', () => { }); test('Editing a new file and closing will keep contents', async () => { - model = await storage.getOrCreateModel(untiledUri, undefined, true); + model = await storage.getOrCreateModel({ file: untiledUri, skipLoadingDirtyContents: true }); expect(model.isDirty).to.be.equal(false, 'Editor should not be dirty'); insertCell(0, 'a=1'); @@ -531,7 +531,7 @@ suite('DataScience - Native Editor Storage', () => { // Recreate storage = createStorage(); - model = await storage.getOrCreateModel(untiledUri); + model = await storage.getOrCreateModel({ file: untiledUri }); const cells = model.cells; expect(cells).to.be.lengthOf(2); @@ -550,7 +550,7 @@ suite('DataScience - Native Editor Storage', () => { // Put the regular file into the local storage await localMemento.update(`notebook-storage-${file.toString()}`, differentFile); - model = await storage.getOrCreateModel(file); + model = await storage.getOrCreateModel({ file }); // It should load with that value const cells = model.cells; @@ -571,7 +571,7 @@ suite('DataScience - Native Editor Storage', () => { contents: differentFile, lastModifiedTimeMs: Date.now() }); - model = await storage.getOrCreateModel(file); + model = await storage.getOrCreateModel({ file }); // It should load with that value const cells = model.cells; @@ -601,7 +601,7 @@ suite('DataScience - Native Editor Storage', () => { lastModifiedTimeMs: Date.now() }); - model = await storage.getOrCreateModel(file); + model = await storage.getOrCreateModel({ file }); // It should load with that value const cells = model.cells; diff --git a/src/test/datascience/mockCustomEditorService.ts b/src/test/datascience/mockCustomEditorService.ts index 03ceee2b8c25..fa59c744d1b0 100644 --- a/src/test/datascience/mockCustomEditorService.ts +++ b/src/test/datascience/mockCustomEditorService.ts @@ -138,7 +138,7 @@ export class MockCustomEditorService implements ICustomEditorService { private async getModel(file: Uri): Promise { const nativeProvider = this.provider as NativeEditorProvider; if (nativeProvider) { - return (nativeProvider.loadModel(file) as unknown) as Promise; + return (nativeProvider.loadModel({ file }) as unknown) as Promise; } return undefined; } diff --git a/src/test/datascience/notebook/contentProvider.ds.test.ts b/src/test/datascience/notebook/contentProvider.ds.test.ts index d2a64d11ef61..fa283388337f 100644 --- a/src/test/datascience/notebook/contentProvider.ds.test.ts +++ b/src/test/datascience/notebook/contentProvider.ds.test.ts @@ -60,7 +60,7 @@ suite('DataScience - VSCode Notebook - (Open)', function () { 'notebook', 'testJsonContents.ipynb' ); - const model = await storageProvider.getOrCreateModel(Uri.file(file)); + const model = await storageProvider.getOrCreateModel({ file: Uri.file(file) }); disposables.push(model); model.trust(); const jsonStr = fs.readFileSync(file, { encoding: 'utf8' }); diff --git a/src/test/datascience/notebook/contentProvider.unit.test.ts b/src/test/datascience/notebook/contentProvider.unit.test.ts index 39fd8e5b3464..5ccae9026d79 100644 --- a/src/test/datascience/notebook/contentProvider.unit.test.ts +++ b/src/test/datascience/notebook/contentProvider.unit.test.ts @@ -55,9 +55,7 @@ suite('DataScience - NativeNotebook ContentProvider', () => { ] } ); - when(storageProvider.getOrCreateModel(anything(), anything(), anything(), anything())).thenResolve( - model - ); + when(storageProvider.getOrCreateModel(anything())).thenResolve(model); const notebook = await contentProvider.openNotebook(fileUri, {}); @@ -135,9 +133,7 @@ suite('DataScience - NativeNotebook ContentProvider', () => { ] } ); - when(storageProvider.getOrCreateModel(anything(), anything(), anything(), anything())).thenResolve( - model - ); + when(storageProvider.getOrCreateModel(anything())).thenResolve(model); const notebook = await contentProvider.openNotebook(fileUri, {}); From 6cb43d5eba89da9112a52f2b744583a53b361585 Mon Sep 17 00:00:00 2001 From: David Kutugata Date: Fri, 18 Sep 2020 13:05:45 -0700 Subject: [PATCH 4/9] add jedi-language-server to 3rd party notices (#13977) * add jedi-language-server to 3rd party notices * move license from distribution to repository file --- ThirdPartyNotices-Distribution.txt | 1 - ThirdPartyNotices-Repository.txt | 30 +++++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/ThirdPartyNotices-Distribution.txt b/ThirdPartyNotices-Distribution.txt index 2e62e34b8564..06d2e73f3084 100644 --- a/ThirdPartyNotices-Distribution.txt +++ b/ThirdPartyNotices-Distribution.txt @@ -15141,4 +15141,3 @@ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. You just DO WHAT THE FUCK YOU WANT TO. --------------------------------------------------------- - diff --git a/ThirdPartyNotices-Repository.txt b/ThirdPartyNotices-Repository.txt index 1162db48bc9c..98c64072ca51 100644 --- a/ThirdPartyNotices-Repository.txt +++ b/ThirdPartyNotices-Repository.txt @@ -1167,4 +1167,32 @@ trademarks does not indicate endorsement of the trademark holder by Font Awesome, nor vice versa. **Please do not use brand logos for any purpose except to represent the company, product, or service to which they refer.** ========================================= -END OF font-awesome NOTICES, INFORMATION, AND LICENSE \ No newline at end of file +END OF font-awesome NOTICES, INFORMATION, AND LICENSE + +%% jedi-language-server NOTICES, INFORMATION, AND LICENSE BEGIN HERE +========================================= +jedi-language-server + +MIT License + +Copyright (c) 2019 Sam Roeca + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +========================================= +END OF jedi-language-server NOTICES, INFORMATION, AND LICENSE \ No newline at end of file From 832025ac4011678c88ef9ba9397de607780d6f52 Mon Sep 17 00:00:00 2001 From: David Kutugata Date: Tue, 22 Sep 2020 10:34:09 -0700 Subject: [PATCH 5/9] disable test_discover_complex_default and (#14024) test_discover_complex_doctest --- pythonFiles/tests/testing_tools/adapter/test_functional.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pythonFiles/tests/testing_tools/adapter/test_functional.py b/pythonFiles/tests/testing_tools/adapter/test_functional.py index bd6c6b200314..86ca7275fd56 100644 --- a/pythonFiles/tests/testing_tools/adapter/test_functional.py +++ b/pythonFiles/tests/testing_tools/adapter/test_functional.py @@ -141,6 +141,7 @@ def test_discover_simple(self): ], ) + @pytest.mark.skip(reason="https://github.com/microsoft/vscode-python/issues/14023") def test_discover_complex_default(self): projroot, testroot = resolve_testroot("complex") expected = self.complex(projroot) @@ -161,6 +162,7 @@ def test_discover_complex_default(self): self.maxDiff = None self.assertEqual(result, expected) + @pytest.mark.skip(reason="https://github.com/microsoft/vscode-python/issues/14023") def test_discover_complex_doctest(self): projroot, _ = resolve_testroot("complex") expected = self.complex(projroot) From 074024c92852b06eaa20cc702ac384cdec3a2c37 Mon Sep 17 00:00:00 2001 From: Kartik Raj Date: Wed, 23 Sep 2020 01:59:22 +0530 Subject: [PATCH 6/9] Upgrade isort to 5.5.3 (#14035) (#14037) --- news/1 Enhancements/14027.md | 1 + requirements.in | 2 +- requirements.txt | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 news/1 Enhancements/14027.md diff --git a/news/1 Enhancements/14027.md b/news/1 Enhancements/14027.md new file mode 100644 index 000000000000..810963c7b177 --- /dev/null +++ b/news/1 Enhancements/14027.md @@ -0,0 +1 @@ +Upgraded to isort `5.5.3`. diff --git a/requirements.in b/requirements.in index b2d0327ce838..f8f1eaf05370 100644 --- a/requirements.in +++ b/requirements.in @@ -9,6 +9,6 @@ git+git://github.com/vscode-python/jedi-language-server@42823a2598d4b6369e9273c5ad237a48c5d67553; python_version >= '3.6' pygls==0.9.0; python_version >= '3.6' # Sort Imports -isort==5.5.2; python_version >= '3.6' +isort==5.5.3; python_version >= '3.6' # DS Python daemon python-jsonrpc-server==0.2.0 diff --git a/requirements.txt b/requirements.txt index c309b6ab206b..3a7efb00e04e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,7 +6,7 @@ # click==7.1.2 # via jedi-language-server future==0.18.2 # via python-jsonrpc-server -isort==5.5.2 ; python_version >= "3.6" # via -r requirements.in +isort==5.5.3 ; python_version >= "3.6" # via -r requirements.in git+git://github.com/vscode-python/jedi-language-server@42823a2598d4b6369e9273c5ad237a48c5d67553 ; python_version >= "3.6" # via -r requirements.in jedi==0.17.2 # via jedi-language-server parso==0.7.0 # via jedi From c1258f025c23556eb35423e51366db2e2ff68e6a Mon Sep 17 00:00:00 2001 From: David Kutugata Date: Tue, 22 Sep 2020 16:58:04 -0700 Subject: [PATCH 7/9] prepare release (#14042) --- CHANGELOG.md | 6 +- ThirdPartyNotices-Distribution.txt | 133 +++++++++++++++-------------- news/1 Enhancements/14027.md | 1 - package-lock.json | 2 +- package.json | 2 +- 5 files changed, 73 insertions(+), 71 deletions(-) delete mode 100644 news/1 Enhancements/14027.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 38b5f71f1330..826423317b57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 2020.9.0 (14 September 2020) +## 2020.9.0 (22 September 2020) ### Enhancements @@ -19,6 +19,8 @@ ([#13831](https://github.com/Microsoft/vscode-python/issues/13831)) 1. Enable custom editor support in stable VS code at 20%. ([#13890](https://github.com/Microsoft/vscode-python/issues/13890)) +1. Upgraded to isort `5.5.3`. + ([#14027](https://github.com/Microsoft/vscode-python/issues/14027)) ### Fixes @@ -60,7 +62,7 @@ 1. Correctly install ipykernel when launching from an interpreter. ([#13956](https://github.com/Microsoft/vscode-python/issues/13956)) 1. Backup on custom editors is being ignored. - ([#13981](https://github.com/Microsoft/vscode-python/issues/13981)) + ([#13981](https://github.com/Microsoft/vscode-python/issues/13981)) ### Code Health diff --git a/ThirdPartyNotices-Distribution.txt b/ThirdPartyNotices-Distribution.txt index 06d2e73f3084..ddb4327c18dd 100644 --- a/ThirdPartyNotices-Distribution.txt +++ b/ThirdPartyNotices-Distribution.txt @@ -3265,12 +3265,13 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND --------------------------------------------------------- -estraverse 1.5.1 - BSD-2-Clause -https://github.com/Constellation/estraverse +estraverse 4.3.0 - BSD-2-Clause +https://github.com/estools/estraverse +Copyright (c) 2014 Yusuke Suzuki Copyright (c) 2012 Ariya Hidayat Copyright (c) 2012-2013 Yusuke Suzuki -Copyright (c) 2012-2013 Yusuke Suzuki (http://github.com/Constellation) +Copyright (c) 2012-2016 Yusuke Suzuki (http://github.com/Constellation) Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -3297,13 +3298,12 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------- -estraverse 4.3.0 - BSD-2-Clause -https://github.com/estools/estraverse +estraverse 1.5.1 - BSD-2-Clause +https://github.com/Constellation/estraverse -Copyright (c) 2014 Yusuke Suzuki Copyright (c) 2012 Ariya Hidayat Copyright (c) 2012-2013 Yusuke Suzuki -Copyright (c) 2012-2016 Yusuke Suzuki (http://github.com/Constellation) +Copyright (c) 2012-2013 Yusuke Suzuki (http://github.com/Constellation) Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -4436,7 +4436,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------- -hoist-non-react-statics 3.3.0 - BSD-3-Clause +hoist-non-react-statics 3.3.1 - BSD-3-Clause https://github.com/mridgway/hoist-non-react-statics#readme Copyright 2015, Yahoo! Inc. @@ -4477,7 +4477,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------- -hoist-non-react-statics 3.3.1 - BSD-3-Clause +hoist-non-react-statics 3.3.0 - BSD-3-Clause https://github.com/mridgway/hoist-non-react-statics#readme Copyright 2015, Yahoo! Inc. @@ -4597,7 +4597,7 @@ The complete list of contributors can be found at: https://github.com/hapijs/qs/ --------------------------------------------------------- -source-map 0.5.7 - BSD-3-Clause +source-map 0.6.1 - BSD-3-Clause https://github.com/mozilla/source-map Copyright 2011 The Closure Compiler @@ -4640,7 +4640,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------- -source-map 0.6.1 - BSD-3-Clause +source-map 0.5.7 - BSD-3-Clause https://github.com/mozilla/source-map Copyright 2011 The Closure Compiler @@ -5502,8 +5502,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. --------------------------------------------------------- -@babel/runtime 7.8.3 - MIT -https://babeljs.io/docs/en/next/babel-runtime +@babel/runtime 7.5.4 - MIT + Copyright (c) 2014-present Sebastian McKenzie and other contributors @@ -5535,8 +5535,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -@babel/runtime 7.5.4 - MIT - +@babel/runtime 7.8.3 - MIT +https://babeljs.io/docs/en/next/babel-runtime Copyright (c) 2014-present Sebastian McKenzie and other contributors @@ -7420,7 +7420,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -date-format 3.0.0 - MIT +date-format 2.1.0 - MIT https://github.com/nomiddlename/date-format#readme Copyright (c) 2013 Gareth Jones @@ -7451,7 +7451,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -date-format 2.1.0 - MIT +date-format 3.0.0 - MIT https://github.com/nomiddlename/date-format#readme Copyright (c) 2013 Gareth Jones @@ -7482,7 +7482,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -debug 4.1.1 - MIT +debug 3.1.0 - MIT https://github.com/visionmedia/debug#readme Copyright (c) 2014 TJ Holowaychuk @@ -7575,7 +7575,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -debug 3.1.0 - MIT +debug 4.1.1 - MIT https://github.com/visionmedia/debug#readme Copyright (c) 2014 TJ Holowaychuk @@ -8928,7 +8928,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI --------------------------------------------------------- -got 8.3.2 - MIT +got 9.6.0 - MIT https://github.com/sindresorhus/got#readme Copyright (c) Sindre Sorhus (sindresorhus.com) @@ -8948,7 +8948,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI --------------------------------------------------------- -got 9.6.0 - MIT +got 8.3.2 - MIT https://github.com/sindresorhus/got#readme Copyright (c) Sindre Sorhus (sindresorhus.com) @@ -9431,7 +9431,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -isarray 1.0.0 - MIT +isarray 0.0.1 - MIT https://github.com/juliangruber/isarray Copyright (c) 2013 Julian Gruber @@ -9450,7 +9450,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI --------------------------------------------------------- -isarray 0.0.1 - MIT +isarray 1.0.0 - MIT https://github.com/juliangruber/isarray Copyright (c) 2013 Julian Gruber @@ -9638,7 +9638,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI --------------------------------------------------------- -isort 5.5.2 - MIT +isort 5.5.3 - MIT Copyright 2017 Jack Evans @@ -11173,10 +11173,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -normalize-url 2.0.1 - MIT +normalize-url 4.5.0 - MIT https://github.com/sindresorhus/normalize-url#readme -(c) Sindre Sorhus (https://sindresorhus.com) Copyright (c) Sindre Sorhus (sindresorhus.com) MIT License @@ -11194,9 +11193,10 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI --------------------------------------------------------- -normalize-url 4.5.0 - MIT +normalize-url 2.0.1 - MIT https://github.com/sindresorhus/normalize-url#readme +(c) Sindre Sorhus (https://sindresorhus.com) Copyright (c) Sindre Sorhus (sindresorhus.com) MIT License @@ -11558,7 +11558,7 @@ SOFTWARE. --------------------------------------------------------- -p-cancelable 0.4.1 - MIT +p-cancelable 1.1.0 - MIT https://github.com/sindresorhus/p-cancelable#readme (c) Sindre Sorhus (https://sindresorhus.com) @@ -11579,7 +11579,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI --------------------------------------------------------- -p-cancelable 1.1.0 - MIT +p-cancelable 0.4.1 - MIT https://github.com/sindresorhus/p-cancelable#readme (c) Sindre Sorhus (https://sindresorhus.com) @@ -11931,7 +11931,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI --------------------------------------------------------- -process-nextick-args 2.0.1 - MIT +process-nextick-args 1.0.7 - MIT https://github.com/calvinmetcalf/process-nextick-args Copyright (c) 2015 Calvin Metcalf @@ -11961,7 +11961,7 @@ SOFTWARE.** --------------------------------------------------------- -process-nextick-args 1.0.7 - MIT +process-nextick-args 2.0.1 - MIT https://github.com/calvinmetcalf/process-nextick-args Copyright (c) 2015 Calvin Metcalf @@ -12128,7 +12128,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI --------------------------------------------------------- -pump 3.0.0 - MIT +pump 2.0.1 - MIT https://github.com/mafintosh/pump#readme Copyright (c) 2014 Mathias Buus @@ -12159,7 +12159,7 @@ THE SOFTWARE. --------------------------------------------------------- -pump 2.0.1 - MIT +pump 3.0.0 - MIT https://github.com/mafintosh/pump#readme Copyright (c) 2014 Mathias Buus @@ -12429,7 +12429,7 @@ IN THE SOFTWARE. --------------------------------------------------------- -readable-stream 2.3.7 - MIT +readable-stream 2.3.6 - MIT https://github.com/nodejs/readable-stream#readme Copyright Joyent, Inc. and other Node contributors. @@ -12487,7 +12487,7 @@ IN THE SOFTWARE. --------------------------------------------------------- -readable-stream 2.3.6 - MIT +readable-stream 2.3.7 - MIT https://github.com/nodejs/readable-stream#readme Copyright Joyent, Inc. and other Node contributors. @@ -12703,8 +12703,8 @@ SOFTWARE. --------------------------------------------------------- -resolve 1.1.7 - MIT -https://github.com/substack/node-resolve#readme +resolve 1.11.1 - MIT +https://github.com/browserify/resolve#readme This software is released under the MIT license: @@ -12731,8 +12731,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -resolve 1.11.1 - MIT -https://github.com/browserify/resolve#readme +resolve 1.1.7 - MIT +https://github.com/substack/node-resolve#readme This software is released under the MIT license: @@ -13134,7 +13134,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -static-module 2.2.5 - MIT +static-module 3.0.3 - MIT https://github.com/substack/static-module @@ -13162,7 +13162,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- -static-module 3.0.3 - MIT +static-module 2.2.5 - MIT https://github.com/substack/static-module @@ -14067,7 +14067,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI --------------------------------------------------------- -unicode-trie 2.0.0 - MIT +unicode-trie 1.0.0 - MIT https://github.com/devongovett/unicode-trie Copyright 2018 @@ -14086,7 +14086,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI --------------------------------------------------------- -unicode-trie 1.0.0 - MIT +unicode-trie 2.0.0 - MIT https://github.com/devongovett/unicode-trie Copyright 2018 @@ -14320,6 +14320,27 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- + +--------------------------------------------------------- + +uuid 8.2.0 - MIT +https://github.com/uuidjs/uuid#readme + +Copyright 2011, Sebastian Tschan https://blueimp.net +Copyright (c) Paul Johnston 1999 - 2009 Other contributors Greg Holt, Andrew Kepert, Ydnar, Lostinet + +The MIT License (MIT) + +Copyright (c) 2010-2020 Robert Kieffer and other contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + --------------------------------------------------------- --------------------------------------------------------- @@ -14354,27 +14375,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ---------------------------------------------------------- - ---------------------------------------------------------- - -uuid 8.2.0 - MIT -https://github.com/uuidjs/uuid#readme - -Copyright 2011, Sebastian Tschan https://blueimp.net -Copyright (c) Paul Johnston 1999 - 2009 Other contributors Greg Holt, Andrew Kepert, Ydnar, Lostinet - -The MIT License (MIT) - -Copyright (c) 2010-2020 Robert Kieffer and other contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - --------------------------------------------------------- --------------------------------------------------------- @@ -14825,7 +14825,7 @@ SOFTWARE. --------------------------------------------------------- -xml2js 0.4.19 - MIT +xml2js 0.2.8 - MIT https://github.com/Leonidas-from-XIV/node-xml2js Copyright 2010, 2011, 2012, 2013. @@ -14855,7 +14855,7 @@ IN THE SOFTWARE. --------------------------------------------------------- -xml2js 0.2.8 - MIT +xml2js 0.4.19 - MIT https://github.com/Leonidas-from-XIV/node-xml2js Copyright 2010, 2011, 2012, 2013. @@ -15141,3 +15141,4 @@ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. You just DO WHAT THE FUCK YOU WANT TO. --------------------------------------------------------- + diff --git a/news/1 Enhancements/14027.md b/news/1 Enhancements/14027.md deleted file mode 100644 index 810963c7b177..000000000000 --- a/news/1 Enhancements/14027.md +++ /dev/null @@ -1 +0,0 @@ -Upgraded to isort `5.5.3`. diff --git a/package-lock.json b/package-lock.json index 3c3d66258cc9..02c8932d6c64 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "python", - "version": "2020.9.0-rc", + "version": "2020.9.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index a91c5a5be59d..b34f0ee31e6b 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.9.0-rc", + "version": "2020.9.0", "featureFlags": { "usingNewInterpreterStorage": true }, From 0b41a8631fbd7eaf5024d3d0ed31185ee5edc69b Mon Sep 17 00:00:00 2001 From: David Kutugata Date: Tue, 22 Sep 2020 20:54:44 -0700 Subject: [PATCH 8/9] fixed annoying warnings (#14049) --- CHANGELOG.md | 2 +- package.nls.json | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 826423317b57..dc0ec9e5af07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 2020.9.0 (22 September 2020) +## 2020.9.0 (23 September 2020) ### Enhancements diff --git a/package.nls.json b/package.nls.json index 16a537b3a669..b1b7007f43d8 100644 --- a/package.nls.json +++ b/package.nls.json @@ -59,6 +59,8 @@ "python.command.python.datascience.debugFileInteractive.title": "Debug Current File in Python Interactive Window", "python.command.python.datascience.runallcells.title": "Run All Cells", "python.command.python.datascience.notebookeditor.runallcells.title": "Run All Notebook Cells", + "python.command.python.datascience.notebookeditor.expandallcells.title": "Expand All Notebook Cells", + "python.command.python.datascience.notebookeditor.collapseallcells.title": "Collapse All Notebook Cells", "python.command.python.datascience.runallcellsabove.title": "Run Above", "python.command.python.datascience.runcellandallbelow.title": "Run Below", "python.command.python.datascience.runallcellsabove.palette.title": "Run Cells Above Current Cell", From 78d2007e548bb3ce1a6976ab13af1cef35199f3a Mon Sep 17 00:00:00 2001 From: David Kutugata Date: Wed, 23 Sep 2020 10:41:09 -0700 Subject: [PATCH 9/9] update version --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 02c8932d6c64..16469d045b25 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "python", - "version": "2020.9.0", + "version": "2020.10.0-dev", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index b34f0ee31e6b..041efbadfd50 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.9.0", + "version": "2020.10.0-dev", "featureFlags": { "usingNewInterpreterStorage": true },