Skip to content

Commit cb4d48e

Browse files
authored
feat: improve package management (#279)
⚠️ BREAKING CHANGE: This PR has an API change that replaces `install` and `uninstall` methods on package manager with `manage`. Reasoning: Both the install and uninstall flows did very similar things. In all the implementations this was duplicating the steps. The idea here is to make it easier from the flow perspective. ![image](https://github.com/user-attachments/assets/53087fca-ddc9-44f4-bcb9-9b005264db56)
1 parent faab63f commit cb4d48e

20 files changed

+368
-497
lines changed

examples/sample1/src/api.ts

Lines changed: 53 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -48,23 +48,6 @@ export interface PythonCommandRunConfiguration {
4848
args?: string[];
4949
}
5050

51-
export enum TerminalShellType {
52-
powershell = 'powershell',
53-
powershellCore = 'powershellCore',
54-
commandPrompt = 'commandPrompt',
55-
gitbash = 'gitbash',
56-
bash = 'bash',
57-
zsh = 'zsh',
58-
ksh = 'ksh',
59-
fish = 'fish',
60-
cshell = 'cshell',
61-
tcshell = 'tcshell',
62-
nushell = 'nushell',
63-
wsl = 'wsl',
64-
xonsh = 'xonsh',
65-
unknown = 'unknown',
66-
}
67-
6851
/**
6952
* Contains details on how to use a particular python environment
7053
*
@@ -73,7 +56,7 @@ export enum TerminalShellType {
7356
* 2. If {@link PythonEnvironmentExecutionInfo.activatedRun} is not provided, then:
7457
* - If {@link PythonEnvironmentExecutionInfo.shellActivation} is provided and shell type is known, then that will be used.
7558
* - If {@link PythonEnvironmentExecutionInfo.shellActivation} is provided and shell type is not known, then:
76-
* - {@link TerminalShellType.unknown} will be used if provided.
59+
* - 'unknown' will be used if provided.
7760
* - {@link PythonEnvironmentExecutionInfo.activation} will be used otherwise.
7861
* - If {@link PythonEnvironmentExecutionInfo.shellActivation} is not provided, then {@link PythonEnvironmentExecutionInfo.activation} will be used.
7962
* - If {@link PythonEnvironmentExecutionInfo.activation} is not provided, then {@link PythonEnvironmentExecutionInfo.run} will be used.
@@ -82,7 +65,7 @@ export enum TerminalShellType {
8265
* 1. If {@link PythonEnvironmentExecutionInfo.shellActivation} is provided and shell type is known, then that will be used.
8366
* 2. If {@link PythonEnvironmentExecutionInfo.shellActivation} is provided and shell type is not known, then {@link PythonEnvironmentExecutionInfo.activation} will be used.
8467
* 3. If {@link PythonEnvironmentExecutionInfo.shellActivation} is not provided, then:
85-
* - {@link TerminalShellType.unknown} will be used if provided.
68+
* - 'unknown' will be used if provided.
8669
* - {@link PythonEnvironmentExecutionInfo.activation} will be used otherwise.
8770
* 4. If {@link PythonEnvironmentExecutionInfo.activation} is not provided, then {@link PythonEnvironmentExecutionInfo.run} will be used.
8871
*
@@ -107,11 +90,11 @@ export interface PythonEnvironmentExecutionInfo {
10790
/**
10891
* Details on how to activate an environment using a shell specific command.
10992
* If set this will override the {@link PythonEnvironmentExecutionInfo.activation}.
110-
* {@link TerminalShellType.unknown} is used if shell type is not known.
111-
* If {@link TerminalShellType.unknown} is not provided and shell type is not known then
93+
* 'unknown' is used if shell type is not known.
94+
* If 'unknown' is not provided and shell type is not known then
11295
* {@link PythonEnvironmentExecutionInfo.activation} if set.
11396
*/
114-
shellActivation?: Map<TerminalShellType, PythonCommandRunConfiguration[]>;
97+
shellActivation?: Map<string, PythonCommandRunConfiguration[]>;
11598

11699
/**
117100
* Details on how to deactivate an environment.
@@ -121,11 +104,11 @@ export interface PythonEnvironmentExecutionInfo {
121104
/**
122105
* Details on how to deactivate an environment using a shell specific command.
123106
* If set this will override the {@link PythonEnvironmentExecutionInfo.deactivation} property.
124-
* {@link TerminalShellType.unknown} is used if shell type is not known.
125-
* If {@link TerminalShellType.unknown} is not provided and shell type is not known then
107+
* 'unknown' is used if shell type is not known.
108+
* If 'unknown' is not provided and shell type is not known then
126109
* {@link PythonEnvironmentExecutionInfo.deactivation} if set.
127110
*/
128-
shellDeactivation?: Map<TerminalShellType, PythonCommandRunConfiguration[]>;
111+
shellDeactivation?: Map<string, PythonCommandRunConfiguration[]>;
129112
}
130113

131114
/**
@@ -592,20 +575,12 @@ export interface PackageManager {
592575
log?: LogOutputChannel;
593576

594577
/**
595-
* Installs packages in the specified Python environment.
578+
* Installs/Uninstall packages in the specified Python environment.
596579
* @param environment - The Python environment in which to install packages.
597580
* @param packages - The packages to install.
598581
* @returns A promise that resolves when the installation is complete.
599582
*/
600-
install(environment: PythonEnvironment, packages?: string[], options?: PackageInstallOptions): Promise<void>;
601-
602-
/**
603-
* Uninstalls packages from the specified Python environment.
604-
* @param environment - The Python environment from which to uninstall packages.
605-
* @param packages - The packages to uninstall, which can be an array of packages or strings.
606-
* @returns A promise that resolves when the uninstall is complete.
607-
*/
608-
uninstall(environment: PythonEnvironment, packages?: Package[] | string[]): Promise<void>;
583+
manage(environment: PythonEnvironment, options: PackageManagementOptions): Promise<void>;
609584

610585
/**
611586
* Refreshes the package list for the specified Python environment.
@@ -730,15 +705,47 @@ export interface DidChangePythonProjectsEventArgs {
730705
removed: PythonProject[];
731706
}
732707

733-
/**
734-
* Options for package installation.
735-
*/
736-
export interface PackageInstallOptions {
737-
/**
738-
* Upgrade the packages if it is already installed.
739-
*/
740-
upgrade?: boolean;
741-
}
708+
export type PackageManagementOptions =
709+
| {
710+
/**
711+
* Upgrade the packages if it is already installed.
712+
*/
713+
upgrade?: boolean;
714+
715+
/**
716+
* Show option to skip package installation
717+
*/
718+
showSkipOption?: boolean;
719+
/**
720+
* The list of packages to install.
721+
*/
722+
install: string[];
723+
724+
/**
725+
* The list of packages to uninstall.
726+
*/
727+
uninstall?: string[];
728+
}
729+
| {
730+
/**
731+
* Upgrade the packages if it is already installed.
732+
*/
733+
upgrade?: boolean;
734+
735+
/**
736+
* Show option to skip package installation
737+
*/
738+
showSkipOption?: boolean;
739+
/**
740+
* The list of packages to install.
741+
*/
742+
install?: string[];
743+
744+
/**
745+
* The list of packages to uninstall.
746+
*/
747+
uninstall: string[];
748+
};
742749

743750
export interface PythonProcess {
744751
/**
@@ -921,21 +928,13 @@ export interface PythonPackageItemApi {
921928

922929
export interface PythonPackageManagementApi {
923930
/**
924-
* Install packages into a Python Environment.
931+
* Install/Uninstall packages into a Python Environment.
925932
*
926933
* @param environment The Python Environment into which packages are to be installed.
927934
* @param packages The packages to install.
928935
* @param options Options for installing packages.
929936
*/
930-
installPackages(environment: PythonEnvironment, packages: string[], options?: PackageInstallOptions): Promise<void>;
931-
932-
/**
933-
* Uninstall packages from a Python Environment.
934-
*
935-
* @param environment The Python Environment from which packages are to be uninstalled.
936-
* @param packages The packages to uninstall.
937-
*/
938-
uninstallPackages(environment: PythonEnvironment, packages: PackageInfo[] | string[]): Promise<void>;
937+
managePackages(environment: PythonEnvironment, options: PackageManagementOptions): Promise<void>;
939938
}
940939

941940
export interface PythonPackageManagerApi

package-lock.json

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@
66
"publisher": "ms-python",
77
"preview": true,
88
"engines": {
9-
"vscode": "^1.99.0-20250317"
9+
"vscode": "^1.100.0-20250407"
1010
},
1111
"categories": [
1212
"Other"
1313
],
1414
"enabledApiProposals": [
15-
"terminalShellType",
1615
"terminalShellEnv"
1716
],
1817
"capabilities": {
@@ -142,7 +141,6 @@
142141
{
143142
"command": "python-envs.reset",
144143
"title": "%python-envs.reset.title%",
145-
"shortTitle": "Reset Environment",
146144
"category": "Python",
147145
"icon": "$(sync)"
148146
},
@@ -174,7 +172,6 @@
174172
{
175173
"command": "python-envs.packages",
176174
"title": "%python-envs.packages.title%",
177-
"shortTitle": "Modify Packages",
178175
"category": "Python",
179176
"icon": "$(package)"
180177
},
@@ -534,7 +531,7 @@
534531
"@types/node": "20.2.5",
535532
"@types/sinon": "^17.0.3",
536533
"@types/stack-trace": "0.0.29",
537-
"@types/vscode": "^1.97.0",
534+
"@types/vscode": "^1.99.0",
538535
"@types/which": "^3.0.4",
539536
"@typescript-eslint/eslint-plugin": "^8.16.0",
540537
"@typescript-eslint/parser": "^8.16.0",

package.nls.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@
1616
"python-envs.createAny.title": "Create Environment",
1717
"python-envs.set.title": "Set Workspace Environment",
1818
"python-envs.setEnv.title": "Set As Workspace Environment",
19-
"python-envs.reset.title": "Reset Environment Selection to Default",
19+
"python-envs.reset.title": "Reset to Default",
2020
"python-envs.remove.title": "Delete Environment",
2121
"python-envs.refreshAllManagers.title": "Refresh All Environment Managers",
2222
"python-envs.refreshManager.title": "Refresh Environments List",
2323
"python-envs.refreshPackages.title": "Refresh Packages List",
24-
"python-envs.packages.title": "Install or Remove Packages",
24+
"python-envs.packages.title": "Manage Packages",
2525
"python-envs.clearCache.title": "Clear Cache",
2626
"python-envs.runInTerminal.title": "Run in Terminal",
2727
"python-envs.createTerminal.title": "Create Python Terminal",

src/api.ts

Lines changed: 44 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -575,20 +575,12 @@ export interface PackageManager {
575575
log?: LogOutputChannel;
576576

577577
/**
578-
* Installs packages in the specified Python environment.
578+
* Installs/Uninstall packages in the specified Python environment.
579579
* @param environment - The Python environment in which to install packages.
580580
* @param packages - The packages to install.
581581
* @returns A promise that resolves when the installation is complete.
582582
*/
583-
install(environment: PythonEnvironment, packages?: string[], options?: PackageInstallOptions): Promise<void>;
584-
585-
/**
586-
* Uninstalls packages from the specified Python environment.
587-
* @param environment - The Python environment from which to uninstall packages.
588-
* @param packages - The packages to uninstall, which can be an array of packages or strings.
589-
* @returns A promise that resolves when the uninstall is complete.
590-
*/
591-
uninstall(environment: PythonEnvironment, packages?: Package[] | string[]): Promise<void>;
583+
manage(environment: PythonEnvironment, options: PackageManagementOptions): Promise<void>;
592584

593585
/**
594586
* Refreshes the package list for the specified Python environment.
@@ -713,20 +705,47 @@ export interface DidChangePythonProjectsEventArgs {
713705
removed: PythonProject[];
714706
}
715707

716-
/**
717-
* Options for package installation.
718-
*/
719-
export interface PackageInstallOptions {
720-
/**
721-
* Upgrade the packages if it is already installed.
722-
*/
723-
upgrade?: boolean;
708+
export type PackageManagementOptions =
709+
| {
710+
/**
711+
* Upgrade the packages if it is already installed.
712+
*/
713+
upgrade?: boolean;
724714

725-
/**
726-
* Show option to skip package installation
727-
*/
728-
showSkipOption?: boolean;
729-
}
715+
/**
716+
* Show option to skip package installation
717+
*/
718+
showSkipOption?: boolean;
719+
/**
720+
* The list of packages to install.
721+
*/
722+
install: string[];
723+
724+
/**
725+
* The list of packages to uninstall.
726+
*/
727+
uninstall?: string[];
728+
}
729+
| {
730+
/**
731+
* Upgrade the packages if it is already installed.
732+
*/
733+
upgrade?: boolean;
734+
735+
/**
736+
* Show option to skip package installation
737+
*/
738+
showSkipOption?: boolean;
739+
/**
740+
* The list of packages to install.
741+
*/
742+
install?: string[];
743+
744+
/**
745+
* The list of packages to uninstall.
746+
*/
747+
uninstall: string[];
748+
};
730749

731750
export interface PythonProcess {
732751
/**
@@ -909,21 +928,13 @@ export interface PythonPackageItemApi {
909928

910929
export interface PythonPackageManagementApi {
911930
/**
912-
* Install packages into a Python Environment.
931+
* Install/Uninstall packages into a Python Environment.
913932
*
914933
* @param environment The Python Environment into which packages are to be installed.
915934
* @param packages The packages to install.
916935
* @param options Options for installing packages.
917936
*/
918-
installPackages(environment: PythonEnvironment, packages: string[], options?: PackageInstallOptions): Promise<void>;
919-
920-
/**
921-
* Uninstall packages from a Python Environment.
922-
*
923-
* @param environment The Python Environment from which packages are to be uninstalled.
924-
* @param packages The packages to uninstall.
925-
*/
926-
uninstallPackages(environment: PythonEnvironment, packages: PackageInfo[] | string[]): Promise<void>;
937+
managePackages(environment: PythonEnvironment, options: PackageManagementOptions): Promise<void>;
927938
}
928939

929940
export interface PythonPackageManagerApi

0 commit comments

Comments
 (0)