-
Notifications
You must be signed in to change notification settings - Fork 760
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement uv pip show
#2115
Implement uv pip show
#2115
Changes from all commits
1ae4381
8bf37bd
c83fc7a
f0e66c3
7116117
aac3f9d
7f55fa0
503385b
1b006f1
638ba9c
dd04fd4
d3f934a
488c8af
de32a29
2504023
15bcc34
78fbb0c
1c62351
11bc92b
e6db72a
511652f
40097f3
aa562f9
2ed2754
7b7f807
e4ab93d
345f8d6
94bb603
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
use std::fmt::Write; | ||
|
||
use anyhow::Result; | ||
use owo_colors::OwoColorize; | ||
use tracing::debug; | ||
|
||
use anstream::{eprintln, println}; | ||
use distribution_types::Name; | ||
use platform_host::Platform; | ||
use uv_cache::Cache; | ||
use uv_fs::Simplified; | ||
use uv_installer::SitePackages; | ||
use uv_interpreter::PythonEnvironment; | ||
use uv_normalize::PackageName; | ||
|
||
use crate::commands::ExitStatus; | ||
use crate::printer::Printer; | ||
|
||
/// Show information about one or more installed packages. | ||
pub(crate) fn pip_show( | ||
mut packages: Vec<PackageName>, | ||
strict: bool, | ||
python: Option<&str>, | ||
system: bool, | ||
quiet: bool, | ||
cache: &Cache, | ||
mut printer: Printer, | ||
) -> Result<ExitStatus> { | ||
if packages.is_empty() { | ||
#[allow(clippy::print_stderr)] | ||
{ | ||
eprintln!( | ||
"{}{} Please provide a package name or names.", | ||
"warning".yellow().bold(), | ||
":".bold(), | ||
); | ||
} | ||
return Ok(ExitStatus::Failure); | ||
} | ||
|
||
// Detect the current Python interpreter. | ||
let platform = Platform::current()?; | ||
let venv = if let Some(python) = python { | ||
PythonEnvironment::from_requested_python(python, &platform, cache)? | ||
} else if system { | ||
PythonEnvironment::from_default_python(&platform, cache)? | ||
} else { | ||
match PythonEnvironment::from_virtualenv(platform.clone(), cache) { | ||
Ok(venv) => venv, | ||
Err(uv_interpreter::Error::VenvNotFound) => { | ||
PythonEnvironment::from_default_python(&platform, cache)? | ||
} | ||
Err(err) => return Err(err.into()), | ||
} | ||
}; | ||
|
||
debug!( | ||
"Using Python {} environment at {}", | ||
venv.interpreter().python_version(), | ||
venv.python_executable().simplified_display().cyan() | ||
); | ||
|
||
// Build the installed index. | ||
let site_packages = SitePackages::from_executable(&venv)?; | ||
|
||
// Sort and deduplicate the packages, which are keyed by name. | ||
packages.sort_unstable(); | ||
packages.dedup(); | ||
|
||
// Map to the local distributions. | ||
let distributions = { | ||
let mut distributions = Vec::with_capacity(packages.len()); | ||
|
||
// Identify all packages that are installed. | ||
for package in &packages { | ||
let installed = site_packages.get_packages(package); | ||
if installed.is_empty() { | ||
writeln!( | ||
printer, | ||
"{}{} Package(s) not found for: {}", | ||
"warning".yellow().bold(), | ||
":".bold(), | ||
package.as_ref().bold() | ||
)?; | ||
} else { | ||
distributions.extend(installed); | ||
} | ||
} | ||
|
||
distributions | ||
}; | ||
|
||
// Like `pip`, if no packages were found, return a failure. | ||
if distributions.is_empty() { | ||
return Ok(ExitStatus::Failure); | ||
} | ||
|
||
if !quiet { | ||
// Print the information for each package. | ||
let mut first = true; | ||
for distribution in &distributions { | ||
if first { | ||
first = false; | ||
} else { | ||
// Print a separator between packages. | ||
#[allow(clippy::print_stdout)] | ||
{ | ||
println!("---"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I also had to change these back to using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I improved the situation a bit here: #2227 |
||
} | ||
} | ||
|
||
// Print the name, version, and location (e.g., the `site-packages` directory). | ||
#[allow(clippy::print_stdout)] | ||
{ | ||
println!("Name: {}", distribution.name()); | ||
println!("Version: {}", distribution.version()); | ||
println!( | ||
"Location: {}", | ||
distribution | ||
.path() | ||
.parent() | ||
.expect("package path is not root") | ||
.simplified_display() | ||
); | ||
} | ||
} | ||
|
||
// Validate that the environment is consistent. | ||
if strict { | ||
for diagnostic in site_packages.diagnostics()? { | ||
writeln!( | ||
printer, | ||
"{}{} {}", | ||
"warning".yellow().bold(), | ||
":".bold(), | ||
diagnostic.message().bold() | ||
)?; | ||
} | ||
} | ||
} | ||
|
||
Ok(ExitStatus::Success) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ChannyClaus - I simplified things a bit here because this method only needs to accept a list of package names (unlike
uninstall
which needs to accept a list of requirements files, etc.).