|
1 | 1 | // Copyright (c) Microsoft Corporation. All rights reserved. |
2 | 2 | // Licensed under the MIT License. |
3 | 3 |
|
4 | | -import { inject, injectable } from "inversify"; |
5 | | -import { Uri } from "vscode"; |
6 | | - |
7 | | -import { IInterpreterService } from "../../interpreter/contracts"; |
8 | | -import { IServiceContainer } from "../../ioc/types"; |
9 | | -import { EnvironmentType } from "../../pythonEnvironments/info"; |
10 | | -import { IApplicationShell } from "../application/types"; |
11 | | -import { IPlatformService } from "../platform/types"; |
12 | | -import { Product } from "../types"; |
13 | | -import { Installer } from "../utils/localize"; |
14 | | -import { isResource } from "../utils/misc"; |
15 | | -import { ProductNames } from "./productNames"; |
16 | | -import { |
17 | | - IInstallationChannelManager, |
18 | | - IModuleInstaller, |
19 | | - InterpreterUri, |
20 | | -} from "./types"; |
| 4 | +import { inject, injectable } from 'inversify'; |
| 5 | +import { Uri } from 'vscode'; |
| 6 | +import { IInterpreterService } from '../../interpreter/contracts'; |
| 7 | +import { IServiceContainer } from '../../ioc/types'; |
| 8 | +import { EnvironmentType } from '../../pythonEnvironments/info'; |
| 9 | +import { IApplicationShell } from '../application/types'; |
| 10 | +import { IPlatformService } from '../platform/types'; |
| 11 | +import { Product } from '../types'; |
| 12 | +import { Installer } from '../utils/localize'; |
| 13 | +import { isResource } from '../utils/misc'; |
| 14 | +import { ProductNames } from './productNames'; |
| 15 | +import { IInstallationChannelManager, IModuleInstaller, InterpreterUri } from './types'; |
21 | 16 |
|
22 | 17 | @injectable() |
23 | 18 | export class InstallationChannelManager implements IInstallationChannelManager { |
24 | | - constructor( |
25 | | - @inject(IServiceContainer) private serviceContainer: IServiceContainer, |
26 | | - ) {} |
27 | | - |
28 | | - public async getInstallationChannel( |
29 | | - product: Product, |
30 | | - resource?: InterpreterUri, |
31 | | - ): Promise<IModuleInstaller | undefined> { |
32 | | - const channels = await this.getInstallationChannels(resource); |
33 | | - |
34 | | - if (channels.length === 1) { |
35 | | - return channels[0]; |
36 | | - } |
37 | | - |
38 | | - const productName = ProductNames.get(product)!; |
39 | | - |
40 | | - const appShell = |
41 | | - this.serviceContainer.get<IApplicationShell>(IApplicationShell); |
42 | | - |
43 | | - if (channels.length === 0) { |
44 | | - await this.showNoInstallersMessage( |
45 | | - isResource(resource) ? resource : undefined, |
46 | | - ); |
47 | | - |
48 | | - return; |
49 | | - } |
50 | | - |
51 | | - const placeHolder = `Select an option to install ${productName}`; |
52 | | - |
53 | | - const options = channels.map((installer) => { |
54 | | - return { |
55 | | - label: `Install using ${installer.displayName}`, |
56 | | - description: "", |
57 | | - installer, |
58 | | - }; |
59 | | - }); |
60 | | - |
61 | | - const selection = await appShell.showQuickPick<(typeof options)[0]>( |
62 | | - options, |
63 | | - { |
64 | | - matchOnDescription: true, |
65 | | - matchOnDetail: true, |
66 | | - placeHolder, |
67 | | - }, |
68 | | - ); |
69 | | - |
70 | | - return selection ? selection.installer : undefined; |
71 | | - } |
72 | | - |
73 | | - public async getInstallationChannels( |
74 | | - resource?: InterpreterUri, |
75 | | - ): Promise<IModuleInstaller[]> { |
76 | | - const installers = |
77 | | - this.serviceContainer.getAll<IModuleInstaller>(IModuleInstaller); |
78 | | - |
79 | | - const supportedInstallers: IModuleInstaller[] = []; |
80 | | - |
81 | | - if (installers.length === 0) { |
82 | | - return []; |
83 | | - } |
84 | | - // group by priority and pick supported from the highest priority |
85 | | - installers.sort((a, b) => b.priority - a.priority); |
86 | | - |
87 | | - let currentPri = installers[0].priority; |
88 | | - |
89 | | - for (const mi of installers) { |
90 | | - if (mi.priority !== currentPri) { |
91 | | - if (supportedInstallers.length > 0) { |
92 | | - break; // return highest priority supported installers |
93 | | - } |
94 | | - // If none supported, try next priority group |
95 | | - currentPri = mi.priority; |
96 | | - } |
97 | | - |
98 | | - if (await mi.isSupported(resource)) { |
99 | | - supportedInstallers.push(mi); |
100 | | - } |
101 | | - } |
102 | | - |
103 | | - return supportedInstallers; |
104 | | - } |
105 | | - |
106 | | - public async showNoInstallersMessage(resource?: Uri): Promise<void> { |
107 | | - const interpreters = |
108 | | - this.serviceContainer.get<IInterpreterService>(IInterpreterService); |
109 | | - |
110 | | - const interpreter = await interpreters.getActiveInterpreter(resource); |
111 | | - |
112 | | - if (!interpreter) { |
113 | | - return; // Handled in the Python installation check. |
114 | | - } |
115 | | - |
116 | | - const appShell = |
117 | | - this.serviceContainer.get<IApplicationShell>(IApplicationShell); |
118 | | - |
119 | | - const search = "Search for help"; |
120 | | - |
121 | | - let result: string | undefined; |
122 | | - |
123 | | - if (interpreter.envType === EnvironmentType.Conda) { |
124 | | - result = await appShell.showErrorMessage( |
125 | | - Installer.noCondaOrPipInstaller(), |
126 | | - Installer.searchForHelp(), |
127 | | - ); |
128 | | - } else { |
129 | | - result = await appShell.showErrorMessage( |
130 | | - Installer.noPipInstaller(), |
131 | | - Installer.searchForHelp(), |
132 | | - ); |
133 | | - } |
134 | | - |
135 | | - if (result === search) { |
136 | | - const platform = |
137 | | - this.serviceContainer.get<IPlatformService>(IPlatformService); |
138 | | - |
139 | | - const osName = platform.isWindows |
140 | | - ? "Windows" |
141 | | - : platform.isMac |
142 | | - ? "MacOS" |
143 | | - : "Linux"; |
144 | | - |
145 | | - appShell.openUrl( |
146 | | - `https://www.bing.com/search?q=Install Pip ${osName} ${ |
147 | | - interpreter.envType === EnvironmentType.Conda ? "Conda" : "" |
148 | | - }`, |
149 | | - ); |
150 | | - } |
151 | | - } |
| 19 | + constructor(@inject(IServiceContainer) private serviceContainer: IServiceContainer) {} |
| 20 | + |
| 21 | + public async getInstallationChannel( |
| 22 | + product: Product, |
| 23 | + resource?: InterpreterUri, |
| 24 | + ): Promise<IModuleInstaller | undefined> { |
| 25 | + const channels = await this.getInstallationChannels(resource); |
| 26 | + if (channels.length === 1) { |
| 27 | + return channels[0]; |
| 28 | + } |
| 29 | + |
| 30 | + const productName = ProductNames.get(product)!; |
| 31 | + const appShell = this.serviceContainer.get<IApplicationShell>(IApplicationShell); |
| 32 | + if (channels.length === 0) { |
| 33 | + await this.showNoInstallersMessage(isResource(resource) ? resource : undefined); |
| 34 | + return; |
| 35 | + } |
| 36 | + |
| 37 | + const placeHolder = `Select an option to install ${productName}`; |
| 38 | + const options = channels.map((installer) => { |
| 39 | + return { |
| 40 | + label: `Install using ${installer.displayName}`, |
| 41 | + description: '', |
| 42 | + installer, |
| 43 | + }; |
| 44 | + }); |
| 45 | + const selection = await appShell.showQuickPick<typeof options[0]>(options, { |
| 46 | + matchOnDescription: true, |
| 47 | + matchOnDetail: true, |
| 48 | + placeHolder, |
| 49 | + }); |
| 50 | + return selection ? selection.installer : undefined; |
| 51 | + } |
| 52 | + |
| 53 | + public async getInstallationChannels(resource?: InterpreterUri): Promise<IModuleInstaller[]> { |
| 54 | + const installers = this.serviceContainer.getAll<IModuleInstaller>(IModuleInstaller); |
| 55 | + const supportedInstallers: IModuleInstaller[] = []; |
| 56 | + if (installers.length === 0) { |
| 57 | + return []; |
| 58 | + } |
| 59 | + // group by priority and pick supported from the highest priority |
| 60 | + installers.sort((a, b) => b.priority - a.priority); |
| 61 | + let currentPri = installers[0].priority; |
| 62 | + for (const mi of installers) { |
| 63 | + if (mi.priority !== currentPri) { |
| 64 | + if (supportedInstallers.length > 0) { |
| 65 | + break; // return highest priority supported installers |
| 66 | + } |
| 67 | + // If none supported, try next priority group |
| 68 | + currentPri = mi.priority; |
| 69 | + } |
| 70 | + if (await mi.isSupported(resource)) { |
| 71 | + supportedInstallers.push(mi); |
| 72 | + } |
| 73 | + } |
| 74 | + return supportedInstallers; |
| 75 | + } |
| 76 | + |
| 77 | + public async showNoInstallersMessage(resource?: Uri): Promise<void> { |
| 78 | + const interpreters = this.serviceContainer.get<IInterpreterService>(IInterpreterService); |
| 79 | + const interpreter = await interpreters.getActiveInterpreter(resource); |
| 80 | + if (!interpreter) { |
| 81 | + return; // Handled in the Python installation check. |
| 82 | + } |
| 83 | + |
| 84 | + const appShell = this.serviceContainer.get<IApplicationShell>(IApplicationShell); |
| 85 | + const search = 'Search for help'; |
| 86 | + let result: string | undefined; |
| 87 | + if (interpreter.envType === EnvironmentType.Conda) { |
| 88 | + result = await appShell.showErrorMessage(Installer.noCondaOrPipInstaller(), Installer.searchForHelp()); |
| 89 | + } else { |
| 90 | + result = await appShell.showErrorMessage(Installer.noPipInstaller(), Installer.searchForHelp()); |
| 91 | + } |
| 92 | + if (result === search) { |
| 93 | + const platform = this.serviceContainer.get<IPlatformService>(IPlatformService); |
| 94 | + const osName = platform.isWindows ? 'Windows' : platform.isMac ? 'MacOS' : 'Linux'; |
| 95 | + appShell.openUrl( |
| 96 | + `https://www.bing.com/search?q=Install Pip ${osName} ${ |
| 97 | + interpreter.envType === EnvironmentType.Conda ? 'Conda' : '' |
| 98 | + }`, |
| 99 | + ); |
| 100 | + } |
| 101 | + } |
152 | 102 | } |
0 commit comments