Distinguish between direct and transitive packages#1530
Merged
Conversation
Member
|
do you have a screenshot of what this would look like? and how do you see it working for other pkg managers? |
8f270b3 to
1bd1f7b
Compare
Contributor
Author
|
Depends on #1538 |
3eed7fb to
e6467d6
Compare
Base automatically changed from
vscode-python-environments-package-refactor
to
main
June 11, 2026 22:26
e6467d6 to
3f579f5
Compare
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Log parse failures in parsePipListJson() instead of silently returning [] - Make isTransitive readonly on PackageInfo and PythonPackageImpl - Rename fetchDirectPackageNames to getDirectPackageNames in public API - Fix JSDoc to say Set instead of array - Add isTransitive to public API PackageInfo - Localize transitive uninstall confirmation and (transitive) prefix - Respect pkg.iconPath, only fallback to ThemeIcon - Wrap getDirectPackageNames in try/catch for error isolation - Use poetry show --top-level instead of --tree; fix glyph regex - Only refresh packages when cache is empty, not on every expansion - Add unit tests for parsePipListJson, parseUvTree, and error handling Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
Author
|
Addressed all review comments in the latest commit. See individual replies on each comment thread for details. |
edvilme
commented
Jun 12, 2026
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| * @param environment - The Python environment for which to fetch direct package names. | ||
| * @returns A promise that resolves to a set of package name strings, or undefined if not supported. | ||
| */ | ||
| getDirectPackageNames?(environment: PythonEnvironment): Promise<Set<string> | undefined>; |
Contributor
There was a problem hiding this comment.
Is it implemented for conda? Seems not covered
Contributor
Author
There was a problem hiding this comment.
Conda doesn't have a direct mechanism for getting direct packages, only conda env export --from-history which isn't strictly the same as direct or transitive packages, and can lead to more confusion
| /** | ||
| * Fetches the names of direct (non-transitive) packages for the specified Python environment. | ||
| * @param environment - The Python environment for which to fetch direct package names. | ||
| * @returns A promise that resolves to a set of package name strings, or undefined if not supported. |
Contributor
There was a problem hiding this comment.
Copilot generated: Two questions on this signature:
Set<string>is unusual on our public API surface;readonly string[]would be more consistent with the rest ofPackageManagerand easier for consumers to serialize/transport.- The three observable states — method not implemented, method returns
undefined, method returns an emptySet— all need documented semantics. The current consumer treats empty-set as "no info" (via asize > 0guard), which silently drops legitimately-empty results. Likewise, consumers ofPackageInfo.isTransitivecan't distinguishundefinedfromfalse; please document thatundefinedmeans "unknown".
Show a modal warning with 'Uninstall Anyway' / 'Cancel' instead of silently blocking uninstall of transitive packages. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…intent) pip list --not-required and uv pip tree --depth=0 return leaf packages (no dependents), not user-installed packages. Document this limitation on the PackageManager interface, pip implementation, and utility function. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Transitive packages now show a tooltip: 'This package is a dependency of another installed package. It may also have been explicitly installed.' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Include . in the extraction regex so dotted package names like zope.interface and ruamel.yaml are not truncated. Normalization via normalizePackageName (PEP 503) is already applied for comparison. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
eleanorjboyd
previously approved these changes
Jun 16, 2026
Replace the readonly-bypassing cast with object spread to create new enriched package objects. Original cached objects are not mutated, making the readonly contract genuinely respected. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
aeschli
approved these changes
Jun 16, 2026
DonJayamanne
approved these changes
Jun 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This pull request attempts to identify transitive packages in the user environment, and show indicators in the UI.
Problem
All installed packages, regardless of hierarchy are displayed equally in the sidebar. However, the relationships between them is not entirely obvious through the UI. This may cause (less experienced) users to get confused when they see packages they haven't explicitly installed, or to modify/delete transitive packages, potentially affecting their direct packages.
Hence, there needs to be a way to clearly distinguish between them, and provide guardrails to prevent unintended behaviour.
Proposal
Direct packages are detected through the built in commands of the package managers
pip list --not-required --format=jsonuv pip tree --depth 0poetry show --top-level --no-ansiconda env export --from-history*Packages shown are clearly identified as "Direct packages" or "Transitive" in the UI. Controls for uninstalling transitive packages are hidden to avoid unwanted behaviors.
Closes #524