mirror of
https://github.com/astral-sh/uv.git
synced 2025-10-17 05:47:45 +00:00
Enable freeze
and list
to introspect non-virtualenv Pythons (#2033)
## Summary Now that we have the ability to introspect the installed packages for arbitrary Pythons, we can allow `pip freeze` and `pip list` to fall back to the "default" Python, if no virtualenv is present. Closes https://github.com/astral-sh/uv/issues/2005.
This commit is contained in:
parent
23afa09fae
commit
02703281f0
6 changed files with 74 additions and 10 deletions
|
@ -68,7 +68,7 @@ pub fn find_requested_python(
|
|||
}
|
||||
}
|
||||
|
||||
/// Pick a sensible default for the python a user wants when they didn't specify a version.
|
||||
/// Pick a sensible default for the Python a user wants when they didn't specify a version.
|
||||
///
|
||||
/// We prefer the test overwrite `UV_TEST_PYTHON_PATH` if it is set, otherwise `python3`/`python` or
|
||||
/// `python.exe` respectively.
|
||||
|
|
|
@ -9,7 +9,7 @@ use uv_fs::{LockedFile, Normalized};
|
|||
|
||||
use crate::cfg::PyVenvConfiguration;
|
||||
use crate::python_platform::PythonPlatform;
|
||||
use crate::{find_requested_python, Error, Interpreter};
|
||||
use crate::{find_default_python, find_requested_python, Error, Interpreter};
|
||||
|
||||
/// A Python executable and its associated platform markers.
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -65,6 +65,15 @@ impl Virtualenv {
|
|||
})
|
||||
}
|
||||
|
||||
/// Create a [`Virtualenv`] for the default Python interpreter.
|
||||
pub fn from_default_python(platform: &Platform, cache: &Cache) -> Result<Self, Error> {
|
||||
let interpreter = find_default_python(platform, cache)?;
|
||||
Ok(Self {
|
||||
root: interpreter.base_prefix().to_path_buf(),
|
||||
interpreter,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the location of the Python interpreter.
|
||||
pub fn root(&self) -> &Path {
|
||||
&self.root
|
||||
|
|
|
@ -12,8 +12,8 @@ use crate::printer::Printer;
|
|||
|
||||
/// Clear the cache.
|
||||
pub(crate) fn cache_clean(
|
||||
cache: &Cache,
|
||||
packages: &[PackageName],
|
||||
cache: &Cache,
|
||||
mut printer: Printer,
|
||||
) -> Result<ExitStatus> {
|
||||
if !cache.root().exists() {
|
||||
|
|
|
@ -17,10 +17,25 @@ use crate::commands::ExitStatus;
|
|||
use crate::printer::Printer;
|
||||
|
||||
/// Enumerate the installed packages in the current environment.
|
||||
pub(crate) fn pip_freeze(cache: &Cache, strict: bool, mut printer: Printer) -> Result<ExitStatus> {
|
||||
pub(crate) fn pip_freeze(
|
||||
strict: bool,
|
||||
python: Option<&str>,
|
||||
cache: &Cache,
|
||||
mut printer: Printer,
|
||||
) -> Result<ExitStatus> {
|
||||
// Detect the current Python interpreter.
|
||||
let platform = Platform::current()?;
|
||||
let venv = Virtualenv::from_env(platform, cache)?;
|
||||
let venv = if let Some(python) = python {
|
||||
Virtualenv::from_requested_python(python, &platform, cache)?
|
||||
} else {
|
||||
match Virtualenv::from_env(platform.clone(), cache) {
|
||||
Ok(venv) => venv,
|
||||
Err(uv_interpreter::Error::VenvNotFound) => {
|
||||
Virtualenv::from_default_python(&platform, cache)?
|
||||
}
|
||||
Err(err) => return Err(err.into()),
|
||||
}
|
||||
};
|
||||
|
||||
debug!(
|
||||
"Using Python {} environment at {}",
|
||||
|
|
|
@ -21,16 +21,27 @@ use crate::printer::Printer;
|
|||
|
||||
/// Enumerate the installed packages in the current environment.
|
||||
pub(crate) fn pip_list(
|
||||
cache: &Cache,
|
||||
strict: bool,
|
||||
editable: bool,
|
||||
exclude_editable: bool,
|
||||
exclude: &[PackageName],
|
||||
python: Option<&str>,
|
||||
cache: &Cache,
|
||||
mut printer: Printer,
|
||||
) -> Result<ExitStatus> {
|
||||
// Detect the current Python interpreter.
|
||||
let platform = Platform::current()?;
|
||||
let venv = Virtualenv::from_env(platform, cache)?;
|
||||
let venv = if let Some(python) = python {
|
||||
Virtualenv::from_requested_python(python, &platform, cache)?
|
||||
} else {
|
||||
match Virtualenv::from_env(platform.clone(), cache) {
|
||||
Ok(venv) => venv,
|
||||
Err(uv_interpreter::Error::VenvNotFound) => {
|
||||
Virtualenv::from_default_python(&platform, cache)?
|
||||
}
|
||||
Err(err) => return Err(err.into()),
|
||||
}
|
||||
};
|
||||
|
||||
debug!(
|
||||
"Using Python {} environment at {}",
|
||||
|
|
|
@ -730,6 +730,20 @@ struct PipFreezeArgs {
|
|||
/// issues.
|
||||
#[clap(long)]
|
||||
strict: bool,
|
||||
|
||||
/// The Python interpreter for which packages should be listed.
|
||||
///
|
||||
/// By default, `uv` lists packages in the currently activated virtual environment, or a virtual
|
||||
/// environment (`.venv`) located in the current working directory or any parent directory,
|
||||
/// falling back to the system Python if no virtual environment is found.
|
||||
///
|
||||
/// Supported formats:
|
||||
/// - `3.10` looks for an installed Python 3.10 using `py --list-paths` on Windows, or
|
||||
/// `python3.10` on Linux and macOS. (Specifying a patch version is not supported.)
|
||||
/// - `python3.10` or `python.exe` looks for a binary with the given name in `PATH`.
|
||||
/// - `/home/ferris/.local/bin/python3.10` uses the exact Python at the given path.
|
||||
#[clap(long, short, verbatim_doc_comment)]
|
||||
python: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Args)]
|
||||
|
@ -751,6 +765,20 @@ struct PipListArgs {
|
|||
/// Exclude the specified package(s) from the output.
|
||||
#[clap(long)]
|
||||
r#exclude: Vec<PackageName>,
|
||||
|
||||
/// The Python interpreter for which packages should be listed.
|
||||
///
|
||||
/// By default, `uv` lists packages in the currently activated virtual environment, or a virtual
|
||||
/// environment (`.venv`) located in the current working directory or any parent directory,
|
||||
/// falling back to the system Python if no virtual environment is found.
|
||||
///
|
||||
/// Supported formats:
|
||||
/// - `3.10` looks for an installed Python 3.10 using `py --list-paths` on Windows, or
|
||||
/// `python3.10` on Linux and macOS. (Specifying a patch version is not supported.)
|
||||
/// - `python3.10` or `python.exe` looks for a binary with the given name in `PATH`.
|
||||
/// - `/home/ferris/.local/bin/python3.10` uses the exact Python at the given path.
|
||||
#[clap(long, short, verbatim_doc_comment)]
|
||||
python: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Args)]
|
||||
|
@ -1160,21 +1188,22 @@ async fn run() -> Result<ExitStatus> {
|
|||
}
|
||||
Commands::Pip(PipNamespace {
|
||||
command: PipCommand::Freeze(args),
|
||||
}) => commands::pip_freeze(&cache, args.strict, printer),
|
||||
}) => commands::pip_freeze(args.strict, args.python.as_deref(), &cache, printer),
|
||||
Commands::Pip(PipNamespace {
|
||||
command: PipCommand::List(args),
|
||||
}) => commands::pip_list(
|
||||
&cache,
|
||||
args.strict,
|
||||
args.editable,
|
||||
args.exclude_editable,
|
||||
&args.exclude,
|
||||
args.python.as_deref(),
|
||||
&cache,
|
||||
printer,
|
||||
),
|
||||
Commands::Cache(CacheNamespace {
|
||||
command: CacheCommand::Clean(args),
|
||||
})
|
||||
| Commands::Clean(args) => commands::cache_clean(&cache, &args.package, printer),
|
||||
| Commands::Clean(args) => commands::cache_clean(&args.package, &cache, printer),
|
||||
Commands::Cache(CacheNamespace {
|
||||
command: CacheCommand::Dir,
|
||||
}) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue