diff --git a/src/client/common/installer/condaInstaller.ts b/src/client/common/installer/condaInstaller.ts index a20b35e0f110..fbb3dcf183ef 100644 --- a/src/client/common/installer/condaInstaller.ts +++ b/src/client/common/installer/condaInstaller.ts @@ -88,18 +88,7 @@ export class CondaInstaller extends ModuleInstaller { // Found that using conda-forge is best at packages like tensorboard & ipykernel which seem to get updated first on conda-forge // https://github.com/microsoft/vscode-jupyter/issues/7787 & https://github.com/microsoft/vscode-python/issues/17628 // Do this just for the datascience packages. - if ( - [ - Product.tensorboard, - Product.ipykernel, - Product.pandas, - Product.nbconvert, - Product.jupyter, - Product.notebook, - ] - .map(translateProductToModule) - .includes(moduleName) - ) { + if ([Product.tensorboard].map(translateProductToModule).includes(moduleName)) { args.push('-c', 'conda-forge'); } if (info && info.name) { diff --git a/src/client/common/installer/moduleInstaller.ts b/src/client/common/installer/moduleInstaller.ts index 62160b7e25c9..f70dd937aba9 100644 --- a/src/client/common/installer/moduleInstaller.ts +++ b/src/client/common/installer/moduleInstaller.ts @@ -264,18 +264,6 @@ export function translateProductToModule(product: Product): string { return 'unittest'; case Product.bandit: return 'bandit'; - case Product.jupyter: - return 'jupyter'; - case Product.notebook: - return 'notebook'; - case Product.pandas: - return 'pandas'; - case Product.ipykernel: - return 'ipykernel'; - case Product.nbconvert: - return 'nbconvert'; - case Product.kernelspec: - return 'kernelspec'; case Product.tensorboard: return 'tensorboard'; case Product.torchProfilerInstallName: diff --git a/src/client/common/installer/productNames.ts b/src/client/common/installer/productNames.ts index 6474e8a2a514..378fd5a38dba 100644 --- a/src/client/common/installer/productNames.ts +++ b/src/client/common/installer/productNames.ts @@ -19,11 +19,5 @@ ProductNames.set(Product.yapf, 'yapf'); ProductNames.set(Product.tensorboard, 'tensorboard'); ProductNames.set(Product.torchProfilerInstallName, 'torch-tb-profiler'); ProductNames.set(Product.torchProfilerImportName, 'torch_tb_profiler'); -ProductNames.set(Product.jupyter, 'jupyter'); -ProductNames.set(Product.notebook, 'notebook'); -ProductNames.set(Product.ipykernel, 'ipykernel'); -ProductNames.set(Product.nbconvert, 'nbconvert'); -ProductNames.set(Product.kernelspec, 'kernelspec'); -ProductNames.set(Product.pandas, 'pandas'); ProductNames.set(Product.pip, 'pip'); ProductNames.set(Product.ensurepip, 'ensurepip'); diff --git a/src/client/common/installer/productService.ts b/src/client/common/installer/productService.ts index 5de130e84d06..26a01e37c3ba 100644 --- a/src/client/common/installer/productService.ts +++ b/src/client/common/installer/productService.ts @@ -25,12 +25,6 @@ export class ProductService implements IProductService { this.ProductTypes.set(Product.autopep8, ProductType.Formatter); this.ProductTypes.set(Product.black, ProductType.Formatter); this.ProductTypes.set(Product.yapf, ProductType.Formatter); - this.ProductTypes.set(Product.jupyter, ProductType.DataScience); - this.ProductTypes.set(Product.notebook, ProductType.DataScience); - this.ProductTypes.set(Product.ipykernel, ProductType.DataScience); - this.ProductTypes.set(Product.nbconvert, ProductType.DataScience); - this.ProductTypes.set(Product.kernelspec, ProductType.DataScience); - this.ProductTypes.set(Product.pandas, ProductType.DataScience); this.ProductTypes.set(Product.tensorboard, ProductType.DataScience); this.ProductTypes.set(Product.torchProfilerInstallName, ProductType.DataScience); this.ProductTypes.set(Product.torchProfilerImportName, ProductType.DataScience); diff --git a/src/client/common/types.ts b/src/client/common/types.ts index 3359854f89b7..b48a2daadaa6 100644 --- a/src/client/common/types.ts +++ b/src/client/common/types.ts @@ -109,12 +109,6 @@ export enum Product { isort = 15, black = 16, bandit = 17, - jupyter = 18, - ipykernel = 19, - notebook = 20, - kernelspec = 21, - nbconvert = 22, - pandas = 23, tensorboard = 24, torchProfilerInstallName = 25, torchProfilerImportName = 26, diff --git a/src/client/jupyter/jupyterIntegration.ts b/src/client/jupyter/jupyterIntegration.ts index 7f660d26e5e4..dbfd1bdf5681 100644 --- a/src/client/jupyter/jupyterIntegration.ts +++ b/src/client/jupyter/jupyterIntegration.ts @@ -6,90 +6,20 @@ import { inject, injectable, named } from 'inversify'; import { dirname } from 'path'; -import { CancellationToken, Event, Extension, Memento, Uri } from 'vscode'; +import { Extension, Memento, Uri } from 'vscode'; import type { SemVer } from 'semver'; import { IContextKeyManager, IWorkspaceService } from '../common/application/types'; import { JUPYTER_EXTENSION_ID, PYLANCE_EXTENSION_ID } from '../common/constants'; -import { InterpreterUri, ModuleInstallFlags } from '../common/installer/types'; -import { - GLOBAL_MEMENTO, - IExtensions, - IInstaller, - IMemento, - InstallerResponse, - Product, - ProductInstallStatus, - Resource, -} from '../common/types'; +import { GLOBAL_MEMENTO, IExtensions, IMemento, Resource } from '../common/types'; import { getDebugpyPackagePath } from '../debugger/extension/adapter/remoteLaunchers'; import { IEnvironmentActivationService } from '../interpreter/activation/types'; import { IInterpreterQuickPickItem, IInterpreterSelector } from '../interpreter/configuration/types'; -import { - IComponentAdapter, - ICondaService, - IInterpreterDisplay, - IInterpreterService, - IInterpreterStatusbarVisibilityFilter, - PythonEnvironmentsChangedEvent, -} from '../interpreter/contracts'; +import { ICondaService, IInterpreterDisplay, IInterpreterStatusbarVisibilityFilter } from '../interpreter/contracts'; import { PythonEnvironment } from '../pythonEnvironments/info'; import { PylanceApi } from '../activation/node/pylanceApi'; import { ExtensionContextKey } from '../common/application/contextKeys'; -/** - * This allows Python extension to update Product enum without breaking Jupyter. - * I.e. we have a strict contract, else using numbers (in enums) is bound to break across products. - */ -enum JupyterProductToInstall { - jupyter = 'jupyter', - ipykernel = 'ipykernel', - notebook = 'notebook', - kernelspec = 'kernelspec', - nbconvert = 'nbconvert', - pandas = 'pandas', - pip = 'pip', -} - -const ProductMapping: { [key in JupyterProductToInstall]: Product } = { - [JupyterProductToInstall.ipykernel]: Product.ipykernel, - [JupyterProductToInstall.jupyter]: Product.jupyter, - [JupyterProductToInstall.kernelspec]: Product.kernelspec, - [JupyterProductToInstall.nbconvert]: Product.nbconvert, - [JupyterProductToInstall.notebook]: Product.notebook, - [JupyterProductToInstall.pandas]: Product.pandas, - [JupyterProductToInstall.pip]: Product.pip, -}; type PythonApiForJupyterExtension = { - /** - * IInterpreterService - */ - onDidChangeInterpreter: Event; - /** - * IInterpreterService - */ - readonly refreshPromise: Promise | undefined; - /** - * IInterpreterService - */ - readonly onDidChangeInterpreters: Event; - /** - * Equivalent to getInterpreters() in IInterpreterService - */ - getKnownInterpreters(resource?: Uri): PythonEnvironment[]; - /** - * @deprecated Use `getKnownInterpreters`, `onDidChangeInterpreters`, and `refreshPromise` instead. - * Equivalent to getAllInterpreters() in IInterpreterService - */ - getInterpreters(resource?: Uri): Promise; - /** - * IInterpreterService - */ - getActiveInterpreter(resource?: Uri): Promise; - /** - * IInterpreterService - */ - getInterpreterDetails(pythonPath: string, resource?: Uri): Promise; - /** * IEnvironmentActivationService */ @@ -98,31 +28,11 @@ type PythonApiForJupyterExtension = { interpreter?: PythonEnvironment, allowExceptions?: boolean, ): Promise; - isMicrosoftStoreInterpreter(pythonPath: string): Promise; - suggestionToQuickPickItem(suggestion: PythonEnvironment, workspaceUri?: Uri | undefined): IInterpreterQuickPickItem; getKnownSuggestions(resource: Resource): IInterpreterQuickPickItem[]; /** * @deprecated Use `getKnownSuggestions` and `suggestionToQuickPickItem` instead. */ getSuggestions(resource: Resource): Promise; - /** - * IInstaller - */ - install( - product: JupyterProductToInstall, - resource?: InterpreterUri, - cancel?: CancellationToken, - reInstallAndUpdate?: boolean, - installPipIfRequired?: boolean, - ): Promise; - /** - * IInstaller - */ - isProductVersionCompatible( - product: Product, - semVerRequirement: string, - resource?: InterpreterUri, - ): Promise; /** * Returns path to where `debugpy` is. In python extension this is `/pythonFiles/lib/python`. */ @@ -140,10 +50,6 @@ type PythonApiForJupyterExtension = { * Returns the conda executable. */ getCondaFile(): Promise; - getEnvironmentActivationShellCommands( - resource: Resource, - interpreter?: PythonEnvironment, - ): Promise; /** * Call to provide a function that the Python extension can call to request the Python @@ -181,13 +87,10 @@ export class JupyterExtensionIntegration { constructor( @inject(IExtensions) private readonly extensions: IExtensions, - @inject(IInterpreterService) private readonly interpreterService: IInterpreterService, @inject(IInterpreterSelector) private readonly interpreterSelector: IInterpreterSelector, - @inject(IInstaller) private readonly installer: IInstaller, @inject(IEnvironmentActivationService) private readonly envActivation: IEnvironmentActivationService, @inject(IMemento) @named(GLOBAL_MEMENTO) private globalState: Memento, @inject(IInterpreterDisplay) private interpreterDisplay: IInterpreterDisplay, - @inject(IComponentAdapter) private pyenvs: IComponentAdapter, @inject(IWorkspaceService) private workspaceService: IWorkspaceService, @inject(ICondaService) private readonly condaService: ICondaService, @inject(IContextKeyManager) private readonly contextManager: IContextKeyManager, @@ -201,54 +104,15 @@ export class JupyterExtensionIntegration { } // Forward python parts jupyterExtensionApi.registerPythonApi({ - onDidChangeInterpreter: this.interpreterService.onDidChangeInterpreter, - getActiveInterpreter: async (resource?: Uri) => this.interpreterService.getActiveInterpreter(resource), - getInterpreterDetails: async (pythonPath: string) => - this.interpreterService.getInterpreterDetails(pythonPath), - refreshPromise: this.interpreterService.refreshPromise, - onDidChangeInterpreters: this.interpreterService.onDidChangeInterpreters, - getKnownInterpreters: (resource: Uri | undefined) => this.pyenvs.getInterpreters(resource), - getInterpreters: async (resource: Uri | undefined) => this.interpreterService.getAllInterpreters(resource), getActivatedEnvironmentVariables: async ( resource: Resource, interpreter?: PythonEnvironment, allowExceptions?: boolean, ) => this.envActivation.getActivatedEnvironmentVariables(resource, interpreter, allowExceptions), - isMicrosoftStoreInterpreter: async (pythonPath: string): Promise => - this.pyenvs.isMicrosoftStoreInterpreter(pythonPath), getSuggestions: async (resource: Resource): Promise => this.interpreterSelector.getAllSuggestions(resource), getKnownSuggestions: (resource: Resource): IInterpreterQuickPickItem[] => this.interpreterSelector.getSuggestions(resource), - suggestionToQuickPickItem: ( - suggestion: PythonEnvironment, - workspaceUri?: Uri | undefined, - ): IInterpreterQuickPickItem => - this.interpreterSelector.suggestionToQuickPickItem(suggestion, workspaceUri), - install: async ( - product: JupyterProductToInstall, - resource?: InterpreterUri, - cancel?: CancellationToken, - reInstallAndUpdate?: boolean, - installPipIfRequired?: boolean, - ): Promise => { - let flags = - reInstallAndUpdate === true - ? ModuleInstallFlags.updateDependencies | ModuleInstallFlags.reInstall - : undefined; - if (installPipIfRequired === true) { - flags = flags - ? flags | ModuleInstallFlags.installPipIfRequired - : ModuleInstallFlags.installPipIfRequired; - } - return this.installer.install(ProductMapping[product], resource, cancel, flags); - }, - isProductVersionCompatible: async ( - product: Product, - semVerRequirement: string, - resource?: InterpreterUri, - ): Promise => - this.installer.isProductVersionCompatible(product, semVerRequirement, resource), getDebuggerPath: async () => dirname(getDebugpyPackagePath()), getInterpreterPathSelectedForJupyterServer: () => this.globalState.get('INTERPRETER_PATH_SELECTED_FOR_JUPYTER_SERVER'), @@ -257,8 +121,6 @@ export class JupyterExtensionIntegration { ), getCondaFile: () => this.condaService.getCondaFile(), getCondaVersion: () => this.condaService.getCondaVersion(), - getEnvironmentActivationShellCommands: (resource: Resource, interpreter?: PythonEnvironment) => - this.envActivation.getEnvironmentActivationShellCommands(resource, interpreter), registerJupyterPythonPathFunction: (func: (uri: Uri) => Promise) => this.registerJupyterPythonPathFunction(func), registerGetNotebookUriForTextDocumentUriFunction: (func: (textDocumentUri: Uri) => Uri | undefined) => diff --git a/src/test/activation/node/lspInteractiveWindowMiddlewareAddon.unit.test.ts b/src/test/activation/node/lspInteractiveWindowMiddlewareAddon.unit.test.ts index 256e57a5d724..32d9198ef7ba 100644 --- a/src/test/activation/node/lspInteractiveWindowMiddlewareAddon.unit.test.ts +++ b/src/test/activation/node/lspInteractiveWindowMiddlewareAddon.unit.test.ts @@ -10,13 +10,8 @@ import { anything, capture, instance, mock, verify, when } from 'ts-mockito'; import { LanguageClient } from 'vscode-languageclient/node'; import { LspInteractiveWindowMiddlewareAddon } from '../../../client/activation/node/lspInteractiveWindowMiddlewareAddon'; import { JupyterExtensionIntegration } from '../../../client/jupyter/jupyterIntegration'; -import { IExtensions, IInstaller } from '../../../client/common/types'; -import { - IComponentAdapter, - ICondaService, - IInterpreterDisplay, - IInterpreterService, -} from '../../../client/interpreter/contracts'; +import { IExtensions } from '../../../client/common/types'; +import { ICondaService, IInterpreterDisplay } from '../../../client/interpreter/contracts'; import { IInterpreterSelector } from '../../../client/interpreter/configuration/types'; import { IEnvironmentActivationService } from '../../../client/interpreter/activation/types'; import { IContextKeyManager, IWorkspaceService } from '../../../client/common/application/types'; @@ -32,13 +27,10 @@ suite('Pylance Language Server - Interactive Window LSP Notebooks', () => { languageClient = instance(languageClientMock); jupyterApi = new JupyterExtensionIntegration( mock(), - mock(), mock(), - mock(), mock(), new MockMemento(), mock(), - mock(), mock(), mock(), mock(), diff --git a/src/test/common/installer/productInstaller.unit.test.ts b/src/test/common/installer/productInstaller.unit.test.ts index ed1be158c0aa..66e0cc005870 100644 --- a/src/test/common/installer/productInstaller.unit.test.ts +++ b/src/test/common/installer/productInstaller.unit.test.ts @@ -57,155 +57,6 @@ suite('DataScienceInstaller install', async () => { // noop }); - test('Requires interpreter Uri', async () => { - let threwUp = false; - try { - await dataScienceInstaller.install(Product.ipykernel); - } catch (ex) { - threwUp = true; - } - expect(threwUp).to.equal(true, 'Should raise exception'); - }); - - test('Will ignore with no installer modules', async () => { - const testEnvironment: PythonEnvironment = { - envType: EnvironmentType.VirtualEnv, - envName: 'test', - envPath: interpreterPath, - path: interpreterPath, - architecture: Architecture.x64, - sysPrefix: '', - }; - installationChannelManager - .setup((c) => c.getInstallationChannels(TypeMoq.It.isAny())) - .returns(() => Promise.resolve([])); - const result = await dataScienceInstaller.install(Product.ipykernel, testEnvironment); - expect(result).to.equal(InstallerResponse.Ignore, 'Should be InstallerResponse.Ignore'); - }); - - test('Will invoke conda for conda environments', async () => { - const testEnvironment: PythonEnvironment = { - envType: EnvironmentType.Conda, - envName: 'test', - envPath: interpreterPath, - path: interpreterPath, - architecture: Architecture.x64, - sysPrefix: '', - }; - const testInstaller = TypeMoq.Mock.ofType(); - testInstaller.setup((c) => c.type).returns(() => ModuleInstallerType.Conda); - testInstaller - .setup((c) => - c.installModule( - TypeMoq.It.isValue(Product.ipykernel), - TypeMoq.It.isValue(testEnvironment), - TypeMoq.It.isAny(), - TypeMoq.It.isAny(), - ), - ) - .returns(() => Promise.resolve()); - - installationChannelManager - .setup((c) => c.getInstallationChannels(TypeMoq.It.isAny())) - .returns(() => Promise.resolve([testInstaller.object])); - - const result = await dataScienceInstaller.install(Product.ipykernel, testEnvironment); - expect(result).to.equal(InstallerResponse.Installed, 'Should be Installed'); - }); - - test('Will invoke pip by default', async () => { - const testEnvironment: PythonEnvironment = { - envType: EnvironmentType.VirtualEnv, - envName: 'test', - envPath: interpreterPath, - path: interpreterPath, - architecture: Architecture.x64, - sysPrefix: '', - }; - const testInstaller = TypeMoq.Mock.ofType(); - - testInstaller.setup((c) => c.type).returns(() => ModuleInstallerType.Pip); - testInstaller - .setup((c) => - c.installModule( - TypeMoq.It.isValue(Product.ipykernel), - TypeMoq.It.isValue(testEnvironment), - TypeMoq.It.isAny(), - TypeMoq.It.isAny(), - ), - ) - .returns(() => Promise.resolve()); - - installationChannelManager - .setup((c) => c.getInstallationChannels(TypeMoq.It.isAny())) - .returns(() => Promise.resolve([testInstaller.object])); - - const result = await dataScienceInstaller.install(Product.ipykernel, testEnvironment); - expect(result).to.equal(InstallerResponse.Installed, 'Should be Installed'); - }); - - test('Will invoke poetry', async () => { - const testEnvironment: PythonEnvironment = { - envType: EnvironmentType.Poetry, - envName: 'test', - envPath: interpreterPath, - path: interpreterPath, - architecture: Architecture.x64, - sysPrefix: '', - }; - const testInstaller = TypeMoq.Mock.ofType(); - - testInstaller.setup((c) => c.type).returns(() => ModuleInstallerType.Poetry); - testInstaller - .setup((c) => - c.installModule( - TypeMoq.It.isValue(Product.ipykernel), - TypeMoq.It.isValue(testEnvironment), - TypeMoq.It.isAny(), - TypeMoq.It.isAny(), - ), - ) - .returns(() => Promise.resolve()); - - installationChannelManager - .setup((c) => c.getInstallationChannels(TypeMoq.It.isAny())) - .returns(() => Promise.resolve([testInstaller.object])); - - const result = await dataScienceInstaller.install(Product.ipykernel, testEnvironment); - expect(result).to.equal(InstallerResponse.Installed, 'Should be Installed'); - }); - - test('Will invoke pipenv', async () => { - const testEnvironment: PythonEnvironment = { - envType: EnvironmentType.Pipenv, - envName: 'test', - envPath: interpreterPath, - path: interpreterPath, - architecture: Architecture.x64, - sysPrefix: '', - }; - const testInstaller = TypeMoq.Mock.ofType(); - - testInstaller.setup((c) => c.type).returns(() => ModuleInstallerType.Pipenv); - testInstaller - .setup((c) => - c.installModule( - TypeMoq.It.isValue(Product.ipykernel), - TypeMoq.It.isValue(testEnvironment), - TypeMoq.It.isAny(), - TypeMoq.It.isAny(), - ), - ) - .returns(() => Promise.resolve()); - - installationChannelManager - .setup((c) => c.getInstallationChannels(TypeMoq.It.isAny())) - .returns(() => Promise.resolve([testInstaller.object])); - - const result = await dataScienceInstaller.install(Product.ipykernel, testEnvironment); - expect(result).to.equal(InstallerResponse.Installed, 'Should be Installed'); - }); - test('Will invoke pip for pytorch with conda environment', async () => { // See https://github.com/microsoft/vscode-jupyter/issues/5034 const testEnvironment: PythonEnvironment = {