mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 21:35:00 +00:00
Change "toolchain" to "python" (#4735)
Whew this is a lot. The user-facing changes are: - `uv toolchain` to `uv python` e.g. `uv python find`, `uv python install`, ... - `UV_TOOLCHAIN_DIR` to` UV_PYTHON_INSTALL_DIR` - `<UV_STATE_DIR>/toolchains` to `<UV_STATE_DIR>/python` (with [automatic migration](https://github.com/astral-sh/uv/pull/4735/files#r1663029330)) - User-facing messages no longer refer to toolchains, instead using "Python", "Python versions" or "Python installations" The internal changes are: - `uv-toolchain` crate to `uv-python` - `Toolchain` no longer referenced in type names - Dropped unused `SystemPython` type (previously replaced) - Clarified the type names for "managed Python installations" - (more little things)
This commit is contained in:
parent
60fd98a5e4
commit
dd7da6af5f
105 changed files with 2629 additions and 2603 deletions
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
|
@ -135,7 +135,7 @@ jobs:
|
||||||
|
|
||||||
- name: "Install required Python versions"
|
- name: "Install required Python versions"
|
||||||
run: |
|
run: |
|
||||||
cargo run toolchain install
|
cargo run python install
|
||||||
|
|
||||||
- name: "Install cargo nextest"
|
- name: "Install cargo nextest"
|
||||||
uses: taiki-e/install-action@v2
|
uses: taiki-e/install-action@v2
|
||||||
|
@ -172,7 +172,7 @@ jobs:
|
||||||
|
|
||||||
- name: "Install required Python versions"
|
- name: "Install required Python versions"
|
||||||
run: |
|
run: |
|
||||||
cargo run toolchain install
|
cargo run python install
|
||||||
|
|
||||||
- name: "Install cargo nextest"
|
- name: "Install cargo nextest"
|
||||||
uses: taiki-e/install-action@v2
|
uses: taiki-e/install-action@v2
|
||||||
|
|
|
@ -42,7 +42,7 @@ Testing uv requires multiple specific Python versions; they can be installed wit
|
||||||
cargo run toolchain install
|
cargo run toolchain install
|
||||||
```
|
```
|
||||||
|
|
||||||
The storage directory can be configured with `UV_TOOLCHAIN_DIR`.
|
The storage directory can be configured with `UV_PYTHON_INSTALL_DIR`.
|
||||||
|
|
||||||
### Local testing
|
### Local testing
|
||||||
|
|
||||||
|
|
116
Cargo.lock
generated
116
Cargo.lock
generated
|
@ -408,8 +408,8 @@ dependencies = [
|
||||||
"uv-dispatch",
|
"uv-dispatch",
|
||||||
"uv-distribution",
|
"uv-distribution",
|
||||||
"uv-git",
|
"uv-git",
|
||||||
|
"uv-python",
|
||||||
"uv-resolver",
|
"uv-resolver",
|
||||||
"uv-toolchain",
|
|
||||||
"uv-types",
|
"uv-types",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -4483,12 +4483,12 @@ dependencies = [
|
||||||
"uv-git",
|
"uv-git",
|
||||||
"uv-installer",
|
"uv-installer",
|
||||||
"uv-normalize",
|
"uv-normalize",
|
||||||
|
"uv-python",
|
||||||
"uv-requirements",
|
"uv-requirements",
|
||||||
"uv-resolver",
|
"uv-resolver",
|
||||||
"uv-scripts",
|
"uv-scripts",
|
||||||
"uv-settings",
|
"uv-settings",
|
||||||
"uv-tool",
|
"uv-tool",
|
||||||
"uv-toolchain",
|
|
||||||
"uv-types",
|
"uv-types",
|
||||||
"uv-virtualenv",
|
"uv-virtualenv",
|
||||||
"uv-warnings",
|
"uv-warnings",
|
||||||
|
@ -4543,7 +4543,7 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
"uv-configuration",
|
"uv-configuration",
|
||||||
"uv-fs",
|
"uv-fs",
|
||||||
"uv-toolchain",
|
"uv-python",
|
||||||
"uv-types",
|
"uv-types",
|
||||||
"uv-virtualenv",
|
"uv-virtualenv",
|
||||||
]
|
]
|
||||||
|
@ -4587,9 +4587,9 @@ dependencies = [
|
||||||
"uv-cache",
|
"uv-cache",
|
||||||
"uv-configuration",
|
"uv-configuration",
|
||||||
"uv-normalize",
|
"uv-normalize",
|
||||||
|
"uv-python",
|
||||||
"uv-resolver",
|
"uv-resolver",
|
||||||
"uv-settings",
|
"uv-settings",
|
||||||
"uv-toolchain",
|
|
||||||
"uv-version",
|
"uv-version",
|
||||||
"uv-warnings",
|
"uv-warnings",
|
||||||
]
|
]
|
||||||
|
@ -4699,9 +4699,9 @@ dependencies = [
|
||||||
"uv-distribution",
|
"uv-distribution",
|
||||||
"uv-git",
|
"uv-git",
|
||||||
"uv-installer",
|
"uv-installer",
|
||||||
|
"uv-python",
|
||||||
"uv-resolver",
|
"uv-resolver",
|
||||||
"uv-settings",
|
"uv-settings",
|
||||||
"uv-toolchain",
|
|
||||||
"uv-types",
|
"uv-types",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
]
|
]
|
||||||
|
@ -4725,8 +4725,8 @@ dependencies = [
|
||||||
"uv-distribution",
|
"uv-distribution",
|
||||||
"uv-git",
|
"uv-git",
|
||||||
"uv-installer",
|
"uv-installer",
|
||||||
|
"uv-python",
|
||||||
"uv-resolver",
|
"uv-resolver",
|
||||||
"uv-toolchain",
|
|
||||||
"uv-types",
|
"uv-types",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -4871,7 +4871,7 @@ dependencies = [
|
||||||
"uv-fs",
|
"uv-fs",
|
||||||
"uv-git",
|
"uv-git",
|
||||||
"uv-normalize",
|
"uv-normalize",
|
||||||
"uv-toolchain",
|
"uv-python",
|
||||||
"uv-types",
|
"uv-types",
|
||||||
"uv-warnings",
|
"uv-warnings",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
|
@ -4894,6 +4894,52 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uv-python"
|
||||||
|
version = "0.0.1"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"assert_fs",
|
||||||
|
"cache-key",
|
||||||
|
"clap",
|
||||||
|
"configparser",
|
||||||
|
"fs-err",
|
||||||
|
"futures",
|
||||||
|
"indoc",
|
||||||
|
"install-wheel-rs",
|
||||||
|
"itertools 0.13.0",
|
||||||
|
"once_cell",
|
||||||
|
"pep440_rs",
|
||||||
|
"pep508_rs",
|
||||||
|
"platform-tags",
|
||||||
|
"pypi-types",
|
||||||
|
"regex",
|
||||||
|
"reqwest",
|
||||||
|
"reqwest-middleware",
|
||||||
|
"rmp-serde",
|
||||||
|
"same-file",
|
||||||
|
"schemars",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"target-lexicon",
|
||||||
|
"temp-env",
|
||||||
|
"tempfile",
|
||||||
|
"test-log",
|
||||||
|
"thiserror",
|
||||||
|
"tokio-util",
|
||||||
|
"tracing",
|
||||||
|
"url",
|
||||||
|
"uv-cache",
|
||||||
|
"uv-client",
|
||||||
|
"uv-configuration",
|
||||||
|
"uv-extract",
|
||||||
|
"uv-fs",
|
||||||
|
"uv-state",
|
||||||
|
"uv-warnings",
|
||||||
|
"which",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uv-requirements"
|
name = "uv-requirements"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -4974,7 +5020,7 @@ dependencies = [
|
||||||
"uv-distribution",
|
"uv-distribution",
|
||||||
"uv-git",
|
"uv-git",
|
||||||
"uv-normalize",
|
"uv-normalize",
|
||||||
"uv-toolchain",
|
"uv-python",
|
||||||
"uv-types",
|
"uv-types",
|
||||||
"uv-warnings",
|
"uv-warnings",
|
||||||
]
|
]
|
||||||
|
@ -5014,8 +5060,8 @@ dependencies = [
|
||||||
"uv-fs",
|
"uv-fs",
|
||||||
"uv-macros",
|
"uv-macros",
|
||||||
"uv-normalize",
|
"uv-normalize",
|
||||||
|
"uv-python",
|
||||||
"uv-resolver",
|
"uv-resolver",
|
||||||
"uv-toolchain",
|
|
||||||
"uv-warnings",
|
"uv-warnings",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -5047,58 +5093,12 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
"uv-cache",
|
"uv-cache",
|
||||||
"uv-fs",
|
"uv-fs",
|
||||||
|
"uv-python",
|
||||||
"uv-state",
|
"uv-state",
|
||||||
"uv-toolchain",
|
|
||||||
"uv-virtualenv",
|
"uv-virtualenv",
|
||||||
"uv-warnings",
|
"uv-warnings",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "uv-toolchain"
|
|
||||||
version = "0.0.1"
|
|
||||||
dependencies = [
|
|
||||||
"anyhow",
|
|
||||||
"assert_fs",
|
|
||||||
"cache-key",
|
|
||||||
"clap",
|
|
||||||
"configparser",
|
|
||||||
"fs-err",
|
|
||||||
"futures",
|
|
||||||
"indoc",
|
|
||||||
"install-wheel-rs",
|
|
||||||
"itertools 0.13.0",
|
|
||||||
"once_cell",
|
|
||||||
"pep440_rs",
|
|
||||||
"pep508_rs",
|
|
||||||
"platform-tags",
|
|
||||||
"pypi-types",
|
|
||||||
"regex",
|
|
||||||
"reqwest",
|
|
||||||
"reqwest-middleware",
|
|
||||||
"rmp-serde",
|
|
||||||
"same-file",
|
|
||||||
"schemars",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"target-lexicon",
|
|
||||||
"temp-env",
|
|
||||||
"tempfile",
|
|
||||||
"test-log",
|
|
||||||
"thiserror",
|
|
||||||
"tokio-util",
|
|
||||||
"tracing",
|
|
||||||
"url",
|
|
||||||
"uv-cache",
|
|
||||||
"uv-client",
|
|
||||||
"uv-configuration",
|
|
||||||
"uv-extract",
|
|
||||||
"uv-fs",
|
|
||||||
"uv-state",
|
|
||||||
"uv-warnings",
|
|
||||||
"which",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uv-types"
|
name = "uv-types"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
|
@ -5116,7 +5116,7 @@ dependencies = [
|
||||||
"uv-configuration",
|
"uv-configuration",
|
||||||
"uv-git",
|
"uv-git",
|
||||||
"uv-normalize",
|
"uv-normalize",
|
||||||
"uv-toolchain",
|
"uv-python",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -5135,7 +5135,7 @@ dependencies = [
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tracing",
|
"tracing",
|
||||||
"uv-fs",
|
"uv-fs",
|
||||||
"uv-toolchain",
|
"uv-python",
|
||||||
"uv-version",
|
"uv-version",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ uv-scripts = { path = "crates/uv-scripts" }
|
||||||
uv-settings = { path = "crates/uv-settings" }
|
uv-settings = { path = "crates/uv-settings" }
|
||||||
uv-state = { path = "crates/uv-state" }
|
uv-state = { path = "crates/uv-state" }
|
||||||
uv-tool = { path = "crates/uv-tool" }
|
uv-tool = { path = "crates/uv-tool" }
|
||||||
uv-toolchain = { path = "crates/uv-toolchain" }
|
uv-python = { path = "crates/uv-python" }
|
||||||
uv-types = { path = "crates/uv-types" }
|
uv-types = { path = "crates/uv-types" }
|
||||||
uv-version = { path = "crates/uv-version" }
|
uv-version = { path = "crates/uv-version" }
|
||||||
uv-virtualenv = { path = "crates/uv-virtualenv" }
|
uv-virtualenv = { path = "crates/uv-virtualenv" }
|
||||||
|
|
|
@ -89,7 +89,7 @@ Functionality for interacting with Git repositories.
|
||||||
|
|
||||||
Functionality for installing Python packages into a virtual environment.
|
Functionality for installing Python packages into a virtual environment.
|
||||||
|
|
||||||
## [uv-toolchain](./uv-toolchain)
|
## [uv-python](./uv-python)
|
||||||
|
|
||||||
Functionality for detecting and leveraging the current Python interpreter.
|
Functionality for detecting and leveraging the current Python interpreter.
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ uv-configuration = { workspace = true }
|
||||||
uv-dispatch = { workspace = true }
|
uv-dispatch = { workspace = true }
|
||||||
uv-distribution = { workspace = true }
|
uv-distribution = { workspace = true }
|
||||||
uv-git = { workspace = true }
|
uv-git = { workspace = true }
|
||||||
uv-toolchain = { workspace = true }
|
uv-python = { workspace = true }
|
||||||
uv-resolver = { workspace = true }
|
uv-resolver = { workspace = true }
|
||||||
uv-types = { workspace = true }
|
uv-types = { workspace = true }
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,8 @@ use bench::criterion::{criterion_group, criterion_main, measurement::WallTime, C
|
||||||
use pypi_types::Requirement;
|
use pypi_types::Requirement;
|
||||||
use uv_cache::Cache;
|
use uv_cache::Cache;
|
||||||
use uv_client::RegistryClientBuilder;
|
use uv_client::RegistryClientBuilder;
|
||||||
|
use uv_python::PythonEnvironment;
|
||||||
use uv_resolver::Manifest;
|
use uv_resolver::Manifest;
|
||||||
use uv_toolchain::PythonEnvironment;
|
|
||||||
|
|
||||||
fn resolve_warm_jupyter(c: &mut Criterion<WallTime>) {
|
fn resolve_warm_jupyter(c: &mut Criterion<WallTime>) {
|
||||||
let runtime = &tokio::runtime::Builder::new_current_thread()
|
let runtime = &tokio::runtime::Builder::new_current_thread()
|
||||||
|
@ -87,11 +87,11 @@ mod resolver {
|
||||||
use uv_dispatch::BuildDispatch;
|
use uv_dispatch::BuildDispatch;
|
||||||
use uv_distribution::DistributionDatabase;
|
use uv_distribution::DistributionDatabase;
|
||||||
use uv_git::GitResolver;
|
use uv_git::GitResolver;
|
||||||
|
use uv_python::PythonEnvironment;
|
||||||
use uv_resolver::{
|
use uv_resolver::{
|
||||||
FlatIndex, InMemoryIndex, Manifest, OptionsBuilder, PythonRequirement, ResolutionGraph,
|
FlatIndex, InMemoryIndex, Manifest, OptionsBuilder, PythonRequirement, ResolutionGraph,
|
||||||
Resolver,
|
Resolver,
|
||||||
};
|
};
|
||||||
use uv_toolchain::PythonEnvironment;
|
|
||||||
use uv_types::{BuildIsolation, EmptyInstalledPackages, HashStrategy, InFlight};
|
use uv_types::{BuildIsolation, EmptyInstalledPackages, HashStrategy, InFlight};
|
||||||
|
|
||||||
static MARKERS: Lazy<MarkerEnvironment> = Lazy::new(|| {
|
static MARKERS: Lazy<MarkerEnvironment> = Lazy::new(|| {
|
||||||
|
|
|
@ -20,7 +20,7 @@ pep508_rs = { workspace = true }
|
||||||
pypi-types = { workspace = true }
|
pypi-types = { workspace = true }
|
||||||
uv-configuration = { workspace = true }
|
uv-configuration = { workspace = true }
|
||||||
uv-fs = { workspace = true }
|
uv-fs = { workspace = true }
|
||||||
uv-toolchain = { workspace = true }
|
uv-python = { workspace = true }
|
||||||
uv-types = { workspace = true }
|
uv-types = { workspace = true }
|
||||||
uv-virtualenv = { workspace = true }
|
uv-virtualenv = { workspace = true }
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ use pep508_rs::PackageName;
|
||||||
use pypi_types::{Requirement, VerbatimParsedUrl};
|
use pypi_types::{Requirement, VerbatimParsedUrl};
|
||||||
use uv_configuration::{BuildKind, ConfigSettings, SetupPyStrategy};
|
use uv_configuration::{BuildKind, ConfigSettings, SetupPyStrategy};
|
||||||
use uv_fs::{rename_with_retry, PythonExt, Simplified};
|
use uv_fs::{rename_with_retry, PythonExt, Simplified};
|
||||||
use uv_toolchain::{Interpreter, PythonEnvironment};
|
use uv_python::{Interpreter, PythonEnvironment};
|
||||||
use uv_types::{BuildContext, BuildIsolation, SourceBuildTrait};
|
use uv_types::{BuildContext, BuildIsolation, SourceBuildTrait};
|
||||||
|
|
||||||
/// e.g. `pygraphviz/graphviz_wrap.c:3020:10: fatal error: graphviz/cgraph.h: No such file or directory`
|
/// e.g. `pygraphviz/graphviz_wrap.c:3020:10: fatal error: graphviz/cgraph.h: No such file or directory`
|
||||||
|
|
|
@ -21,7 +21,7 @@ uv-configuration = { workspace = true, features = ["clap"] }
|
||||||
uv-normalize = { workspace = true }
|
uv-normalize = { workspace = true }
|
||||||
uv-resolver = { workspace = true, features = ["clap"] }
|
uv-resolver = { workspace = true, features = ["clap"] }
|
||||||
uv-settings = { workspace = true, features = ["schemars"] }
|
uv-settings = { workspace = true, features = ["schemars"] }
|
||||||
uv-toolchain = { workspace = true, features = ["clap", "schemars"]}
|
uv-python = { workspace = true, features = ["clap", "schemars"]}
|
||||||
uv-version = { workspace = true }
|
uv-version = { workspace = true }
|
||||||
uv-warnings = { workspace = true }
|
uv-warnings = { workspace = true }
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,8 @@ use uv_configuration::{
|
||||||
ConfigSettingEntry, IndexStrategy, KeyringProviderType, PackageNameSpecifier, TargetTriple,
|
ConfigSettingEntry, IndexStrategy, KeyringProviderType, PackageNameSpecifier, TargetTriple,
|
||||||
};
|
};
|
||||||
use uv_normalize::{ExtraName, PackageName};
|
use uv_normalize::{ExtraName, PackageName};
|
||||||
|
use uv_python::{PythonFetch, PythonPreference, PythonVersion};
|
||||||
use uv_resolver::{AnnotationStyle, ExcludeNewer, PreReleaseMode, ResolutionMode};
|
use uv_resolver::{AnnotationStyle, ExcludeNewer, PreReleaseMode, ResolutionMode};
|
||||||
use uv_toolchain::{PythonVersion, ToolchainFetch, ToolchainPreference};
|
|
||||||
|
|
||||||
pub mod compat;
|
pub mod compat;
|
||||||
pub mod options;
|
pub mod options;
|
||||||
|
@ -118,13 +118,13 @@ pub struct GlobalArgs {
|
||||||
#[arg(global = true, long, overrides_with("offline"), hide = true)]
|
#[arg(global = true, long, overrides_with("offline"), hide = true)]
|
||||||
pub no_offline: bool,
|
pub no_offline: bool,
|
||||||
|
|
||||||
/// Whether to prefer Python toolchains from uv or on the system.
|
/// Whether to prefer using Python from uv or on the system.
|
||||||
#[arg(global = true, long)]
|
#[arg(global = true, long)]
|
||||||
pub toolchain_preference: Option<ToolchainPreference>,
|
pub python_preference: Option<PythonPreference>,
|
||||||
|
|
||||||
/// Whether to automatically download Python toolchains when required.
|
/// Whether to automatically download Python when required.
|
||||||
#[arg(global = true, long)]
|
#[arg(global = true, long)]
|
||||||
pub toolchain_fetch: Option<ToolchainFetch>,
|
pub python_fetch: Option<PythonFetch>,
|
||||||
|
|
||||||
/// Whether to enable experimental, preview features.
|
/// Whether to enable experimental, preview features.
|
||||||
#[arg(global = true, long, hide = true, env = "UV_PREVIEW", value_parser = clap::builder::BoolishValueParser::new(), overrides_with("no_preview"))]
|
#[arg(global = true, long, hide = true, env = "UV_PREVIEW", value_parser = clap::builder::BoolishValueParser::new(), overrides_with("no_preview"))]
|
||||||
|
@ -173,7 +173,7 @@ pub enum Commands {
|
||||||
/// Run and manage executable Python packages.
|
/// Run and manage executable Python packages.
|
||||||
Tool(ToolNamespace),
|
Tool(ToolNamespace),
|
||||||
/// Manage Python installations.
|
/// Manage Python installations.
|
||||||
Toolchain(ToolchainNamespace),
|
Python(PythonNamespace),
|
||||||
/// Manage Python projects.
|
/// Manage Python projects.
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
Project(ProjectCommand),
|
Project(ProjectCommand),
|
||||||
|
@ -2020,72 +2020,71 @@ pub struct ToolUninstallArgs {
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
#[allow(clippy::struct_excessive_bools)]
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
pub struct ToolchainNamespace {
|
pub struct PythonNamespace {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
pub command: ToolchainCommand,
|
pub command: PythonCommand,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
pub enum ToolchainCommand {
|
pub enum PythonCommand {
|
||||||
/// List the available toolchains.
|
/// List the available Python installations.
|
||||||
List(ToolchainListArgs),
|
List(PythonListArgs),
|
||||||
|
|
||||||
/// Download and install toolchains.
|
/// Download and install Python versions.
|
||||||
Install(ToolchainInstallArgs),
|
Install(PythonInstallArgs),
|
||||||
|
|
||||||
/// Search for a toolchain.
|
/// Search for a Python installation.
|
||||||
#[command(disable_version_flag = true)]
|
Find(PythonFindArgs),
|
||||||
Find(ToolchainFindArgs),
|
|
||||||
|
|
||||||
/// Show the toolchains directory.
|
/// Show the uv Python installation directory.
|
||||||
Dir,
|
Dir,
|
||||||
|
|
||||||
/// Uninstall toolchains.
|
/// Uninstall Python versions.
|
||||||
Uninstall(ToolchainUninstallArgs),
|
Uninstall(PythonUninstallArgs),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
#[allow(clippy::struct_excessive_bools)]
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
pub struct ToolchainListArgs {
|
pub struct PythonListArgs {
|
||||||
/// List all toolchain versions, including outdated patch versions.
|
/// List all Python versions, including outdated patch versions.
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub all_versions: bool,
|
pub all_versions: bool,
|
||||||
|
|
||||||
/// List toolchains for all platforms.
|
/// List Python installations for all platforms.
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub all_platforms: bool,
|
pub all_platforms: bool,
|
||||||
|
|
||||||
/// Only show installed toolchains, exclude available downloads.
|
/// Only show installed Python versions, exclude available downloads.
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub only_installed: bool,
|
pub only_installed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
#[allow(clippy::struct_excessive_bools)]
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
pub struct ToolchainInstallArgs {
|
pub struct PythonInstallArgs {
|
||||||
/// The toolchains to install.
|
/// The Python versions to install.
|
||||||
///
|
///
|
||||||
/// If not provided, the requested toolchain(s) will be read from the `.python-versions`
|
/// If not provided, the requested Python version(s) will be read from the `.python-versions`
|
||||||
/// or `.python-version` files. If neither file is present, uv will check if it has
|
/// or `.python-version` files. If neither file is present, uv will check if it has
|
||||||
/// installed any toolchains. If not, it will install the latest stable version of Python.
|
/// installed any Python versions. If not, it will install the latest stable version of Python.
|
||||||
pub targets: Vec<String>,
|
pub targets: Vec<String>,
|
||||||
|
|
||||||
/// Force the installation of the toolchain, even if it is already installed.
|
/// Force the installation of the requested Python, even if it is already installed.
|
||||||
#[arg(long, short)]
|
#[arg(long, short)]
|
||||||
pub force: bool,
|
pub force: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
#[allow(clippy::struct_excessive_bools)]
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
pub struct ToolchainUninstallArgs {
|
pub struct PythonUninstallArgs {
|
||||||
/// The toolchains to uninstall.
|
/// The Python versions to uninstall.
|
||||||
pub targets: Vec<String>,
|
pub targets: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
#[allow(clippy::struct_excessive_bools)]
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
pub struct ToolchainFindArgs {
|
pub struct PythonFindArgs {
|
||||||
/// The toolchain request.
|
/// The Python request.
|
||||||
pub request: Option<String>,
|
pub request: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ uv-git = { workspace = true }
|
||||||
uv-installer = { workspace = true }
|
uv-installer = { workspace = true }
|
||||||
uv-resolver = { workspace = true }
|
uv-resolver = { workspace = true }
|
||||||
uv-settings = { workspace = true, features = ["schemars"] }
|
uv-settings = { workspace = true, features = ["schemars"] }
|
||||||
uv-toolchain = { workspace = true }
|
uv-python = { workspace = true }
|
||||||
uv-types = { workspace = true }
|
uv-types = { workspace = true }
|
||||||
|
|
||||||
# Any dependencies that are exclusively used in `uv-dev` should be listed as non-workspace
|
# Any dependencies that are exclusively used in `uv-dev` should be listed as non-workspace
|
||||||
|
|
|
@ -16,8 +16,8 @@ use uv_configuration::{
|
||||||
};
|
};
|
||||||
use uv_dispatch::BuildDispatch;
|
use uv_dispatch::BuildDispatch;
|
||||||
use uv_git::GitResolver;
|
use uv_git::GitResolver;
|
||||||
|
use uv_python::{EnvironmentPreference, PythonEnvironment, PythonRequest};
|
||||||
use uv_resolver::{FlatIndex, InMemoryIndex};
|
use uv_resolver::{FlatIndex, InMemoryIndex};
|
||||||
use uv_toolchain::{EnvironmentPreference, PythonEnvironment, ToolchainRequest};
|
|
||||||
use uv_types::{BuildContext, BuildIsolation, InFlight};
|
use uv_types::{BuildContext, BuildIsolation, InFlight};
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
|
@ -68,8 +68,8 @@ pub(crate) async fn build(args: BuildArgs) -> Result<PathBuf> {
|
||||||
let index_urls = IndexLocations::default();
|
let index_urls = IndexLocations::default();
|
||||||
let index_strategy = IndexStrategy::default();
|
let index_strategy = IndexStrategy::default();
|
||||||
let setup_py = SetupPyStrategy::default();
|
let setup_py = SetupPyStrategy::default();
|
||||||
let toolchain = PythonEnvironment::find(
|
let python = PythonEnvironment::find(
|
||||||
&ToolchainRequest::default(),
|
&PythonRequest::default(),
|
||||||
EnvironmentPreference::OnlyVirtual,
|
EnvironmentPreference::OnlyVirtual,
|
||||||
&cache,
|
&cache,
|
||||||
)?;
|
)?;
|
||||||
|
@ -78,7 +78,7 @@ pub(crate) async fn build(args: BuildArgs) -> Result<PathBuf> {
|
||||||
let build_dispatch = BuildDispatch::new(
|
let build_dispatch = BuildDispatch::new(
|
||||||
&client,
|
&client,
|
||||||
&cache,
|
&cache,
|
||||||
toolchain.interpreter(),
|
python.interpreter(),
|
||||||
&index_urls,
|
&index_urls,
|
||||||
&flat_index,
|
&flat_index,
|
||||||
&index,
|
&index,
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::path::PathBuf;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
use uv_cache::{Cache, CacheArgs};
|
use uv_cache::{Cache, CacheArgs};
|
||||||
use uv_toolchain::{EnvironmentPreference, PythonEnvironment, ToolchainRequest};
|
use uv_python::{EnvironmentPreference, PythonEnvironment, PythonRequest};
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
pub(crate) struct CompileArgs {
|
pub(crate) struct CompileArgs {
|
||||||
|
@ -21,7 +21,7 @@ pub(crate) async fn compile(args: CompileArgs) -> anyhow::Result<()> {
|
||||||
python
|
python
|
||||||
} else {
|
} else {
|
||||||
let interpreter = PythonEnvironment::find(
|
let interpreter = PythonEnvironment::find(
|
||||||
&ToolchainRequest::default(),
|
&PythonRequest::default(),
|
||||||
EnvironmentPreference::OnlyVirtual,
|
EnvironmentPreference::OnlyVirtual,
|
||||||
&cache,
|
&cache,
|
||||||
)?
|
)?
|
||||||
|
|
|
@ -24,7 +24,7 @@ uv-configuration = { workspace = true }
|
||||||
uv-distribution = { workspace = true }
|
uv-distribution = { workspace = true }
|
||||||
uv-git = { workspace = true }
|
uv-git = { workspace = true }
|
||||||
uv-installer = { workspace = true }
|
uv-installer = { workspace = true }
|
||||||
uv-toolchain = { workspace = true }
|
uv-python = { workspace = true }
|
||||||
uv-resolver = { workspace = true }
|
uv-resolver = { workspace = true }
|
||||||
uv-types = { workspace = true }
|
uv-types = { workspace = true }
|
||||||
|
|
||||||
|
|
|
@ -23,10 +23,10 @@ use uv_configuration::{Concurrency, PreviewMode};
|
||||||
use uv_distribution::DistributionDatabase;
|
use uv_distribution::DistributionDatabase;
|
||||||
use uv_git::GitResolver;
|
use uv_git::GitResolver;
|
||||||
use uv_installer::{Installer, Plan, Planner, Preparer, SitePackages};
|
use uv_installer::{Installer, Plan, Planner, Preparer, SitePackages};
|
||||||
|
use uv_python::{Interpreter, PythonEnvironment};
|
||||||
use uv_resolver::{
|
use uv_resolver::{
|
||||||
ExcludeNewer, FlatIndex, InMemoryIndex, Manifest, OptionsBuilder, PythonRequirement, Resolver,
|
ExcludeNewer, FlatIndex, InMemoryIndex, Manifest, OptionsBuilder, PythonRequirement, Resolver,
|
||||||
};
|
};
|
||||||
use uv_toolchain::{Interpreter, PythonEnvironment};
|
|
||||||
use uv_types::{BuildContext, BuildIsolation, EmptyInstalledPackages, HashStrategy, InFlight};
|
use uv_types::{BuildContext, BuildIsolation, EmptyInstalledPackages, HashStrategy, InFlight};
|
||||||
|
|
||||||
/// The main implementation of [`BuildContext`], used by the CLI, see [`BuildContext`]
|
/// The main implementation of [`BuildContext`], used by the CLI, see [`BuildContext`]
|
||||||
|
|
|
@ -27,7 +27,7 @@ uv-distribution = { workspace = true }
|
||||||
uv-extract = { workspace = true }
|
uv-extract = { workspace = true }
|
||||||
uv-fs = { workspace = true }
|
uv-fs = { workspace = true }
|
||||||
uv-git = { workspace = true }
|
uv-git = { workspace = true }
|
||||||
uv-toolchain = { workspace = true }
|
uv-python = { workspace = true }
|
||||||
uv-normalize = { workspace = true }
|
uv-normalize = { workspace = true }
|
||||||
uv-types = { workspace = true }
|
uv-types = { workspace = true }
|
||||||
uv-warnings = { workspace = true }
|
uv-warnings = { workspace = true }
|
||||||
|
|
|
@ -3,7 +3,7 @@ use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
use distribution_types::CachedDist;
|
use distribution_types::CachedDist;
|
||||||
use uv_toolchain::PythonEnvironment;
|
use uv_python::PythonEnvironment;
|
||||||
|
|
||||||
pub struct Installer<'a> {
|
pub struct Installer<'a> {
|
||||||
venv: &'a PythonEnvironment,
|
venv: &'a PythonEnvironment,
|
||||||
|
|
|
@ -21,7 +21,7 @@ use uv_distribution::{
|
||||||
};
|
};
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
use uv_git::GitUrl;
|
use uv_git::GitUrl;
|
||||||
use uv_toolchain::PythonEnvironment;
|
use uv_python::PythonEnvironment;
|
||||||
use uv_types::HashStrategy;
|
use uv_types::HashStrategy;
|
||||||
|
|
||||||
use crate::satisfies::RequirementSatisfaction;
|
use crate::satisfies::RequirementSatisfaction;
|
||||||
|
|
|
@ -13,7 +13,7 @@ use distribution_types::{
|
||||||
use pep440_rs::{Version, VersionSpecifiers};
|
use pep440_rs::{Version, VersionSpecifiers};
|
||||||
use pypi_types::{Requirement, VerbatimParsedUrl};
|
use pypi_types::{Requirement, VerbatimParsedUrl};
|
||||||
use uv_normalize::PackageName;
|
use uv_normalize::PackageName;
|
||||||
use uv_toolchain::PythonEnvironment;
|
use uv_python::PythonEnvironment;
|
||||||
use uv_types::InstalledPackagesProvider;
|
use uv_types::InstalledPackagesProvider;
|
||||||
|
|
||||||
use crate::satisfies::RequirementSatisfaction;
|
use crate::satisfies::RequirementSatisfaction;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uv-toolchain"
|
name = "uv-python"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
edition = { workspace = true }
|
edition = { workspace = true }
|
||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -3,10 +3,10 @@
|
||||||
// Generated with `{{generated_with}}`
|
// Generated with `{{generated_with}}`
|
||||||
// From template at `{{generated_from}}`
|
// From template at `{{generated_from}}`
|
||||||
|
|
||||||
pub(crate) const PYTHON_DOWNLOADS: &[PythonDownload] = &[
|
pub(crate) const PYTHON_DOWNLOADS: &[ManagedPythonDownload] = &[
|
||||||
{{#versions}}
|
{{#versions}}
|
||||||
PythonDownload {
|
ManagedPythonDownload {
|
||||||
key: ToolchainKey {
|
key: PythonInstallationKey {
|
||||||
major: {{value.major}},
|
major: {{value.major}},
|
||||||
minor: {{value.minor}},
|
minor: {{value.minor}},
|
||||||
patch: {{value.patch}},
|
patch: {{value.patch}},
|
|
@ -6,9 +6,9 @@ use std::str::FromStr;
|
||||||
use crate::implementation::{
|
use crate::implementation::{
|
||||||
Error as ImplementationError, ImplementationName, LenientImplementationName,
|
Error as ImplementationError, ImplementationName, LenientImplementationName,
|
||||||
};
|
};
|
||||||
|
use crate::installation::PythonInstallationKey;
|
||||||
use crate::platform::{self, Arch, Libc, Os};
|
use crate::platform::{self, Arch, Libc, Os};
|
||||||
use crate::toolchain::ToolchainKey;
|
use crate::{Interpreter, PythonRequest, PythonVersion, VersionRequest};
|
||||||
use crate::{Interpreter, PythonVersion, ToolchainRequest, VersionRequest};
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use uv_client::WrappedReqwestError;
|
use uv_client::WrappedReqwestError;
|
||||||
|
|
||||||
|
@ -45,26 +45,26 @@ pub enum Error {
|
||||||
#[source]
|
#[source]
|
||||||
err: io::Error,
|
err: io::Error,
|
||||||
},
|
},
|
||||||
#[error("Failed to read toolchain directory: {0}", dir.user_display())]
|
#[error("Failed to read managed Python installation directory: {0}", dir.user_display())]
|
||||||
ReadError {
|
ReadError {
|
||||||
dir: PathBuf,
|
dir: PathBuf,
|
||||||
#[source]
|
#[source]
|
||||||
err: io::Error,
|
err: io::Error,
|
||||||
},
|
},
|
||||||
#[error("Failed to parse toolchain directory name: {0}")]
|
#[error("Failed to parse managed Python directory name: {0}")]
|
||||||
NameError(String),
|
NameError(String),
|
||||||
#[error("Failed to parse request part")]
|
#[error("Failed to parse request part")]
|
||||||
InvalidRequestPlatform(#[from] platform::Error),
|
InvalidRequestPlatform(#[from] platform::Error),
|
||||||
#[error("Cannot download toolchain for request: {0}")]
|
#[error("Cannot download managed Python for request: {0}")]
|
||||||
InvalidRequestKind(ToolchainRequest),
|
InvalidRequestKind(PythonRequest),
|
||||||
// TODO(zanieb): Implement display for `PythonDownloadRequest`
|
// TODO(zanieb): Implement display for `PythonDownloadRequest`
|
||||||
#[error("No download found for request: {0:?}")]
|
#[error("No download found for request: {0:?}")]
|
||||||
NoDownloadFound(PythonDownloadRequest),
|
NoDownloadFound(PythonDownloadRequest),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct PythonDownload {
|
pub struct ManagedPythonDownload {
|
||||||
key: ToolchainKey,
|
key: PythonInstallationKey,
|
||||||
url: &'static str,
|
url: &'static str,
|
||||||
sha256: Option<&'static str>,
|
sha256: Option<&'static str>,
|
||||||
}
|
}
|
||||||
|
@ -125,30 +125,30 @@ impl PythonDownloadRequest {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a new [`PythonDownloadRequest`] from a [`ToolchainRequest`] if possible.
|
/// Construct a new [`PythonDownloadRequest`] from a [`PythonRequest`] if possible.
|
||||||
///
|
///
|
||||||
/// Returns [`None`] if the request kind is not compatible with a download, e.g., it is
|
/// Returns [`None`] if the request kind is not compatible with a download, e.g., it is
|
||||||
/// a request for a specific directory or executable name.
|
/// a request for a specific directory or executable name.
|
||||||
pub fn try_from_request(request: &ToolchainRequest) -> Option<Self> {
|
pub fn try_from_request(request: &PythonRequest) -> Option<Self> {
|
||||||
Self::from_request(request).ok()
|
Self::from_request(request).ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a new [`PythonDownloadRequest`] from a [`ToolchainRequest`].
|
/// Construct a new [`PythonDownloadRequest`] from a [`PythonRequest`].
|
||||||
pub fn from_request(request: &ToolchainRequest) -> Result<Self, Error> {
|
pub fn from_request(request: &PythonRequest) -> Result<Self, Error> {
|
||||||
match request {
|
match request {
|
||||||
ToolchainRequest::Version(version) => Ok(Self::default().with_version(version.clone())),
|
PythonRequest::Version(version) => Ok(Self::default().with_version(version.clone())),
|
||||||
ToolchainRequest::Implementation(implementation) => {
|
PythonRequest::Implementation(implementation) => {
|
||||||
Ok(Self::default().with_implementation(*implementation))
|
Ok(Self::default().with_implementation(*implementation))
|
||||||
}
|
}
|
||||||
ToolchainRequest::ImplementationVersion(implementation, version) => Ok(Self::default()
|
PythonRequest::ImplementationVersion(implementation, version) => Ok(Self::default()
|
||||||
.with_implementation(*implementation)
|
.with_implementation(*implementation)
|
||||||
.with_version(version.clone())),
|
.with_version(version.clone())),
|
||||||
ToolchainRequest::Key(request) => Ok(request.clone()),
|
PythonRequest::Key(request) => Ok(request.clone()),
|
||||||
ToolchainRequest::Any => Ok(Self::default()),
|
PythonRequest::Any => Ok(Self::default()),
|
||||||
// We can't download a toolchain for these request kinds
|
// We can't download a managed installation for these request kinds
|
||||||
ToolchainRequest::Directory(_)
|
PythonRequest::Directory(_)
|
||||||
| ToolchainRequest::ExecutableName(_)
|
| PythonRequest::ExecutableName(_)
|
||||||
| ToolchainRequest::File(_) => Err(Error::InvalidRequestKind(request.clone())),
|
| PythonRequest::File(_) => Err(Error::InvalidRequestKind(request.clone())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,11 +204,12 @@ impl PythonDownloadRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over all [`PythonDownload`]'s that match this request.
|
/// Iterate over all [`PythonDownload`]'s that match this request.
|
||||||
pub fn iter_downloads(&self) -> impl Iterator<Item = &'static PythonDownload> + '_ {
|
pub fn iter_downloads(&self) -> impl Iterator<Item = &'static ManagedPythonDownload> + '_ {
|
||||||
PythonDownload::iter_all().filter(move |download| self.satisfied_by_download(download))
|
ManagedPythonDownload::iter_all()
|
||||||
|
.filter(move |download| self.satisfied_by_download(download))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn satisfied_by_key(&self, key: &ToolchainKey) -> bool {
|
pub fn satisfied_by_key(&self, key: &PythonInstallationKey) -> bool {
|
||||||
if let Some(arch) = &self.arch {
|
if let Some(arch) = &self.arch {
|
||||||
if key.arch != *arch {
|
if key.arch != *arch {
|
||||||
return false;
|
return false;
|
||||||
|
@ -232,7 +233,7 @@ impl PythonDownloadRequest {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn satisfied_by_download(&self, download: &PythonDownload) -> bool {
|
pub fn satisfied_by_download(&self, download: &ManagedPythonDownload) -> bool {
|
||||||
self.satisfied_by_key(download.key())
|
self.satisfied_by_key(download.key())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,9 +357,11 @@ pub enum DownloadResult {
|
||||||
Fetched(PathBuf),
|
Fetched(PathBuf),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PythonDownload {
|
impl ManagedPythonDownload {
|
||||||
/// Return the first [`PythonDownload`] matching a request, if any.
|
/// Return the first [`PythonDownload`] matching a request, if any.
|
||||||
pub fn from_request(request: &PythonDownloadRequest) -> Result<&'static PythonDownload, Error> {
|
pub fn from_request(
|
||||||
|
request: &PythonDownloadRequest,
|
||||||
|
) -> Result<&'static ManagedPythonDownload, Error> {
|
||||||
request
|
request
|
||||||
.iter_downloads()
|
.iter_downloads()
|
||||||
.next()
|
.next()
|
||||||
|
@ -366,7 +369,7 @@ impl PythonDownload {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over all [`PythonDownload`]'s.
|
/// Iterate over all [`PythonDownload`]'s.
|
||||||
pub fn iter_all() -> impl Iterator<Item = &'static PythonDownload> {
|
pub fn iter_all() -> impl Iterator<Item = &'static ManagedPythonDownload> {
|
||||||
PYTHON_DOWNLOADS.iter()
|
PYTHON_DOWNLOADS.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,7 +377,7 @@ impl PythonDownload {
|
||||||
self.url
|
self.url
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn key(&self) -> &ToolchainKey {
|
pub fn key(&self) -> &PythonInstallationKey {
|
||||||
&self.key
|
&self.key
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,7 +468,7 @@ impl From<reqwest_middleware::Error> for Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for PythonDownload {
|
impl Display for ManagedPythonDownload {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "{}", self.key)
|
write!(f, "{}", self.key)
|
||||||
}
|
}
|
|
@ -7,12 +7,12 @@ use std::sync::Arc;
|
||||||
use uv_cache::Cache;
|
use uv_cache::Cache;
|
||||||
use uv_fs::{LockedFile, Simplified};
|
use uv_fs::{LockedFile, Simplified};
|
||||||
|
|
||||||
use crate::discovery::find_toolchain;
|
use crate::discovery::find_python_installation;
|
||||||
use crate::toolchain::Toolchain;
|
use crate::installation::PythonInstallation;
|
||||||
use crate::virtualenv::{virtualenv_python_executable, PyVenvConfiguration};
|
use crate::virtualenv::{virtualenv_python_executable, PyVenvConfiguration};
|
||||||
use crate::{
|
use crate::{
|
||||||
EnvironmentPreference, Error, Interpreter, Prefix, Target, ToolchainNotFound,
|
EnvironmentPreference, Error, Interpreter, Prefix, PythonNotFound, PythonPreference,
|
||||||
ToolchainPreference, ToolchainRequest,
|
PythonRequest, Target,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A Python environment, consisting of a Python [`Interpreter`] and its associated paths.
|
/// A Python environment, consisting of a Python [`Interpreter`] and its associated paths.
|
||||||
|
@ -27,15 +27,15 @@ struct PythonEnvironmentShared {
|
||||||
|
|
||||||
/// The result of failed environment discovery.
|
/// The result of failed environment discovery.
|
||||||
///
|
///
|
||||||
/// Generally this is cast from [`ToolchainNotFound`] by [`PythonEnvironment::find`].
|
/// Generally this is cast from [`PythonNotFound`] by [`PythonEnvironment::find`].
|
||||||
#[derive(Clone, Debug, Error)]
|
#[derive(Clone, Debug, Error)]
|
||||||
pub struct EnvironmentNotFound {
|
pub struct EnvironmentNotFound {
|
||||||
request: ToolchainRequest,
|
request: PythonRequest,
|
||||||
preference: EnvironmentPreference,
|
preference: EnvironmentPreference,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ToolchainNotFound> for EnvironmentNotFound {
|
impl From<PythonNotFound> for EnvironmentNotFound {
|
||||||
fn from(value: ToolchainNotFound) -> Self {
|
fn from(value: PythonNotFound) -> Self {
|
||||||
Self {
|
Self {
|
||||||
request: value.request,
|
request: value.request,
|
||||||
preference: value.environment_preference,
|
preference: value.environment_preference,
|
||||||
|
@ -59,7 +59,7 @@ impl fmt::Display for EnvironmentNotFound {
|
||||||
EnvironmentPreference::OnlyVirtual => "virtual environment",
|
EnvironmentPreference::OnlyVirtual => "virtual environment",
|
||||||
};
|
};
|
||||||
match self.request {
|
match self.request {
|
||||||
ToolchainRequest::Any => {
|
PythonRequest::Any => {
|
||||||
write!(f, "No {environment} found")
|
write!(f, "No {environment} found")
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -72,24 +72,24 @@ impl fmt::Display for EnvironmentNotFound {
|
||||||
impl PythonEnvironment {
|
impl PythonEnvironment {
|
||||||
/// Find a [`PythonEnvironment`] matching the given request and preference.
|
/// Find a [`PythonEnvironment`] matching the given request and preference.
|
||||||
///
|
///
|
||||||
/// If looking for a Python toolchain to create a new environment, use [`Toolchain::find`]
|
/// If looking for a Python interpreter to create a new environment, use [`PythonInstallation::find`]
|
||||||
/// instead.
|
/// instead.
|
||||||
pub fn find(
|
pub fn find(
|
||||||
request: &ToolchainRequest,
|
request: &PythonRequest,
|
||||||
preference: EnvironmentPreference,
|
preference: EnvironmentPreference,
|
||||||
cache: &Cache,
|
cache: &Cache,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let toolchain = match find_toolchain(
|
let installation = match find_python_installation(
|
||||||
request,
|
request,
|
||||||
preference,
|
preference,
|
||||||
// Ignore managed toolchains when looking for environments
|
// Ignore managed installations when looking for environments
|
||||||
ToolchainPreference::OnlySystem,
|
PythonPreference::OnlySystem,
|
||||||
cache,
|
cache,
|
||||||
)? {
|
)? {
|
||||||
Ok(toolchain) => toolchain,
|
Ok(installation) => installation,
|
||||||
Err(err) => return Err(EnvironmentNotFound::from(err).into()),
|
Err(err) => return Err(EnvironmentNotFound::from(err).into()),
|
||||||
};
|
};
|
||||||
Ok(Self::from_toolchain(toolchain))
|
Ok(Self::from_installation(installation))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a [`PythonEnvironment`] from the virtual environment at the given root.
|
/// Create a [`PythonEnvironment`] from the virtual environment at the given root.
|
||||||
|
@ -99,7 +99,7 @@ impl PythonEnvironment {
|
||||||
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
|
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
|
||||||
return Err(Error::MissingEnvironment(EnvironmentNotFound {
|
return Err(Error::MissingEnvironment(EnvironmentNotFound {
|
||||||
preference: EnvironmentPreference::Any,
|
preference: EnvironmentPreference::Any,
|
||||||
request: ToolchainRequest::Directory(root.as_ref().to_owned()),
|
request: PythonRequest::Directory(root.as_ref().to_owned()),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
Err(err) => return Err(Error::Discovery(err.into())),
|
Err(err) => return Err(Error::Discovery(err.into())),
|
||||||
|
@ -113,9 +113,9 @@ impl PythonEnvironment {
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a [`PythonEnvironment`] from an existing [`Toolchain`].
|
/// Create a [`PythonEnvironment`] from an existing [`PythonInstallation`].
|
||||||
pub fn from_toolchain(toolchain: Toolchain) -> Self {
|
pub fn from_installation(installation: PythonInstallation) -> Self {
|
||||||
Self::from_interpreter(toolchain.into_interpreter())
|
Self::from_interpreter(installation.into_interpreter())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a [`PythonEnvironment`] from an existing [`Interpreter`].
|
/// Create a [`PythonEnvironment`] from an existing [`Interpreter`].
|
|
@ -8,27 +8,25 @@ use uv_client::BaseClientBuilder;
|
||||||
use uv_cache::Cache;
|
use uv_cache::Cache;
|
||||||
|
|
||||||
use crate::discovery::{
|
use crate::discovery::{
|
||||||
find_best_toolchain, find_toolchain, EnvironmentPreference, ToolchainRequest,
|
find_best_python_installation, find_python_installation, EnvironmentPreference, PythonRequest,
|
||||||
};
|
};
|
||||||
use crate::downloads::{DownloadResult, PythonDownload, PythonDownloadRequest};
|
use crate::downloads::{DownloadResult, ManagedPythonDownload, PythonDownloadRequest};
|
||||||
use crate::implementation::LenientImplementationName;
|
use crate::implementation::LenientImplementationName;
|
||||||
use crate::managed::{InstalledToolchain, InstalledToolchains};
|
use crate::managed::{ManagedPythonInstallation, ManagedPythonInstallations};
|
||||||
use crate::platform::{Arch, Libc, Os};
|
use crate::platform::{Arch, Libc, Os};
|
||||||
use crate::{
|
use crate::{Error, Interpreter, PythonFetch, PythonPreference, PythonSource, PythonVersion};
|
||||||
Error, Interpreter, PythonVersion, ToolchainFetch, ToolchainPreference, ToolchainSource,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A Python interpreter and accompanying tools.
|
/// A Python interpreter and accompanying tools.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Toolchain {
|
pub struct PythonInstallation {
|
||||||
// Public in the crate for test assertions
|
// Public in the crate for test assertions
|
||||||
pub(crate) source: ToolchainSource,
|
pub(crate) source: PythonSource,
|
||||||
pub(crate) interpreter: Interpreter,
|
pub(crate) interpreter: Interpreter,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Toolchain {
|
impl PythonInstallation {
|
||||||
/// Create a new [`Toolchain`] from a source, interpreter tuple.
|
/// Create a new [`PythonInstallation`] from a source, interpreter tuple.
|
||||||
pub(crate) fn from_tuple(tuple: (ToolchainSource, Interpreter)) -> Self {
|
pub(crate) fn from_tuple(tuple: (PythonSource, Interpreter)) -> Self {
|
||||||
let (source, interpreter) = tuple;
|
let (source, interpreter) = tuple;
|
||||||
Self {
|
Self {
|
||||||
source,
|
source,
|
||||||
|
@ -36,9 +34,9 @@ impl Toolchain {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find an installed [`Toolchain`].
|
/// Find an installed [`PythonInstallation`].
|
||||||
///
|
///
|
||||||
/// This is the standard interface for discovering a Python toolchain for creating
|
/// This is the standard interface for discovering a Python installation for creating
|
||||||
/// an environment. If interested in finding an existing environment, see
|
/// an environment. If interested in finding an existing environment, see
|
||||||
/// [`PythonEnvironment::find`] instead.
|
/// [`PythonEnvironment::find`] instead.
|
||||||
///
|
///
|
||||||
|
@ -47,26 +45,26 @@ impl Toolchain {
|
||||||
/// but if you want to allow an interpreter from a virtual environment if it satisfies the request,
|
/// but if you want to allow an interpreter from a virtual environment if it satisfies the request,
|
||||||
/// then use [`EnvironmentPreference::Any`].
|
/// then use [`EnvironmentPreference::Any`].
|
||||||
///
|
///
|
||||||
/// See [`find_toolchain`] for implementation details.
|
/// See [`find_installation`] for implementation details.
|
||||||
pub fn find(
|
pub fn find(
|
||||||
request: &ToolchainRequest,
|
request: &PythonRequest,
|
||||||
environments: EnvironmentPreference,
|
environments: EnvironmentPreference,
|
||||||
preference: ToolchainPreference,
|
preference: PythonPreference,
|
||||||
cache: &Cache,
|
cache: &Cache,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let toolchain = find_toolchain(request, environments, preference, cache)??;
|
let installation = find_python_installation(request, environments, preference, cache)??;
|
||||||
Ok(toolchain)
|
Ok(installation)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find an installed [`Toolchain`] that satisfies a requested version, if the request cannot
|
/// Find an installed [`PythonInstallation`] that satisfies a requested version, if the request cannot
|
||||||
/// be satisfied, fallback to the best available toolchain.
|
/// be satisfied, fallback to the best available Python installation.
|
||||||
pub fn find_best(
|
pub fn find_best(
|
||||||
request: &ToolchainRequest,
|
request: &PythonRequest,
|
||||||
environments: EnvironmentPreference,
|
environments: EnvironmentPreference,
|
||||||
preference: ToolchainPreference,
|
preference: PythonPreference,
|
||||||
cache: &Cache,
|
cache: &Cache,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
Ok(find_best_toolchain(
|
Ok(find_best_python_installation(
|
||||||
request,
|
request,
|
||||||
environments,
|
environments,
|
||||||
preference,
|
preference,
|
||||||
|
@ -74,33 +72,33 @@ impl Toolchain {
|
||||||
)??)
|
)??)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find or fetch a [`Toolchain`].
|
/// Find or fetch a [`PythonInstallation`].
|
||||||
///
|
///
|
||||||
/// Unlike [`Toolchain::find`], if the toolchain is not installed it will be installed automatically.
|
/// Unlike [`PythonInstallation::find`], if the required Python is not installed it will be installed automatically.
|
||||||
pub async fn find_or_fetch<'a>(
|
pub async fn find_or_fetch<'a>(
|
||||||
request: Option<ToolchainRequest>,
|
request: Option<PythonRequest>,
|
||||||
environments: EnvironmentPreference,
|
environments: EnvironmentPreference,
|
||||||
preference: ToolchainPreference,
|
preference: PythonPreference,
|
||||||
toolchain_fetch: ToolchainFetch,
|
python_fetch: PythonFetch,
|
||||||
client_builder: &BaseClientBuilder<'a>,
|
client_builder: &BaseClientBuilder<'a>,
|
||||||
cache: &Cache,
|
cache: &Cache,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let request = request.unwrap_or_default();
|
let request = request.unwrap_or_default();
|
||||||
|
|
||||||
// Perform a fetch aggressively if managed toolchains are preferred
|
// Perform a fetch aggressively if managed Python is preferred
|
||||||
if matches!(preference, ToolchainPreference::Managed) && toolchain_fetch.is_automatic() {
|
if matches!(preference, PythonPreference::Managed) && python_fetch.is_automatic() {
|
||||||
if let Some(request) = PythonDownloadRequest::try_from_request(&request) {
|
if let Some(request) = PythonDownloadRequest::try_from_request(&request) {
|
||||||
return Self::fetch(request, client_builder, cache).await;
|
return Self::fetch(request, client_builder, cache).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search for the toolchain
|
// Search for the installation
|
||||||
match Self::find(&request, environments, preference, cache) {
|
match Self::find(&request, environments, preference, cache) {
|
||||||
Ok(venv) => Ok(venv),
|
Ok(venv) => Ok(venv),
|
||||||
// If missing and allowed, perform a fetch
|
// If missing and allowed, perform a fetch
|
||||||
err @ Err(Error::MissingToolchain(_))
|
err @ Err(Error::MissingPython(_))
|
||||||
if preference.allows_managed()
|
if preference.allows_managed()
|
||||||
&& toolchain_fetch.is_automatic()
|
&& python_fetch.is_automatic()
|
||||||
&& client_builder.connectivity.is_online() =>
|
&& client_builder.connectivity.is_online() =>
|
||||||
{
|
{
|
||||||
if let Some(request) = PythonDownloadRequest::try_from_request(&request) {
|
if let Some(request) = PythonDownloadRequest::try_from_request(&request) {
|
||||||
|
@ -114,51 +112,51 @@ impl Toolchain {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Download and install the requested toolchain.
|
/// Download and install the requested installation.
|
||||||
pub async fn fetch<'a>(
|
pub async fn fetch<'a>(
|
||||||
request: PythonDownloadRequest,
|
request: PythonDownloadRequest,
|
||||||
client_builder: &BaseClientBuilder<'a>,
|
client_builder: &BaseClientBuilder<'a>,
|
||||||
cache: &Cache,
|
cache: &Cache,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let toolchains = InstalledToolchains::from_settings()?.init()?;
|
let installations = ManagedPythonInstallations::from_settings()?.init()?;
|
||||||
let toolchain_dir = toolchains.root();
|
let installations_dir = installations.root();
|
||||||
let _lock = toolchains.acquire_lock()?;
|
let _lock = installations.acquire_lock()?;
|
||||||
|
|
||||||
let download = PythonDownload::from_request(&request)?;
|
let download = ManagedPythonDownload::from_request(&request)?;
|
||||||
let client = client_builder.build();
|
let client = client_builder.build();
|
||||||
|
|
||||||
info!("Fetching requested toolchain...");
|
info!("Fetching requested Python...");
|
||||||
let result = download.fetch(&client, toolchain_dir).await?;
|
let result = download.fetch(&client, installations_dir).await?;
|
||||||
|
|
||||||
let path = match result {
|
let path = match result {
|
||||||
DownloadResult::AlreadyAvailable(path) => path,
|
DownloadResult::AlreadyAvailable(path) => path,
|
||||||
DownloadResult::Fetched(path) => path,
|
DownloadResult::Fetched(path) => path,
|
||||||
};
|
};
|
||||||
|
|
||||||
let installed = InstalledToolchain::new(path)?;
|
let installed = ManagedPythonInstallation::new(path)?;
|
||||||
installed.ensure_externally_managed()?;
|
installed.ensure_externally_managed()?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
source: ToolchainSource::Managed,
|
source: PythonSource::Managed,
|
||||||
interpreter: Interpreter::query(installed.executable(), cache)?,
|
interpreter: Interpreter::query(installed.executable(), cache)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a [`Toolchain`] from an existing [`Interpreter`].
|
/// Create a [`PythonInstallation`] from an existing [`Interpreter`].
|
||||||
pub fn from_interpreter(interpreter: Interpreter) -> Self {
|
pub fn from_interpreter(interpreter: Interpreter) -> Self {
|
||||||
Self {
|
Self {
|
||||||
source: ToolchainSource::ProvidedPath,
|
source: PythonSource::ProvidedPath,
|
||||||
interpreter,
|
interpreter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the [`ToolchainSource`] of the toolchain, indicating where it was found.
|
/// Return the [`PythonSource`] of the Python installation, indicating where it was found.
|
||||||
pub fn source(&self) -> &ToolchainSource {
|
pub fn source(&self) -> &PythonSource {
|
||||||
&self.source
|
&self.source
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn key(&self) -> ToolchainKey {
|
pub fn key(&self) -> PythonInstallationKey {
|
||||||
ToolchainKey::new(
|
PythonInstallationKey::new(
|
||||||
LenientImplementationName::from(self.interpreter.implementation_name()),
|
LenientImplementationName::from(self.interpreter.implementation_name()),
|
||||||
self.interpreter.python_major(),
|
self.interpreter.python_major(),
|
||||||
self.interpreter.python_minor(),
|
self.interpreter.python_minor(),
|
||||||
|
@ -169,32 +167,32 @@ impl Toolchain {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the Python [`Version`] of the toolchain as reported by its interpreter.
|
/// Return the Python [`Version`] of the Python installation as reported by its interpreter.
|
||||||
pub fn python_version(&self) -> &Version {
|
pub fn python_version(&self) -> &Version {
|
||||||
self.interpreter.python_version()
|
self.interpreter.python_version()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the [`LenientImplementationName`] of the toolchain as reported by its interpreter.
|
/// Return the [`LenientImplementationName`] of the Python installation as reported by its interpreter.
|
||||||
pub fn implementation(&self) -> LenientImplementationName {
|
pub fn implementation(&self) -> LenientImplementationName {
|
||||||
LenientImplementationName::from(self.interpreter.implementation_name())
|
LenientImplementationName::from(self.interpreter.implementation_name())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the [`Arch`] of the toolchain as reported by its interpreter.
|
/// Return the [`Arch`] of the Python installation as reported by its interpreter.
|
||||||
pub fn arch(&self) -> Arch {
|
pub fn arch(&self) -> Arch {
|
||||||
Arch::from(&self.interpreter.platform().arch())
|
Arch::from(&self.interpreter.platform().arch())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the [`Libc`] of the toolchain as reported by its interpreter.
|
/// Return the [`Libc`] of the Python installation as reported by its interpreter.
|
||||||
pub fn libc(&self) -> Libc {
|
pub fn libc(&self) -> Libc {
|
||||||
Libc::from(self.interpreter.platform().os())
|
Libc::from(self.interpreter.platform().os())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the [`Os`] of the toolchain as reported by its interpreter.
|
/// Return the [`Os`] of the Python installation as reported by its interpreter.
|
||||||
pub fn os(&self) -> Os {
|
pub fn os(&self) -> Os {
|
||||||
Os::from(self.interpreter.platform().os())
|
Os::from(self.interpreter.platform().os())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the [`Interpreter`] for the toolchain.
|
/// Return the [`Interpreter`] for the Python installation.
|
||||||
pub fn interpreter(&self) -> &Interpreter {
|
pub fn interpreter(&self) -> &Interpreter {
|
||||||
&self.interpreter
|
&self.interpreter
|
||||||
}
|
}
|
||||||
|
@ -205,13 +203,13 @@ impl Toolchain {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum ToolchainKeyError {
|
pub enum PythonInstallationKeyError {
|
||||||
#[error("Failed to parse toolchain key `{0}`: {1}")]
|
#[error("Failed to parse Python installation key `{0}`: {1}")]
|
||||||
ParseError(String, String),
|
ParseError(String, String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct ToolchainKey {
|
pub struct PythonInstallationKey {
|
||||||
pub(crate) implementation: LenientImplementationName,
|
pub(crate) implementation: LenientImplementationName,
|
||||||
pub(crate) major: u8,
|
pub(crate) major: u8,
|
||||||
pub(crate) minor: u8,
|
pub(crate) minor: u8,
|
||||||
|
@ -221,7 +219,7 @@ pub struct ToolchainKey {
|
||||||
pub(crate) libc: Libc,
|
pub(crate) libc: Libc,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToolchainKey {
|
impl PythonInstallationKey {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
implementation: LenientImplementationName,
|
implementation: LenientImplementationName,
|
||||||
major: u8,
|
major: u8,
|
||||||
|
@ -248,7 +246,7 @@ impl ToolchainKey {
|
||||||
|
|
||||||
pub fn version(&self) -> PythonVersion {
|
pub fn version(&self) -> PythonVersion {
|
||||||
PythonVersion::from_str(&format!("{}.{}.{}", self.major, self.minor, self.patch))
|
PythonVersion::from_str(&format!("{}.{}.{}", self.major, self.minor, self.patch))
|
||||||
.expect("Toolchain keys must have valid Python versions")
|
.expect("Python installation keys must have valid Python versions")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn arch(&self) -> &Arch {
|
pub fn arch(&self) -> &Arch {
|
||||||
|
@ -264,7 +262,7 @@ impl ToolchainKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ToolchainKey {
|
impl fmt::Display for PythonInstallationKey {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
|
@ -274,13 +272,13 @@ impl fmt::Display for ToolchainKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for ToolchainKey {
|
impl FromStr for PythonInstallationKey {
|
||||||
type Err = ToolchainKeyError;
|
type Err = PythonInstallationKeyError;
|
||||||
|
|
||||||
fn from_str(key: &str) -> Result<Self, Self::Err> {
|
fn from_str(key: &str) -> Result<Self, Self::Err> {
|
||||||
let parts = key.split('-').collect::<Vec<_>>();
|
let parts = key.split('-').collect::<Vec<_>>();
|
||||||
let [implementation, version, os, arch, libc] = parts.as_slice() else {
|
let [implementation, version, os, arch, libc] = parts.as_slice() else {
|
||||||
return Err(ToolchainKeyError::ParseError(
|
return Err(PythonInstallationKeyError::ParseError(
|
||||||
key.to_string(),
|
key.to_string(),
|
||||||
"not enough `-`-separated values".to_string(),
|
"not enough `-`-separated values".to_string(),
|
||||||
));
|
));
|
||||||
|
@ -289,15 +287,18 @@ impl FromStr for ToolchainKey {
|
||||||
let implementation = LenientImplementationName::from(*implementation);
|
let implementation = LenientImplementationName::from(*implementation);
|
||||||
|
|
||||||
let os = Os::from_str(os).map_err(|err| {
|
let os = Os::from_str(os).map_err(|err| {
|
||||||
ToolchainKeyError::ParseError(key.to_string(), format!("invalid OS: {err}"))
|
PythonInstallationKeyError::ParseError(key.to_string(), format!("invalid OS: {err}"))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let arch = Arch::from_str(arch).map_err(|err| {
|
let arch = Arch::from_str(arch).map_err(|err| {
|
||||||
ToolchainKeyError::ParseError(key.to_string(), format!("invalid architecture: {err}"))
|
PythonInstallationKeyError::ParseError(
|
||||||
|
key.to_string(),
|
||||||
|
format!("invalid architecture: {err}"),
|
||||||
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let libc = Libc::from_str(libc).map_err(|err| {
|
let libc = Libc::from_str(libc).map_err(|err| {
|
||||||
ToolchainKeyError::ParseError(key.to_string(), format!("invalid libc: {err}"))
|
PythonInstallationKeyError::ParseError(key.to_string(), format!("invalid libc: {err}"))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let [major, minor, patch] = version
|
let [major, minor, patch] = version
|
||||||
|
@ -305,13 +306,13 @@ impl FromStr for ToolchainKey {
|
||||||
.map(str::parse::<u8>)
|
.map(str::parse::<u8>)
|
||||||
.collect::<Result<Vec<_>, _>>()
|
.collect::<Result<Vec<_>, _>>()
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
ToolchainKeyError::ParseError(
|
PythonInstallationKeyError::ParseError(
|
||||||
key.to_string(),
|
key.to_string(),
|
||||||
format!("invalid Python version: {err}"),
|
format!("invalid Python version: {err}"),
|
||||||
)
|
)
|
||||||
})?[..]
|
})?[..]
|
||||||
else {
|
else {
|
||||||
return Err(ToolchainKeyError::ParseError(
|
return Err(PythonInstallationKeyError::ParseError(
|
||||||
key.to_string(),
|
key.to_string(),
|
||||||
"invalid Python version: expected `<major>.<minor>.<patch>`".to_string(),
|
"invalid Python version: expected `<major>.<minor>.<patch>`".to_string(),
|
||||||
));
|
));
|
||||||
|
@ -329,12 +330,12 @@ impl FromStr for ToolchainKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialOrd for ToolchainKey {
|
impl PartialOrd for PythonInstallationKey {
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||||
Some(self.cmp(other))
|
Some(self.cmp(other))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Ord for ToolchainKey {
|
impl Ord for PythonInstallationKey {
|
||||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||||
self.to_string().cmp(&other.to_string())
|
self.to_string().cmp(&other.to_string())
|
||||||
}
|
}
|
File diff suppressed because it is too large
Load diff
|
@ -14,11 +14,11 @@ use crate::downloads::Error as DownloadError;
|
||||||
use crate::implementation::{
|
use crate::implementation::{
|
||||||
Error as ImplementationError, ImplementationName, LenientImplementationName,
|
Error as ImplementationError, ImplementationName, LenientImplementationName,
|
||||||
};
|
};
|
||||||
|
use crate::installation::{self, PythonInstallationKey};
|
||||||
use crate::platform::Error as PlatformError;
|
use crate::platform::Error as PlatformError;
|
||||||
use crate::platform::{Arch, Libc, Os};
|
use crate::platform::{Arch, Libc, Os};
|
||||||
use crate::python_version::PythonVersion;
|
use crate::python_version::PythonVersion;
|
||||||
use crate::toolchain::{self, ToolchainKey};
|
use crate::PythonRequest;
|
||||||
use crate::ToolchainRequest;
|
|
||||||
use uv_fs::{LockedFile, Simplified};
|
use uv_fs::{LockedFile, Simplified};
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
|
@ -41,26 +41,26 @@ pub enum Error {
|
||||||
#[source]
|
#[source]
|
||||||
err: io::Error,
|
err: io::Error,
|
||||||
},
|
},
|
||||||
#[error("Failed to read toolchain directory: {0}", dir.user_display())]
|
#[error("Failed to read Python installation directory: {0}", dir.user_display())]
|
||||||
ReadError {
|
ReadError {
|
||||||
dir: PathBuf,
|
dir: PathBuf,
|
||||||
#[source]
|
#[source]
|
||||||
err: io::Error,
|
err: io::Error,
|
||||||
},
|
},
|
||||||
#[error("Failed to read toolchain directory name: {0}")]
|
#[error("Failed to read managed Python directory name: {0}")]
|
||||||
NameError(String),
|
NameError(String),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
NameParseError(#[from] toolchain::ToolchainKeyError),
|
NameParseError(#[from] installation::PythonInstallationKeyError),
|
||||||
}
|
}
|
||||||
/// A collection of uv-managed Python toolchains installed on the current system.
|
/// A collection of uv-managed Python installations installed on the current system.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct InstalledToolchains {
|
pub struct ManagedPythonInstallations {
|
||||||
/// The path to the top-level directory of the installed toolchains.
|
/// The path to the top-level directory of the installed Python versions.
|
||||||
root: PathBuf,
|
root: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InstalledToolchains {
|
impl ManagedPythonInstallations {
|
||||||
/// A directory for installed toolchains at `root`.
|
/// A directory for Python installations at `root`.
|
||||||
fn from_path(root: impl Into<PathBuf>) -> Self {
|
fn from_path(root: impl Into<PathBuf>) -> Self {
|
||||||
Self { root: root.into() }
|
Self { root: root.into() }
|
||||||
}
|
}
|
||||||
|
@ -74,33 +74,48 @@ impl InstalledToolchains {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prefer, in order:
|
/// Prefer, in order:
|
||||||
/// 1. The specific toolchain directory specified by the user, i.e., `UV_TOOLCHAIN_DIR`
|
/// 1. The specific Python directory specified by the user, i.e., `UV_PYTHON_INSTALL_DIR`
|
||||||
/// 2. A directory in the system-appropriate user-level data directory, e.g., `~/.local/uv/toolchains`
|
/// 2. A directory in the system-appropriate user-level data directory, e.g., `~/.local/uv/python`
|
||||||
/// 3. A directory in the local data directory, e.g., `./.uv/toolchains`
|
/// 3. A directory in the local data directory, e.g., `./.uv/python`
|
||||||
pub fn from_settings() -> Result<Self, Error> {
|
pub fn from_settings() -> Result<Self, Error> {
|
||||||
if let Some(toolchain_dir) = std::env::var_os("UV_TOOLCHAIN_DIR") {
|
if let Some(install_dir) = std::env::var_os("UV_PYTHON_INSTALL_DIR") {
|
||||||
Ok(Self::from_path(toolchain_dir))
|
Ok(Self::from_path(install_dir))
|
||||||
} else {
|
} else {
|
||||||
Ok(Self::from_path(
|
Ok(Self::from_path(
|
||||||
StateStore::from_settings(None)?.bucket(StateBucket::Toolchains),
|
StateStore::from_settings(None)?.bucket(StateBucket::ManagedPython),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a temporary installed toolchain directory.
|
/// Create a temporary Python installation directory.
|
||||||
pub fn temp() -> Result<Self, Error> {
|
pub fn temp() -> Result<Self, Error> {
|
||||||
Ok(Self::from_path(
|
Ok(Self::from_path(
|
||||||
StateStore::temp()?.bucket(StateBucket::Toolchains),
|
StateStore::temp()?.bucket(StateBucket::ManagedPython),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize the installed toolchain directory.
|
/// Initialize the Python installation directory.
|
||||||
///
|
///
|
||||||
/// Ensures the directory is created.
|
/// Ensures the directory is created.
|
||||||
pub fn init(self) -> Result<Self, Error> {
|
pub fn init(self) -> Result<Self, Error> {
|
||||||
let root = &self.root;
|
let root = &self.root;
|
||||||
|
|
||||||
// Create the toolchain directory, if it doesn't exist.
|
// Support `toolchains` -> `python` migration transparently.
|
||||||
|
if !root.exists()
|
||||||
|
&& root
|
||||||
|
.parent()
|
||||||
|
.is_some_and(|parent| parent.join("toolchains").exists())
|
||||||
|
{
|
||||||
|
let deprecated = root.parent().unwrap().join("toolchains");
|
||||||
|
// Move the deprecated directory to the new location.
|
||||||
|
fs::rename(&deprecated, root)?;
|
||||||
|
// Create a link or junction to at the old location
|
||||||
|
uv_fs::replace_symlink(root, &deprecated)?;
|
||||||
|
} else {
|
||||||
|
fs::create_dir_all(root)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the directory, if it doesn't exist.
|
||||||
fs::create_dir_all(root)?;
|
fs::create_dir_all(root)?;
|
||||||
|
|
||||||
// Add a .gitignore.
|
// Add a .gitignore.
|
||||||
|
@ -117,17 +132,19 @@ impl InstalledToolchains {
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over each installed toolchain in this directory.
|
/// Iterate over each Python installation in this directory.
|
||||||
///
|
///
|
||||||
/// Toolchains are sorted descending by name, such that we get deterministic
|
/// Pythons are sorted descending by name, such that we get deterministic
|
||||||
/// ordering across platforms. This also results in newer Python versions coming first,
|
/// ordering across platforms. This also results in newer Python versions coming first,
|
||||||
/// but should not be relied on — instead the toolchains should be sorted later by
|
/// but should not be relied on — instead the installations should be sorted later by
|
||||||
/// the parsed Python version.
|
/// the parsed Python version.
|
||||||
pub fn find_all(&self) -> Result<impl DoubleEndedIterator<Item = InstalledToolchain>, Error> {
|
pub fn find_all(
|
||||||
|
&self,
|
||||||
|
) -> Result<impl DoubleEndedIterator<Item = ManagedPythonInstallation>, Error> {
|
||||||
let dirs = match fs_err::read_dir(&self.root) {
|
let dirs = match fs_err::read_dir(&self.root) {
|
||||||
Ok(toolchain_dirs) => {
|
Ok(installation_dirs) => {
|
||||||
// Collect sorted directory paths; `read_dir` is not stable across platforms
|
// Collect sorted directory paths; `read_dir` is not stable across platforms
|
||||||
let directories: BTreeSet<_> = toolchain_dirs
|
let directories: BTreeSet<_> = installation_dirs
|
||||||
.filter_map(|read_dir| match read_dir {
|
.filter_map(|read_dir| match read_dir {
|
||||||
Ok(entry) => match entry.file_type() {
|
Ok(entry) => match entry.file_type() {
|
||||||
Ok(file_type) => file_type.is_dir().then_some(Ok(entry.path())),
|
Ok(file_type) => file_type.is_dir().then_some(Ok(entry.path())),
|
||||||
|
@ -153,25 +170,25 @@ impl InstalledToolchains {
|
||||||
Ok(dirs
|
Ok(dirs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|path| {
|
.filter_map(|path| {
|
||||||
InstalledToolchain::new(path)
|
ManagedPythonInstallation::new(path)
|
||||||
.inspect_err(|err| {
|
.inspect_err(|err| {
|
||||||
warn!("Ignoring malformed toolchain entry:\n {err}");
|
warn!("Ignoring malformed managed Python entry:\n {err}");
|
||||||
})
|
})
|
||||||
.ok()
|
.ok()
|
||||||
})
|
})
|
||||||
.rev())
|
.rev())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over toolchains that support the current platform.
|
/// Iterate over Python installations that support the current platform.
|
||||||
pub fn find_matching_current_platform(
|
pub fn find_matching_current_platform(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<impl DoubleEndedIterator<Item = InstalledToolchain>, Error> {
|
) -> Result<impl DoubleEndedIterator<Item = ManagedPythonInstallation>, Error> {
|
||||||
let platform_key = platform_key_from_env();
|
let platform_key = platform_key_from_env();
|
||||||
|
|
||||||
let iter = InstalledToolchains::from_settings()?
|
let iter = ManagedPythonInstallations::from_settings()?
|
||||||
.find_all()?
|
.find_all()?
|
||||||
.filter(move |toolchain| {
|
.filter(move |installation| {
|
||||||
toolchain
|
installation
|
||||||
.path
|
.path
|
||||||
.file_name()
|
.file_name()
|
||||||
.map(OsStr::to_string_lossy)
|
.map(OsStr::to_string_lossy)
|
||||||
|
@ -181,20 +198,20 @@ impl InstalledToolchains {
|
||||||
Ok(iter)
|
Ok(iter)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over toolchains that satisfy the given Python version on this platform.
|
/// Iterate over managed Python installations that satisfy the requested version on this platform.
|
||||||
///
|
///
|
||||||
/// ## Errors
|
/// ## Errors
|
||||||
///
|
///
|
||||||
/// - The platform metadata cannot be read
|
/// - The platform metadata cannot be read
|
||||||
/// - A directory in the toolchain directory cannot be read
|
/// - A directory for the installation cannot be read
|
||||||
pub fn find_version<'a>(
|
pub fn find_version<'a>(
|
||||||
&self,
|
&self,
|
||||||
version: &'a PythonVersion,
|
version: &'a PythonVersion,
|
||||||
) -> Result<impl DoubleEndedIterator<Item = InstalledToolchain> + 'a, Error> {
|
) -> Result<impl DoubleEndedIterator<Item = ManagedPythonInstallation> + 'a, Error> {
|
||||||
Ok(self
|
Ok(self
|
||||||
.find_matching_current_platform()?
|
.find_matching_current_platform()?
|
||||||
.filter(move |toolchain| {
|
.filter(move |installation| {
|
||||||
toolchain
|
installation
|
||||||
.path
|
.path
|
||||||
.file_name()
|
.file_name()
|
||||||
.map(OsStr::to_string_lossy)
|
.map(OsStr::to_string_lossy)
|
||||||
|
@ -208,21 +225,21 @@ impl InstalledToolchains {
|
||||||
}
|
}
|
||||||
|
|
||||||
static EXTERNALLY_MANAGED: &str = "[externally-managed]
|
static EXTERNALLY_MANAGED: &str = "[externally-managed]
|
||||||
Error=This toolchain is managed by uv and should not be modified.
|
Error=This Python installation is managed by uv and should not be modified.
|
||||||
";
|
";
|
||||||
|
|
||||||
/// A uv-managed Python toolchain installed on the current system..
|
/// A uv-managed Python installation on the current system..
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
pub struct InstalledToolchain {
|
pub struct ManagedPythonInstallation {
|
||||||
/// The path to the top-level directory of the installed toolchain.
|
/// The path to the top-level directory of the installed Python.
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
/// An install key for the toolchain.
|
/// An install key for the Python version.
|
||||||
key: ToolchainKey,
|
key: PythonInstallationKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InstalledToolchain {
|
impl ManagedPythonInstallation {
|
||||||
pub fn new(path: PathBuf) -> Result<Self, Error> {
|
pub fn new(path: PathBuf) -> Result<Self, Error> {
|
||||||
let key = ToolchainKey::from_str(
|
let key = PythonInstallationKey::from_str(
|
||||||
path.file_name()
|
path.file_name()
|
||||||
.ok_or(Error::NameError("name is empty".to_string()))?
|
.ok_or(Error::NameError("name is empty".to_string()))?
|
||||||
.to_str()
|
.to_str()
|
||||||
|
@ -252,7 +269,7 @@ impl InstalledToolchain {
|
||||||
match self.key.implementation() {
|
match self.key.implementation() {
|
||||||
LenientImplementationName::Known(implementation) => implementation,
|
LenientImplementationName::Known(implementation) => implementation,
|
||||||
LenientImplementationName::Unknown(_) => {
|
LenientImplementationName::Unknown(_) => {
|
||||||
panic!("Managed toolchains should have a known implementation")
|
panic!("Managed Python installations should have a known implementation")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,31 +278,31 @@ impl InstalledToolchain {
|
||||||
&self.path
|
&self.path
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn key(&self) -> &ToolchainKey {
|
pub fn key(&self) -> &PythonInstallationKey {
|
||||||
&self.key
|
&self.key
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn satisfies(&self, request: &ToolchainRequest) -> bool {
|
pub fn satisfies(&self, request: &PythonRequest) -> bool {
|
||||||
match request {
|
match request {
|
||||||
ToolchainRequest::File(path) => self.executable() == *path,
|
PythonRequest::File(path) => self.executable() == *path,
|
||||||
ToolchainRequest::Any => true,
|
PythonRequest::Any => true,
|
||||||
ToolchainRequest::Directory(path) => self.path() == *path,
|
PythonRequest::Directory(path) => self.path() == *path,
|
||||||
ToolchainRequest::ExecutableName(name) => self
|
PythonRequest::ExecutableName(name) => self
|
||||||
.executable()
|
.executable()
|
||||||
.file_name()
|
.file_name()
|
||||||
.is_some_and(|filename| filename.to_string_lossy() == *name),
|
.is_some_and(|filename| filename.to_string_lossy() == *name),
|
||||||
ToolchainRequest::Implementation(implementation) => {
|
PythonRequest::Implementation(implementation) => {
|
||||||
implementation == self.implementation()
|
implementation == self.implementation()
|
||||||
}
|
}
|
||||||
ToolchainRequest::ImplementationVersion(implementation, version) => {
|
PythonRequest::ImplementationVersion(implementation, version) => {
|
||||||
implementation == self.implementation() && version.matches_version(&self.version())
|
implementation == self.implementation() && version.matches_version(&self.version())
|
||||||
}
|
}
|
||||||
ToolchainRequest::Version(version) => version.matches_version(&self.version()),
|
PythonRequest::Version(version) => version.matches_version(&self.version()),
|
||||||
ToolchainRequest::Key(request) => request.satisfied_by_key(self.key()),
|
PythonRequest::Key(request) => request.satisfied_by_key(self.key()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ensure the toolchain is marked as externally managed with the
|
/// Ensure the environment is marked as externally managed with the
|
||||||
/// standard `EXTERNALLY-MANAGED` file.
|
/// standard `EXTERNALLY-MANAGED` file.
|
||||||
pub fn ensure_externally_managed(&self) -> Result<(), Error> {
|
pub fn ensure_externally_managed(&self) -> Result<(), Error> {
|
||||||
// Construct the path to the `stdlib` directory.
|
// Construct the path to the `stdlib` directory.
|
||||||
|
@ -311,7 +328,7 @@ fn platform_key_from_env() -> String {
|
||||||
format!("{os}-{arch}-{libc}").to_lowercase()
|
format!("{os}-{arch}-{libc}").to_lowercase()
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for InstalledToolchain {
|
impl fmt::Display for ManagedPythonInstallation {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
|
@ -2,40 +2,40 @@ use fs_err as fs;
|
||||||
use std::{io, path::PathBuf};
|
use std::{io, path::PathBuf};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use crate::ToolchainRequest;
|
use crate::PythonRequest;
|
||||||
|
|
||||||
/// Read [`ToolchainRequest`]s from a version file, if present.
|
/// Read [`PythonRequest`]s from a version file, if present.
|
||||||
///
|
///
|
||||||
/// Prefers `.python-versions` then `.python-version`.
|
/// Prefers `.python-versions` then `.python-version`.
|
||||||
/// If only one Python version is desired, use [`request_from_version_files`] which prefers the `.python-version` file.
|
/// If only one Python version is desired, use [`request_from_version_files`] which prefers the `.python-version` file.
|
||||||
pub async fn requests_from_version_file() -> Result<Option<Vec<ToolchainRequest>>, io::Error> {
|
pub async fn requests_from_version_file() -> Result<Option<Vec<PythonRequest>>, io::Error> {
|
||||||
if let Some(versions) = read_versions_file().await? {
|
if let Some(versions) = read_versions_file().await? {
|
||||||
Ok(Some(
|
Ok(Some(
|
||||||
versions
|
versions
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|version| ToolchainRequest::parse(&version))
|
.map(|version| PythonRequest::parse(&version))
|
||||||
.collect(),
|
.collect(),
|
||||||
))
|
))
|
||||||
} else if let Some(version) = read_version_file().await? {
|
} else if let Some(version) = read_version_file().await? {
|
||||||
Ok(Some(vec![ToolchainRequest::parse(&version)]))
|
Ok(Some(vec![PythonRequest::parse(&version)]))
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read a [`ToolchainRequest`] from a version file, if present.
|
/// Read a [`PythonRequest`] from a version file, if present.
|
||||||
///
|
///
|
||||||
/// Prefers `.python-version` then the first entry of `.python-versions`.
|
/// Prefers `.python-version` then the first entry of `.python-versions`.
|
||||||
/// If multiple Python versions are desired, use [`requests_from_version_files`] instead.
|
/// If multiple Python versions are desired, use [`requests_from_version_files`] instead.
|
||||||
pub async fn request_from_version_file() -> Result<Option<ToolchainRequest>, io::Error> {
|
pub async fn request_from_version_file() -> Result<Option<PythonRequest>, io::Error> {
|
||||||
if let Some(version) = read_version_file().await? {
|
if let Some(version) = read_version_file().await? {
|
||||||
Ok(Some(ToolchainRequest::parse(&version)))
|
Ok(Some(PythonRequest::parse(&version)))
|
||||||
} else if let Some(versions) = read_versions_file().await? {
|
} else if let Some(versions) = read_versions_file().await? {
|
||||||
Ok(versions
|
Ok(versions
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.inspect(|_| debug!("Using the first version from `.python-versions`"))
|
.inspect(|_| debug!("Using the first version from `.python-versions`"))
|
||||||
.map(|version| ToolchainRequest::parse(&version)))
|
.map(|version| PythonRequest::parse(&version)))
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
|
@ -6,7 +6,7 @@ Generates the `downloads.inc` file from the `downloads.inc.mustache` template.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
uv run --isolated --with chevron-blue -- crates/uv-toolchain/template-download-metadata.py
|
uv run --isolated --with chevron-blue -- crates/uv-python/template-download-metadata.py
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sys
|
import sys
|
|
@ -27,7 +27,7 @@ uv-client = { workspace = true }
|
||||||
uv-configuration = { workspace = true }
|
uv-configuration = { workspace = true }
|
||||||
uv-distribution = { workspace = true }
|
uv-distribution = { workspace = true }
|
||||||
uv-git = { workspace = true }
|
uv-git = { workspace = true }
|
||||||
uv-toolchain = { workspace = true }
|
uv-python = { workspace = true }
|
||||||
uv-normalize = { workspace = true }
|
uv-normalize = { workspace = true }
|
||||||
uv-types = { workspace = true }
|
uv-types = { workspace = true }
|
||||||
uv-warnings = { workspace = true }
|
uv-warnings = { workspace = true }
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use pep440_rs::VersionSpecifiers;
|
use pep440_rs::VersionSpecifiers;
|
||||||
use pep508_rs::{MarkerTree, StringVersion};
|
use pep508_rs::{MarkerTree, StringVersion};
|
||||||
use uv_toolchain::{Interpreter, PythonVersion};
|
use uv_python::{Interpreter, PythonVersion};
|
||||||
|
|
||||||
use crate::{RequiresPython, RequiresPythonBound};
|
use crate::{RequiresPython, RequiresPythonBound};
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ uv-fs = { workspace = true }
|
||||||
uv-macros = { workspace = true }
|
uv-macros = { workspace = true }
|
||||||
uv-normalize = { workspace = true, features = ["schemars"] }
|
uv-normalize = { workspace = true, features = ["schemars"] }
|
||||||
uv-resolver = { workspace = true, features = ["schemars"] }
|
uv-resolver = { workspace = true, features = ["schemars"] }
|
||||||
uv-toolchain = { workspace = true, features = ["schemars"] }
|
uv-python = { workspace = true, features = ["schemars"] }
|
||||||
uv-warnings = { workspace = true }
|
uv-warnings = { workspace = true }
|
||||||
|
|
||||||
dirs-sys = { workspace = true }
|
dirs-sys = { workspace = true }
|
||||||
|
|
|
@ -4,8 +4,8 @@ use std::path::PathBuf;
|
||||||
use distribution_types::IndexUrl;
|
use distribution_types::IndexUrl;
|
||||||
use install_wheel_rs::linker::LinkMode;
|
use install_wheel_rs::linker::LinkMode;
|
||||||
use uv_configuration::{ConfigSettings, IndexStrategy, KeyringProviderType, TargetTriple};
|
use uv_configuration::{ConfigSettings, IndexStrategy, KeyringProviderType, TargetTriple};
|
||||||
|
use uv_python::{PythonFetch, PythonPreference, PythonVersion};
|
||||||
use uv_resolver::{AnnotationStyle, ExcludeNewer, PreReleaseMode, ResolutionMode};
|
use uv_resolver::{AnnotationStyle, ExcludeNewer, PreReleaseMode, ResolutionMode};
|
||||||
use uv_toolchain::{PythonVersion, ToolchainFetch, ToolchainPreference};
|
|
||||||
|
|
||||||
use crate::{FilesystemOptions, PipOptions};
|
use crate::{FilesystemOptions, PipOptions};
|
||||||
|
|
||||||
|
@ -69,8 +69,8 @@ impl_combine_or!(PythonVersion);
|
||||||
impl_combine_or!(ResolutionMode);
|
impl_combine_or!(ResolutionMode);
|
||||||
impl_combine_or!(String);
|
impl_combine_or!(String);
|
||||||
impl_combine_or!(TargetTriple);
|
impl_combine_or!(TargetTriple);
|
||||||
impl_combine_or!(ToolchainPreference);
|
impl_combine_or!(PythonPreference);
|
||||||
impl_combine_or!(ToolchainFetch);
|
impl_combine_or!(PythonFetch);
|
||||||
impl_combine_or!(bool);
|
impl_combine_or!(bool);
|
||||||
|
|
||||||
impl<T> Combine for Option<Vec<T>> {
|
impl<T> Combine for Option<Vec<T>> {
|
||||||
|
|
|
@ -10,8 +10,8 @@ use uv_configuration::{
|
||||||
};
|
};
|
||||||
use uv_macros::CombineOptions;
|
use uv_macros::CombineOptions;
|
||||||
use uv_normalize::{ExtraName, PackageName};
|
use uv_normalize::{ExtraName, PackageName};
|
||||||
|
use uv_python::{PythonFetch, PythonPreference, PythonVersion};
|
||||||
use uv_resolver::{AnnotationStyle, ExcludeNewer, PreReleaseMode, ResolutionMode};
|
use uv_resolver::{AnnotationStyle, ExcludeNewer, PreReleaseMode, ResolutionMode};
|
||||||
use uv_toolchain::{PythonVersion, ToolchainFetch, ToolchainPreference};
|
|
||||||
|
|
||||||
/// A `pyproject.toml` with an (optional) `[tool.uv]` section.
|
/// A `pyproject.toml` with an (optional) `[tool.uv]` section.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -59,8 +59,8 @@ pub struct GlobalOptions {
|
||||||
pub no_cache: Option<bool>,
|
pub no_cache: Option<bool>,
|
||||||
pub cache_dir: Option<PathBuf>,
|
pub cache_dir: Option<PathBuf>,
|
||||||
pub preview: Option<bool>,
|
pub preview: Option<bool>,
|
||||||
pub toolchain_preference: Option<ToolchainPreference>,
|
pub python_preference: Option<PythonPreference>,
|
||||||
pub toolchain_fetch: Option<ToolchainFetch>,
|
pub python_fetch: Option<PythonFetch>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Settings relevant to all installer operations.
|
/// Settings relevant to all installer operations.
|
||||||
|
|
|
@ -95,8 +95,8 @@ impl StateStore {
|
||||||
/// are subdirectories of the state store root.
|
/// are subdirectories of the state store root.
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||||
pub enum StateBucket {
|
pub enum StateBucket {
|
||||||
// Managed toolchains
|
// Managed Python installations
|
||||||
Toolchains,
|
ManagedPython,
|
||||||
// Installed tools
|
// Installed tools
|
||||||
Tools,
|
Tools,
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ pub enum StateBucket {
|
||||||
impl StateBucket {
|
impl StateBucket {
|
||||||
fn to_str(self) -> &'static str {
|
fn to_str(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Self::Toolchains => "toolchains",
|
Self::ManagedPython => "python",
|
||||||
Self::Tools => "tools",
|
Self::Tools => "tools",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ pypi-types = { workspace = true }
|
||||||
uv-cache = { workspace = true }
|
uv-cache = { workspace = true }
|
||||||
uv-fs = { workspace = true }
|
uv-fs = { workspace = true }
|
||||||
uv-state = { workspace = true }
|
uv-state = { workspace = true }
|
||||||
uv-toolchain = { workspace = true }
|
uv-python = { workspace = true }
|
||||||
uv-virtualenv = { workspace = true }
|
uv-virtualenv = { workspace = true }
|
||||||
uv-warnings = { workspace = true }
|
uv-warnings = { workspace = true }
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,8 @@ pub use receipt::ToolReceipt;
|
||||||
pub use tool::{Tool, ToolEntrypoint};
|
pub use tool::{Tool, ToolEntrypoint};
|
||||||
use uv_cache::Cache;
|
use uv_cache::Cache;
|
||||||
use uv_fs::{LockedFile, Simplified};
|
use uv_fs::{LockedFile, Simplified};
|
||||||
|
use uv_python::{Interpreter, PythonEnvironment};
|
||||||
use uv_state::{StateBucket, StateStore};
|
use uv_state::{StateBucket, StateStore};
|
||||||
use uv_toolchain::{Interpreter, PythonEnvironment};
|
|
||||||
use uv_warnings::warn_user_once;
|
use uv_warnings::warn_user_once;
|
||||||
|
|
||||||
mod receipt;
|
mod receipt;
|
||||||
|
@ -38,7 +38,7 @@ pub enum Error {
|
||||||
#[error("Failed to find a directory for executables")]
|
#[error("Failed to find a directory for executables")]
|
||||||
NoExecutableDirectory,
|
NoExecutableDirectory,
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
EnvironmentError(#[from] uv_toolchain::Error),
|
EnvironmentError(#[from] uv_python::Error),
|
||||||
#[error("Failed to find a receipt for tool `{0}` at {1}")]
|
#[error("Failed to find a receipt for tool `{0}` at {1}")]
|
||||||
MissingToolReceipt(String, PathBuf),
|
MissingToolReceipt(String, PathBuf),
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ pypi-types = { workspace = true }
|
||||||
uv-cache = { workspace = true }
|
uv-cache = { workspace = true }
|
||||||
uv-configuration = { workspace = true }
|
uv-configuration = { workspace = true }
|
||||||
uv-git = { workspace = true }
|
uv-git = { workspace = true }
|
||||||
uv-toolchain = { workspace = true }
|
uv-python = { workspace = true }
|
||||||
uv-normalize = { workspace = true }
|
uv-normalize = { workspace = true }
|
||||||
|
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use uv_toolchain::PythonEnvironment;
|
use uv_python::PythonEnvironment;
|
||||||
|
|
||||||
/// Whether to enforce build isolation when building source distributions.
|
/// Whether to enforce build isolation when building source distributions.
|
||||||
#[derive(Debug, Default, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
|
|
|
@ -9,7 +9,7 @@ use pypi_types::Requirement;
|
||||||
use uv_cache::Cache;
|
use uv_cache::Cache;
|
||||||
use uv_configuration::{BuildKind, BuildOptions};
|
use uv_configuration::{BuildKind, BuildOptions};
|
||||||
use uv_git::GitResolver;
|
use uv_git::GitResolver;
|
||||||
use uv_toolchain::{Interpreter, PythonEnvironment};
|
use uv_python::{Interpreter, PythonEnvironment};
|
||||||
|
|
||||||
/// Avoids cyclic crate dependencies between resolver, installer and builder.
|
/// Avoids cyclic crate dependencies between resolver, installer and builder.
|
||||||
///
|
///
|
||||||
|
|
|
@ -20,7 +20,7 @@ workspace = true
|
||||||
platform-tags = { workspace = true }
|
platform-tags = { workspace = true }
|
||||||
pypi-types = { workspace = true }
|
pypi-types = { workspace = true }
|
||||||
uv-fs = { workspace = true }
|
uv-fs = { workspace = true }
|
||||||
uv-toolchain = { workspace = true }
|
uv-python = { workspace = true }
|
||||||
uv-version = { workspace = true }
|
uv-version = { workspace = true }
|
||||||
|
|
||||||
fs-err = { workspace = true }
|
fs-err = { workspace = true }
|
||||||
|
|
|
@ -13,7 +13,7 @@ use tracing::info;
|
||||||
|
|
||||||
use pypi_types::Scheme;
|
use pypi_types::Scheme;
|
||||||
use uv_fs::{cachedir, Simplified};
|
use uv_fs::{cachedir, Simplified};
|
||||||
use uv_toolchain::{Interpreter, VirtualEnvironment};
|
use uv_python::{Interpreter, VirtualEnvironment};
|
||||||
use uv_version::version;
|
use uv_version::version;
|
||||||
|
|
||||||
use crate::{Error, Prompt};
|
use crate::{Error, Prompt};
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::path::Path;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use platform_tags::PlatformError;
|
use platform_tags::PlatformError;
|
||||||
use uv_toolchain::{Interpreter, PythonEnvironment};
|
use uv_python::{Interpreter, PythonEnvironment};
|
||||||
|
|
||||||
pub use crate::bare::create_bare_venv;
|
pub use crate::bare::create_bare_venv;
|
||||||
|
|
||||||
|
@ -15,9 +15,9 @@ pub enum Error {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
IO(#[from] io::Error),
|
IO(#[from] io::Error),
|
||||||
#[error("Failed to determine Python interpreter to use")]
|
#[error("Failed to determine Python interpreter to use")]
|
||||||
Discovery(#[from] uv_toolchain::DiscoveryError),
|
Discovery(#[from] uv_python::DiscoveryError),
|
||||||
#[error("Failed to determine Python interpreter to use")]
|
#[error("Failed to determine Python interpreter to use")]
|
||||||
InterpreterNotFound(#[from] uv_toolchain::ToolchainNotFound),
|
InterpreterNotFound(#[from] uv_python::PythonNotFound),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Platform(#[from] PlatformError),
|
Platform(#[from] PlatformError),
|
||||||
#[error("Could not find a suitable Python executable for the virtual environment based on the interpreter: {0}")]
|
#[error("Could not find a suitable Python executable for the virtual environment based on the interpreter: {0}")]
|
||||||
|
|
|
@ -36,7 +36,7 @@ uv-resolver = { workspace = true }
|
||||||
uv-scripts = { workspace = true }
|
uv-scripts = { workspace = true }
|
||||||
uv-settings = { workspace = true, features = ["schemars"] }
|
uv-settings = { workspace = true, features = ["schemars"] }
|
||||||
uv-tool = { workspace = true }
|
uv-tool = { workspace = true }
|
||||||
uv-toolchain = { workspace = true, features = ["schemars"]}
|
uv-python = { workspace = true, features = ["schemars"]}
|
||||||
uv-types = { workspace = true }
|
uv-types = { workspace = true }
|
||||||
uv-virtualenv = { workspace = true }
|
uv-virtualenv = { workspace = true }
|
||||||
uv-warnings = { workspace = true }
|
uv-warnings = { workspace = true }
|
||||||
|
|
|
@ -22,6 +22,11 @@ pub(crate) use project::lock::lock;
|
||||||
pub(crate) use project::remove::remove;
|
pub(crate) use project::remove::remove;
|
||||||
pub(crate) use project::run::run;
|
pub(crate) use project::run::run;
|
||||||
pub(crate) use project::sync::sync;
|
pub(crate) use project::sync::sync;
|
||||||
|
pub(crate) use python::dir::dir as python_dir;
|
||||||
|
pub(crate) use python::find::find as python_find;
|
||||||
|
pub(crate) use python::install::install as python_install;
|
||||||
|
pub(crate) use python::list::list as python_list;
|
||||||
|
pub(crate) use python::uninstall::uninstall as python_uninstall;
|
||||||
#[cfg(feature = "self-update")]
|
#[cfg(feature = "self-update")]
|
||||||
pub(crate) use self_update::self_update;
|
pub(crate) use self_update::self_update;
|
||||||
pub(crate) use tool::dir::dir as tool_dir;
|
pub(crate) use tool::dir::dir as tool_dir;
|
||||||
|
@ -29,16 +34,11 @@ pub(crate) use tool::install::install as tool_install;
|
||||||
pub(crate) use tool::list::list as tool_list;
|
pub(crate) use tool::list::list as tool_list;
|
||||||
pub(crate) use tool::run::run as tool_run;
|
pub(crate) use tool::run::run as tool_run;
|
||||||
pub(crate) use tool::uninstall::uninstall as tool_uninstall;
|
pub(crate) use tool::uninstall::uninstall as tool_uninstall;
|
||||||
pub(crate) use toolchain::dir::dir as toolchain_dir;
|
|
||||||
pub(crate) use toolchain::find::find as toolchain_find;
|
|
||||||
pub(crate) use toolchain::install::install as toolchain_install;
|
|
||||||
pub(crate) use toolchain::list::list as toolchain_list;
|
|
||||||
pub(crate) use toolchain::uninstall::uninstall as toolchain_uninstall;
|
|
||||||
use uv_cache::Cache;
|
use uv_cache::Cache;
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
use uv_installer::compile_tree;
|
use uv_installer::compile_tree;
|
||||||
use uv_normalize::PackageName;
|
use uv_normalize::PackageName;
|
||||||
use uv_toolchain::PythonEnvironment;
|
use uv_python::PythonEnvironment;
|
||||||
pub(crate) use venv::venv;
|
pub(crate) use venv::venv;
|
||||||
pub(crate) use version::version;
|
pub(crate) use version::version;
|
||||||
|
|
||||||
|
@ -49,9 +49,9 @@ mod cache_dir;
|
||||||
mod cache_prune;
|
mod cache_prune;
|
||||||
pub(crate) mod pip;
|
pub(crate) mod pip;
|
||||||
mod project;
|
mod project;
|
||||||
|
mod python;
|
||||||
pub(crate) mod reporters;
|
pub(crate) mod reporters;
|
||||||
mod tool;
|
mod tool;
|
||||||
mod toolchain;
|
|
||||||
|
|
||||||
#[cfg(feature = "self-update")]
|
#[cfg(feature = "self-update")]
|
||||||
mod self_update;
|
mod self_update;
|
||||||
|
|
|
@ -10,7 +10,7 @@ use uv_cache::Cache;
|
||||||
use uv_configuration::PreviewMode;
|
use uv_configuration::PreviewMode;
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
use uv_installer::{SitePackages, SitePackagesDiagnostic};
|
use uv_installer::{SitePackages, SitePackagesDiagnostic};
|
||||||
use uv_toolchain::{EnvironmentPreference, PythonEnvironment, ToolchainRequest};
|
use uv_python::{EnvironmentPreference, PythonEnvironment, PythonRequest};
|
||||||
|
|
||||||
use crate::commands::{elapsed, ExitStatus};
|
use crate::commands::{elapsed, ExitStatus};
|
||||||
use crate::printer::Printer;
|
use crate::printer::Printer;
|
||||||
|
@ -27,7 +27,7 @@ pub(crate) fn pip_check(
|
||||||
|
|
||||||
// Detect the current Python interpreter.
|
// Detect the current Python interpreter.
|
||||||
let environment = PythonEnvironment::find(
|
let environment = PythonEnvironment::find(
|
||||||
&python.map(ToolchainRequest::parse).unwrap_or_default(),
|
&python.map(PythonRequest::parse).unwrap_or_default(),
|
||||||
EnvironmentPreference::from_system_flag(system, false),
|
EnvironmentPreference::from_system_flag(system, false),
|
||||||
cache,
|
cache,
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -23,6 +23,10 @@ use uv_dispatch::BuildDispatch;
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
use uv_git::GitResolver;
|
use uv_git::GitResolver;
|
||||||
use uv_normalize::PackageName;
|
use uv_normalize::PackageName;
|
||||||
|
use uv_python::{
|
||||||
|
EnvironmentPreference, PythonEnvironment, PythonInstallation, PythonPreference, PythonRequest,
|
||||||
|
PythonVersion, VersionRequest,
|
||||||
|
};
|
||||||
use uv_requirements::{
|
use uv_requirements::{
|
||||||
upgrade::read_requirements_txt, RequirementsSource, RequirementsSpecification,
|
upgrade::read_requirements_txt, RequirementsSource, RequirementsSpecification,
|
||||||
};
|
};
|
||||||
|
@ -31,10 +35,6 @@ use uv_resolver::{
|
||||||
InMemoryIndex, OptionsBuilder, PreReleaseMode, PythonRequirement, RequiresPython,
|
InMemoryIndex, OptionsBuilder, PreReleaseMode, PythonRequirement, RequiresPython,
|
||||||
ResolutionMode,
|
ResolutionMode,
|
||||||
};
|
};
|
||||||
use uv_toolchain::{
|
|
||||||
EnvironmentPreference, PythonEnvironment, PythonVersion, Toolchain, ToolchainPreference,
|
|
||||||
ToolchainRequest, VersionRequest,
|
|
||||||
};
|
|
||||||
use uv_types::{BuildIsolation, EmptyInstalledPackages, HashStrategy, InFlight};
|
use uv_types::{BuildIsolation, EmptyInstalledPackages, HashStrategy, InFlight};
|
||||||
use uv_warnings::warn_user;
|
use uv_warnings::warn_user;
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ pub(crate) async fn pip_compile(
|
||||||
link_mode: LinkMode,
|
link_mode: LinkMode,
|
||||||
python: Option<String>,
|
python: Option<String>,
|
||||||
system: bool,
|
system: bool,
|
||||||
toolchain_preference: ToolchainPreference,
|
python_preference: PythonPreference,
|
||||||
concurrency: Concurrency,
|
concurrency: Concurrency,
|
||||||
native_tls: bool,
|
native_tls: bool,
|
||||||
quiet: bool,
|
quiet: bool,
|
||||||
|
@ -159,18 +159,18 @@ pub(crate) async fn pip_compile(
|
||||||
// Find an interpreter to use for building distributions
|
// Find an interpreter to use for building distributions
|
||||||
let environments = EnvironmentPreference::from_system_flag(system, false);
|
let environments = EnvironmentPreference::from_system_flag(system, false);
|
||||||
let interpreter = if let Some(python) = python.as_ref() {
|
let interpreter = if let Some(python) = python.as_ref() {
|
||||||
let request = ToolchainRequest::parse(python);
|
let request = PythonRequest::parse(python);
|
||||||
Toolchain::find(&request, environments, toolchain_preference, &cache)
|
PythonInstallation::find(&request, environments, python_preference, &cache)
|
||||||
} else {
|
} else {
|
||||||
// TODO(zanieb): The split here hints at a problem with the abstraction; we should be able to use
|
// TODO(zanieb): The split here hints at a problem with the abstraction; we should be able to use
|
||||||
// `Toolchain::find(...)` here.
|
// `PythonInstallation::find(...)` here.
|
||||||
let request = if let Some(version) = python_version.as_ref() {
|
let request = if let Some(version) = python_version.as_ref() {
|
||||||
// TODO(zanieb): We should consolidate `VersionRequest` and `PythonVersion`
|
// TODO(zanieb): We should consolidate `VersionRequest` and `PythonVersion`
|
||||||
ToolchainRequest::Version(VersionRequest::from(version))
|
PythonRequest::Version(VersionRequest::from(version))
|
||||||
} else {
|
} else {
|
||||||
ToolchainRequest::default()
|
PythonRequest::default()
|
||||||
};
|
};
|
||||||
Toolchain::find_best(&request, environments, toolchain_preference, &cache)
|
PythonInstallation::find_best(&request, environments, python_preference, &cache)
|
||||||
}?
|
}?
|
||||||
.into_interpreter();
|
.into_interpreter();
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ use uv_cache::Cache;
|
||||||
use uv_configuration::PreviewMode;
|
use uv_configuration::PreviewMode;
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
use uv_installer::SitePackages;
|
use uv_installer::SitePackages;
|
||||||
use uv_toolchain::{EnvironmentPreference, PythonEnvironment, ToolchainRequest};
|
use uv_python::{EnvironmentPreference, PythonEnvironment, PythonRequest};
|
||||||
|
|
||||||
use crate::commands::ExitStatus;
|
use crate::commands::ExitStatus;
|
||||||
use crate::printer::Printer;
|
use crate::printer::Printer;
|
||||||
|
@ -27,7 +27,7 @@ pub(crate) fn pip_freeze(
|
||||||
) -> Result<ExitStatus> {
|
) -> Result<ExitStatus> {
|
||||||
// Detect the current Python interpreter.
|
// Detect the current Python interpreter.
|
||||||
let environment = PythonEnvironment::find(
|
let environment = PythonEnvironment::find(
|
||||||
&python.map(ToolchainRequest::parse).unwrap_or_default(),
|
&python.map(PythonRequest::parse).unwrap_or_default(),
|
||||||
EnvironmentPreference::from_system_flag(system, false),
|
EnvironmentPreference::from_system_flag(system, false),
|
||||||
cache,
|
cache,
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -20,14 +20,14 @@ use uv_dispatch::BuildDispatch;
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
use uv_git::GitResolver;
|
use uv_git::GitResolver;
|
||||||
use uv_installer::{SatisfiesResult, SitePackages};
|
use uv_installer::{SatisfiesResult, SitePackages};
|
||||||
|
use uv_python::{
|
||||||
|
EnvironmentPreference, Prefix, PythonEnvironment, PythonRequest, PythonVersion, Target,
|
||||||
|
};
|
||||||
use uv_requirements::{RequirementsSource, RequirementsSpecification};
|
use uv_requirements::{RequirementsSource, RequirementsSpecification};
|
||||||
use uv_resolver::{
|
use uv_resolver::{
|
||||||
DependencyMode, ExcludeNewer, FlatIndex, InMemoryIndex, OptionsBuilder, PreReleaseMode,
|
DependencyMode, ExcludeNewer, FlatIndex, InMemoryIndex, OptionsBuilder, PreReleaseMode,
|
||||||
PythonRequirement, ResolutionMode,
|
PythonRequirement, ResolutionMode,
|
||||||
};
|
};
|
||||||
use uv_toolchain::{
|
|
||||||
EnvironmentPreference, Prefix, PythonEnvironment, PythonVersion, Target, ToolchainRequest,
|
|
||||||
};
|
|
||||||
use uv_types::{BuildIsolation, HashStrategy, InFlight};
|
use uv_types::{BuildIsolation, HashStrategy, InFlight};
|
||||||
|
|
||||||
use crate::commands::pip::operations::Modifications;
|
use crate::commands::pip::operations::Modifications;
|
||||||
|
@ -119,7 +119,7 @@ pub(crate) async fn pip_install(
|
||||||
let environment = PythonEnvironment::find(
|
let environment = PythonEnvironment::find(
|
||||||
&python
|
&python
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.map(ToolchainRequest::parse)
|
.map(PythonRequest::parse)
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
EnvironmentPreference::from_system_flag(system, true),
|
EnvironmentPreference::from_system_flag(system, true),
|
||||||
&cache,
|
&cache,
|
||||||
|
|
|
@ -15,8 +15,8 @@ use uv_configuration::PreviewMode;
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
use uv_installer::SitePackages;
|
use uv_installer::SitePackages;
|
||||||
use uv_normalize::PackageName;
|
use uv_normalize::PackageName;
|
||||||
use uv_toolchain::ToolchainRequest;
|
use uv_python::PythonRequest;
|
||||||
use uv_toolchain::{EnvironmentPreference, PythonEnvironment};
|
use uv_python::{EnvironmentPreference, PythonEnvironment};
|
||||||
|
|
||||||
use crate::commands::ExitStatus;
|
use crate::commands::ExitStatus;
|
||||||
use crate::printer::Printer;
|
use crate::printer::Printer;
|
||||||
|
@ -37,7 +37,7 @@ pub(crate) fn pip_list(
|
||||||
) -> Result<ExitStatus> {
|
) -> Result<ExitStatus> {
|
||||||
// Detect the current Python interpreter.
|
// Detect the current Python interpreter.
|
||||||
let environment = PythonEnvironment::find(
|
let environment = PythonEnvironment::find(
|
||||||
&python.map(ToolchainRequest::parse).unwrap_or_default(),
|
&python.map(PythonRequest::parse).unwrap_or_default(),
|
||||||
EnvironmentPreference::from_system_flag(system, false),
|
EnvironmentPreference::from_system_flag(system, false),
|
||||||
cache,
|
cache,
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::borrow::Cow;
|
||||||
use pep508_rs::MarkerEnvironment;
|
use pep508_rs::MarkerEnvironment;
|
||||||
use platform_tags::{Tags, TagsError};
|
use platform_tags::{Tags, TagsError};
|
||||||
use uv_configuration::TargetTriple;
|
use uv_configuration::TargetTriple;
|
||||||
use uv_toolchain::{Interpreter, PythonVersion};
|
use uv_python::{Interpreter, PythonVersion};
|
||||||
|
|
||||||
pub(crate) mod check;
|
pub(crate) mod check;
|
||||||
pub(crate) mod compile;
|
pub(crate) mod compile;
|
||||||
|
|
|
@ -29,6 +29,7 @@ use uv_distribution::DistributionDatabase;
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
use uv_installer::{Plan, Planner, Preparer, SitePackages};
|
use uv_installer::{Plan, Planner, Preparer, SitePackages};
|
||||||
use uv_normalize::{GroupName, PackageName};
|
use uv_normalize::{GroupName, PackageName};
|
||||||
|
use uv_python::PythonEnvironment;
|
||||||
use uv_requirements::{
|
use uv_requirements::{
|
||||||
LookaheadResolver, NamedRequirementsResolver, RequirementsSource, RequirementsSpecification,
|
LookaheadResolver, NamedRequirementsResolver, RequirementsSource, RequirementsSpecification,
|
||||||
SourceTreeResolver,
|
SourceTreeResolver,
|
||||||
|
@ -37,7 +38,6 @@ use uv_resolver::{
|
||||||
DependencyMode, Exclusions, FlatIndex, InMemoryIndex, Manifest, Options, Preference,
|
DependencyMode, Exclusions, FlatIndex, InMemoryIndex, Manifest, Options, Preference,
|
||||||
Preferences, PythonRequirement, ResolutionGraph, Resolver,
|
Preferences, PythonRequirement, ResolutionGraph, Resolver,
|
||||||
};
|
};
|
||||||
use uv_toolchain::PythonEnvironment;
|
|
||||||
use uv_types::{HashStrategy, InFlight, InstalledPackagesProvider};
|
use uv_types::{HashStrategy, InFlight, InstalledPackagesProvider};
|
||||||
use uv_warnings::warn_user;
|
use uv_warnings::warn_user;
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ use uv_configuration::PreviewMode;
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
use uv_installer::SitePackages;
|
use uv_installer::SitePackages;
|
||||||
use uv_normalize::PackageName;
|
use uv_normalize::PackageName;
|
||||||
use uv_toolchain::{EnvironmentPreference, PythonEnvironment, ToolchainRequest};
|
use uv_python::{EnvironmentPreference, PythonEnvironment, PythonRequest};
|
||||||
|
|
||||||
use crate::commands::ExitStatus;
|
use crate::commands::ExitStatus;
|
||||||
use crate::printer::Printer;
|
use crate::printer::Printer;
|
||||||
|
@ -42,7 +42,7 @@ pub(crate) fn pip_show(
|
||||||
|
|
||||||
// Detect the current Python interpreter.
|
// Detect the current Python interpreter.
|
||||||
let environment = PythonEnvironment::find(
|
let environment = PythonEnvironment::find(
|
||||||
&python.map(ToolchainRequest::parse).unwrap_or_default(),
|
&python.map(PythonRequest::parse).unwrap_or_default(),
|
||||||
EnvironmentPreference::from_system_flag(system, false),
|
EnvironmentPreference::from_system_flag(system, false),
|
||||||
cache,
|
cache,
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -19,14 +19,14 @@ use uv_dispatch::BuildDispatch;
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
use uv_git::GitResolver;
|
use uv_git::GitResolver;
|
||||||
use uv_installer::SitePackages;
|
use uv_installer::SitePackages;
|
||||||
|
use uv_python::{
|
||||||
|
EnvironmentPreference, Prefix, PythonEnvironment, PythonRequest, PythonVersion, Target,
|
||||||
|
};
|
||||||
use uv_requirements::{RequirementsSource, RequirementsSpecification};
|
use uv_requirements::{RequirementsSource, RequirementsSpecification};
|
||||||
use uv_resolver::{
|
use uv_resolver::{
|
||||||
DependencyMode, ExcludeNewer, FlatIndex, InMemoryIndex, OptionsBuilder, PreReleaseMode,
|
DependencyMode, ExcludeNewer, FlatIndex, InMemoryIndex, OptionsBuilder, PreReleaseMode,
|
||||||
PythonRequirement, ResolutionMode,
|
PythonRequirement, ResolutionMode,
|
||||||
};
|
};
|
||||||
use uv_toolchain::{
|
|
||||||
EnvironmentPreference, Prefix, PythonEnvironment, PythonVersion, Target, ToolchainRequest,
|
|
||||||
};
|
|
||||||
use uv_types::{BuildIsolation, HashStrategy, InFlight};
|
use uv_types::{BuildIsolation, HashStrategy, InFlight};
|
||||||
|
|
||||||
use crate::commands::pip::operations::Modifications;
|
use crate::commands::pip::operations::Modifications;
|
||||||
|
@ -117,7 +117,7 @@ pub(crate) async fn pip_sync(
|
||||||
let environment = PythonEnvironment::find(
|
let environment = PythonEnvironment::find(
|
||||||
&python
|
&python
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.map(ToolchainRequest::parse)
|
.map(PythonRequest::parse)
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
EnvironmentPreference::from_system_flag(system, true),
|
EnvironmentPreference::from_system_flag(system, true),
|
||||||
&cache,
|
&cache,
|
||||||
|
|
|
@ -13,9 +13,9 @@ use uv_cache::Cache;
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
use uv_installer::SitePackages;
|
use uv_installer::SitePackages;
|
||||||
use uv_normalize::PackageName;
|
use uv_normalize::PackageName;
|
||||||
use uv_toolchain::EnvironmentPreference;
|
use uv_python::EnvironmentPreference;
|
||||||
use uv_toolchain::PythonEnvironment;
|
use uv_python::PythonEnvironment;
|
||||||
use uv_toolchain::ToolchainRequest;
|
use uv_python::PythonRequest;
|
||||||
|
|
||||||
use crate::commands::ExitStatus;
|
use crate::commands::ExitStatus;
|
||||||
use crate::printer::Printer;
|
use crate::printer::Printer;
|
||||||
|
@ -36,7 +36,7 @@ pub(crate) fn pip_tree(
|
||||||
) -> Result<ExitStatus> {
|
) -> Result<ExitStatus> {
|
||||||
// Detect the current Python interpreter.
|
// Detect the current Python interpreter.
|
||||||
let environment = PythonEnvironment::find(
|
let environment = PythonEnvironment::find(
|
||||||
&python.map(ToolchainRequest::parse).unwrap_or_default(),
|
&python.map(PythonRequest::parse).unwrap_or_default(),
|
||||||
EnvironmentPreference::from_system_flag(system, false),
|
EnvironmentPreference::from_system_flag(system, false),
|
||||||
cache,
|
cache,
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -13,10 +13,10 @@ use uv_cache::Cache;
|
||||||
use uv_client::{BaseClientBuilder, Connectivity};
|
use uv_client::{BaseClientBuilder, Connectivity};
|
||||||
use uv_configuration::{KeyringProviderType, PreviewMode};
|
use uv_configuration::{KeyringProviderType, PreviewMode};
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
|
use uv_python::EnvironmentPreference;
|
||||||
|
use uv_python::PythonRequest;
|
||||||
|
use uv_python::{Prefix, PythonEnvironment, Target};
|
||||||
use uv_requirements::{RequirementsSource, RequirementsSpecification};
|
use uv_requirements::{RequirementsSource, RequirementsSpecification};
|
||||||
use uv_toolchain::EnvironmentPreference;
|
|
||||||
use uv_toolchain::ToolchainRequest;
|
|
||||||
use uv_toolchain::{Prefix, PythonEnvironment, Target};
|
|
||||||
|
|
||||||
use crate::commands::{elapsed, ExitStatus};
|
use crate::commands::{elapsed, ExitStatus};
|
||||||
use crate::printer::Printer;
|
use crate::printer::Printer;
|
||||||
|
@ -49,7 +49,7 @@ pub(crate) async fn pip_uninstall(
|
||||||
let environment = PythonEnvironment::find(
|
let environment = PythonEnvironment::find(
|
||||||
&python
|
&python
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.map(ToolchainRequest::parse)
|
.map(PythonRequest::parse)
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
EnvironmentPreference::from_system_flag(system, true),
|
EnvironmentPreference::from_system_flag(system, true),
|
||||||
&cache,
|
&cache,
|
||||||
|
|
|
@ -10,9 +10,9 @@ use uv_distribution::pyproject_mut::PyProjectTomlMut;
|
||||||
use uv_distribution::{DistributionDatabase, ProjectWorkspace, VirtualProject, Workspace};
|
use uv_distribution::{DistributionDatabase, ProjectWorkspace, VirtualProject, Workspace};
|
||||||
use uv_git::GitResolver;
|
use uv_git::GitResolver;
|
||||||
use uv_normalize::PackageName;
|
use uv_normalize::PackageName;
|
||||||
|
use uv_python::{PythonFetch, PythonPreference, PythonRequest};
|
||||||
use uv_requirements::{NamedRequirementsResolver, RequirementsSource, RequirementsSpecification};
|
use uv_requirements::{NamedRequirementsResolver, RequirementsSource, RequirementsSpecification};
|
||||||
use uv_resolver::{FlatIndex, InMemoryIndex};
|
use uv_resolver::{FlatIndex, InMemoryIndex};
|
||||||
use uv_toolchain::{ToolchainFetch, ToolchainPreference, ToolchainRequest};
|
|
||||||
use uv_types::{BuildIsolation, HashStrategy, InFlight};
|
use uv_types::{BuildIsolation, HashStrategy, InFlight};
|
||||||
use uv_warnings::warn_user_once;
|
use uv_warnings::warn_user_once;
|
||||||
|
|
||||||
|
@ -38,8 +38,8 @@ pub(crate) async fn add(
|
||||||
package: Option<PackageName>,
|
package: Option<PackageName>,
|
||||||
python: Option<String>,
|
python: Option<String>,
|
||||||
settings: ResolverInstallerSettings,
|
settings: ResolverInstallerSettings,
|
||||||
toolchain_preference: ToolchainPreference,
|
python_preference: PythonPreference,
|
||||||
toolchain_fetch: ToolchainFetch,
|
python_fetch: PythonFetch,
|
||||||
preview: PreviewMode,
|
preview: PreviewMode,
|
||||||
connectivity: Connectivity,
|
connectivity: Connectivity,
|
||||||
concurrency: Concurrency,
|
concurrency: Concurrency,
|
||||||
|
@ -64,9 +64,9 @@ pub(crate) async fn add(
|
||||||
// Discover or create the virtual environment.
|
// Discover or create the virtual environment.
|
||||||
let venv = project::get_or_init_environment(
|
let venv = project::get_or_init_environment(
|
||||||
project.workspace(),
|
project.workspace(),
|
||||||
python.as_deref().map(ToolchainRequest::parse),
|
python.as_deref().map(PythonRequest::parse),
|
||||||
toolchain_preference,
|
python_preference,
|
||||||
toolchain_fetch,
|
python_fetch,
|
||||||
connectivity,
|
connectivity,
|
||||||
native_tls,
|
native_tls,
|
||||||
cache,
|
cache,
|
||||||
|
|
|
@ -7,9 +7,9 @@ use uv_configuration::{Concurrency, ExtrasSpecification, PreviewMode, Reinstall,
|
||||||
use uv_dispatch::BuildDispatch;
|
use uv_dispatch::BuildDispatch;
|
||||||
use uv_distribution::{Workspace, DEV_DEPENDENCIES};
|
use uv_distribution::{Workspace, DEV_DEPENDENCIES};
|
||||||
use uv_git::ResolvedRepositoryReference;
|
use uv_git::ResolvedRepositoryReference;
|
||||||
|
use uv_python::{Interpreter, PythonFetch, PythonPreference, PythonRequest};
|
||||||
use uv_requirements::upgrade::{read_lockfile, LockedRequirements};
|
use uv_requirements::upgrade::{read_lockfile, LockedRequirements};
|
||||||
use uv_resolver::{FlatIndex, Lock, OptionsBuilder, PythonRequirement, RequiresPython};
|
use uv_resolver::{FlatIndex, Lock, OptionsBuilder, PythonRequirement, RequiresPython};
|
||||||
use uv_toolchain::{Interpreter, ToolchainFetch, ToolchainPreference, ToolchainRequest};
|
|
||||||
use uv_types::{BuildIsolation, EmptyInstalledPackages, HashStrategy, InFlight};
|
use uv_types::{BuildIsolation, EmptyInstalledPackages, HashStrategy, InFlight};
|
||||||
use uv_warnings::{warn_user, warn_user_once};
|
use uv_warnings::{warn_user, warn_user_once};
|
||||||
|
|
||||||
|
@ -23,8 +23,8 @@ pub(crate) async fn lock(
|
||||||
python: Option<String>,
|
python: Option<String>,
|
||||||
settings: ResolverSettings,
|
settings: ResolverSettings,
|
||||||
preview: PreviewMode,
|
preview: PreviewMode,
|
||||||
toolchain_preference: ToolchainPreference,
|
python_preference: PythonPreference,
|
||||||
toolchain_fetch: ToolchainFetch,
|
python_fetch: PythonFetch,
|
||||||
connectivity: Connectivity,
|
connectivity: Connectivity,
|
||||||
concurrency: Concurrency,
|
concurrency: Concurrency,
|
||||||
native_tls: bool,
|
native_tls: bool,
|
||||||
|
@ -41,9 +41,9 @@ pub(crate) async fn lock(
|
||||||
// Find an interpreter for the project
|
// Find an interpreter for the project
|
||||||
let interpreter = FoundInterpreter::discover(
|
let interpreter = FoundInterpreter::discover(
|
||||||
&workspace,
|
&workspace,
|
||||||
python.as_deref().map(ToolchainRequest::parse),
|
python.as_deref().map(PythonRequest::parse),
|
||||||
toolchain_preference,
|
python_preference,
|
||||||
toolchain_fetch,
|
python_fetch,
|
||||||
connectivity,
|
connectivity,
|
||||||
native_tls,
|
native_tls,
|
||||||
cache,
|
cache,
|
||||||
|
|
|
@ -15,12 +15,12 @@ use uv_distribution::{DistributionDatabase, Workspace};
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
use uv_git::GitResolver;
|
use uv_git::GitResolver;
|
||||||
use uv_installer::{SatisfiesResult, SitePackages};
|
use uv_installer::{SatisfiesResult, SitePackages};
|
||||||
|
use uv_python::{
|
||||||
|
request_from_version_file, EnvironmentPreference, Interpreter, PythonEnvironment, PythonFetch,
|
||||||
|
PythonInstallation, PythonPreference, PythonRequest, VersionRequest,
|
||||||
|
};
|
||||||
use uv_requirements::{NamedRequirementsResolver, RequirementsSpecification};
|
use uv_requirements::{NamedRequirementsResolver, RequirementsSpecification};
|
||||||
use uv_resolver::{FlatIndex, InMemoryIndex, OptionsBuilder, PythonRequirement, RequiresPython};
|
use uv_resolver::{FlatIndex, InMemoryIndex, OptionsBuilder, PythonRequirement, RequiresPython};
|
||||||
use uv_toolchain::{
|
|
||||||
request_from_version_file, EnvironmentPreference, Interpreter, PythonEnvironment, Toolchain,
|
|
||||||
ToolchainFetch, ToolchainPreference, ToolchainRequest, VersionRequest,
|
|
||||||
};
|
|
||||||
use uv_types::{BuildIsolation, HashStrategy, InFlight};
|
use uv_types::{BuildIsolation, HashStrategy, InFlight};
|
||||||
|
|
||||||
use crate::commands::pip;
|
use crate::commands::pip;
|
||||||
|
@ -44,7 +44,7 @@ pub(crate) enum ProjectError {
|
||||||
RequestedPythonIncompatibility(Version, RequiresPython),
|
RequestedPythonIncompatibility(Version, RequiresPython),
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Toolchain(#[from] uv_toolchain::Error),
|
Python(#[from] uv_python::Error),
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Virtualenv(#[from] uv_virtualenv::Error),
|
Virtualenv(#[from] uv_virtualenv::Error),
|
||||||
|
@ -94,14 +94,14 @@ pub(crate) fn find_requires_python(
|
||||||
fn find_environment(
|
fn find_environment(
|
||||||
workspace: &Workspace,
|
workspace: &Workspace,
|
||||||
cache: &Cache,
|
cache: &Cache,
|
||||||
) -> Result<PythonEnvironment, uv_toolchain::Error> {
|
) -> Result<PythonEnvironment, uv_python::Error> {
|
||||||
PythonEnvironment::from_root(workspace.venv(), cache)
|
PythonEnvironment::from_root(workspace.venv(), cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if the given interpreter satisfies the project's requirements.
|
/// Check if the given interpreter satisfies the project's requirements.
|
||||||
fn interpreter_meets_requirements(
|
fn interpreter_meets_requirements(
|
||||||
interpreter: &Interpreter,
|
interpreter: &Interpreter,
|
||||||
requested_python: Option<&ToolchainRequest>,
|
requested_python: Option<&PythonRequest>,
|
||||||
cache: &Cache,
|
cache: &Cache,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let Some(request) = requested_python else {
|
let Some(request) = requested_python else {
|
||||||
|
@ -126,9 +126,9 @@ impl FoundInterpreter {
|
||||||
/// Discover the interpreter to use in the current [`Workspace`].
|
/// Discover the interpreter to use in the current [`Workspace`].
|
||||||
pub(crate) async fn discover(
|
pub(crate) async fn discover(
|
||||||
workspace: &Workspace,
|
workspace: &Workspace,
|
||||||
python_request: Option<ToolchainRequest>,
|
python_request: Option<PythonRequest>,
|
||||||
toolchain_preference: ToolchainPreference,
|
python_preference: PythonPreference,
|
||||||
toolchain_fetch: ToolchainFetch,
|
python_fetch: PythonFetch,
|
||||||
connectivity: Connectivity,
|
connectivity: Connectivity,
|
||||||
native_tls: bool,
|
native_tls: bool,
|
||||||
cache: &Cache,
|
cache: &Cache,
|
||||||
|
@ -147,9 +147,7 @@ impl FoundInterpreter {
|
||||||
requires_python
|
requires_python
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(RequiresPython::specifiers)
|
.map(RequiresPython::specifiers)
|
||||||
.map(|specifiers| {
|
.map(|specifiers| PythonRequest::Version(VersionRequest::Range(specifiers.clone())))
|
||||||
ToolchainRequest::Version(VersionRequest::Range(specifiers.clone()))
|
|
||||||
})
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Read from the virtual environment first.
|
// Read from the virtual environment first.
|
||||||
|
@ -172,7 +170,7 @@ impl FoundInterpreter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(uv_toolchain::Error::MissingEnvironment(_)) => {}
|
Err(uv_python::Error::MissingEnvironment(_)) => {}
|
||||||
Err(err) => return Err(err.into()),
|
Err(err) => return Err(err.into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -181,11 +179,11 @@ impl FoundInterpreter {
|
||||||
.native_tls(native_tls);
|
.native_tls(native_tls);
|
||||||
|
|
||||||
// Locate the Python interpreter to use in the environment
|
// Locate the Python interpreter to use in the environment
|
||||||
let interpreter = Toolchain::find_or_fetch(
|
let interpreter = PythonInstallation::find_or_fetch(
|
||||||
python_request,
|
python_request,
|
||||||
EnvironmentPreference::OnlySystem,
|
EnvironmentPreference::OnlySystem,
|
||||||
toolchain_preference,
|
python_preference,
|
||||||
toolchain_fetch,
|
python_fetch,
|
||||||
&client_builder,
|
&client_builder,
|
||||||
cache,
|
cache,
|
||||||
)
|
)
|
||||||
|
@ -223,9 +221,9 @@ impl FoundInterpreter {
|
||||||
/// Initialize a virtual environment for the current project.
|
/// Initialize a virtual environment for the current project.
|
||||||
pub(crate) async fn get_or_init_environment(
|
pub(crate) async fn get_or_init_environment(
|
||||||
workspace: &Workspace,
|
workspace: &Workspace,
|
||||||
python: Option<ToolchainRequest>,
|
python: Option<PythonRequest>,
|
||||||
toolchain_preference: ToolchainPreference,
|
python_preference: PythonPreference,
|
||||||
toolchain_fetch: ToolchainFetch,
|
python_fetch: PythonFetch,
|
||||||
connectivity: Connectivity,
|
connectivity: Connectivity,
|
||||||
native_tls: bool,
|
native_tls: bool,
|
||||||
cache: &Cache,
|
cache: &Cache,
|
||||||
|
@ -234,8 +232,8 @@ pub(crate) async fn get_or_init_environment(
|
||||||
match FoundInterpreter::discover(
|
match FoundInterpreter::discover(
|
||||||
workspace,
|
workspace,
|
||||||
python,
|
python,
|
||||||
toolchain_preference,
|
python_preference,
|
||||||
toolchain_fetch,
|
python_fetch,
|
||||||
connectivity,
|
connectivity,
|
||||||
native_tls,
|
native_tls,
|
||||||
cache,
|
cache,
|
||||||
|
|
|
@ -7,7 +7,7 @@ use uv_configuration::{Concurrency, ExtrasSpecification, PreviewMode};
|
||||||
use uv_distribution::pyproject::DependencyType;
|
use uv_distribution::pyproject::DependencyType;
|
||||||
use uv_distribution::pyproject_mut::PyProjectTomlMut;
|
use uv_distribution::pyproject_mut::PyProjectTomlMut;
|
||||||
use uv_distribution::{ProjectWorkspace, VirtualProject, Workspace};
|
use uv_distribution::{ProjectWorkspace, VirtualProject, Workspace};
|
||||||
use uv_toolchain::{ToolchainFetch, ToolchainPreference, ToolchainRequest};
|
use uv_python::{PythonFetch, PythonPreference, PythonRequest};
|
||||||
use uv_warnings::{warn_user, warn_user_once};
|
use uv_warnings::{warn_user, warn_user_once};
|
||||||
|
|
||||||
use crate::commands::pip::operations::Modifications;
|
use crate::commands::pip::operations::Modifications;
|
||||||
|
@ -22,8 +22,8 @@ pub(crate) async fn remove(
|
||||||
dependency_type: DependencyType,
|
dependency_type: DependencyType,
|
||||||
package: Option<PackageName>,
|
package: Option<PackageName>,
|
||||||
python: Option<String>,
|
python: Option<String>,
|
||||||
toolchain_preference: ToolchainPreference,
|
python_preference: PythonPreference,
|
||||||
toolchain_fetch: ToolchainFetch,
|
python_fetch: PythonFetch,
|
||||||
preview: PreviewMode,
|
preview: PreviewMode,
|
||||||
connectivity: Connectivity,
|
connectivity: Connectivity,
|
||||||
concurrency: Concurrency,
|
concurrency: Concurrency,
|
||||||
|
@ -85,9 +85,9 @@ pub(crate) async fn remove(
|
||||||
// Discover or create the virtual environment.
|
// Discover or create the virtual environment.
|
||||||
let venv = project::get_or_init_environment(
|
let venv = project::get_or_init_environment(
|
||||||
project.workspace(),
|
project.workspace(),
|
||||||
python.as_deref().map(ToolchainRequest::parse),
|
python.as_deref().map(PythonRequest::parse),
|
||||||
toolchain_preference,
|
python_preference,
|
||||||
toolchain_fetch,
|
python_fetch,
|
||||||
connectivity,
|
connectivity,
|
||||||
native_tls,
|
native_tls,
|
||||||
cache,
|
cache,
|
||||||
|
|
|
@ -13,11 +13,11 @@ use uv_client::{BaseClientBuilder, Connectivity};
|
||||||
use uv_configuration::{Concurrency, ExtrasSpecification, PreviewMode};
|
use uv_configuration::{Concurrency, ExtrasSpecification, PreviewMode};
|
||||||
use uv_distribution::{VirtualProject, Workspace, WorkspaceError};
|
use uv_distribution::{VirtualProject, Workspace, WorkspaceError};
|
||||||
use uv_normalize::PackageName;
|
use uv_normalize::PackageName;
|
||||||
use uv_requirements::{RequirementsSource, RequirementsSpecification};
|
use uv_python::{
|
||||||
use uv_toolchain::{
|
request_from_version_file, EnvironmentPreference, Interpreter, PythonEnvironment, PythonFetch,
|
||||||
request_from_version_file, EnvironmentPreference, Interpreter, PythonEnvironment, Toolchain,
|
PythonInstallation, PythonPreference, PythonRequest, VersionRequest,
|
||||||
ToolchainFetch, ToolchainPreference, ToolchainRequest, VersionRequest,
|
|
||||||
};
|
};
|
||||||
|
use uv_requirements::{RequirementsSource, RequirementsSpecification};
|
||||||
use uv_warnings::warn_user_once;
|
use uv_warnings::warn_user_once;
|
||||||
|
|
||||||
use crate::commands::pip::operations::Modifications;
|
use crate::commands::pip::operations::Modifications;
|
||||||
|
@ -37,8 +37,8 @@ pub(crate) async fn run(
|
||||||
settings: ResolverInstallerSettings,
|
settings: ResolverInstallerSettings,
|
||||||
isolated: bool,
|
isolated: bool,
|
||||||
preview: PreviewMode,
|
preview: PreviewMode,
|
||||||
toolchain_preference: ToolchainPreference,
|
python_preference: PythonPreference,
|
||||||
toolchain_fetch: ToolchainFetch,
|
python_fetch: PythonFetch,
|
||||||
connectivity: Connectivity,
|
connectivity: Connectivity,
|
||||||
concurrency: Concurrency,
|
concurrency: Concurrency,
|
||||||
native_tls: bool,
|
native_tls: bool,
|
||||||
|
@ -71,14 +71,14 @@ pub(crate) async fn run(
|
||||||
|
|
||||||
// (1) Explicit request from user
|
// (1) Explicit request from user
|
||||||
let python_request = if let Some(request) = python.as_deref() {
|
let python_request = if let Some(request) = python.as_deref() {
|
||||||
Some(ToolchainRequest::parse(request))
|
Some(PythonRequest::parse(request))
|
||||||
// (2) Request from `.python-version`
|
// (2) Request from `.python-version`
|
||||||
} else if let Some(request) = request_from_version_file().await? {
|
} else if let Some(request) = request_from_version_file().await? {
|
||||||
Some(request)
|
Some(request)
|
||||||
// (3) `Requires-Python` in `pyproject.toml`
|
// (3) `Requires-Python` in `pyproject.toml`
|
||||||
} else {
|
} else {
|
||||||
metadata.requires_python.map(|requires_python| {
|
metadata.requires_python.map(|requires_python| {
|
||||||
ToolchainRequest::Version(VersionRequest::Range(requires_python))
|
PythonRequest::Version(VersionRequest::Range(requires_python))
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -86,11 +86,11 @@ pub(crate) async fn run(
|
||||||
.connectivity(connectivity)
|
.connectivity(connectivity)
|
||||||
.native_tls(native_tls);
|
.native_tls(native_tls);
|
||||||
|
|
||||||
let interpreter = Toolchain::find_or_fetch(
|
let interpreter = PythonInstallation::find_or_fetch(
|
||||||
python_request,
|
python_request,
|
||||||
EnvironmentPreference::Any,
|
EnvironmentPreference::Any,
|
||||||
toolchain_preference,
|
python_preference,
|
||||||
toolchain_fetch,
|
python_fetch,
|
||||||
&client_builder,
|
&client_builder,
|
||||||
cache,
|
cache,
|
||||||
)
|
)
|
||||||
|
@ -171,9 +171,9 @@ pub(crate) async fn run(
|
||||||
|
|
||||||
let venv = project::get_or_init_environment(
|
let venv = project::get_or_init_environment(
|
||||||
project.workspace(),
|
project.workspace(),
|
||||||
python.as_deref().map(ToolchainRequest::parse),
|
python.as_deref().map(PythonRequest::parse),
|
||||||
toolchain_preference,
|
python_preference,
|
||||||
toolchain_fetch,
|
python_fetch,
|
||||||
connectivity,
|
connectivity,
|
||||||
native_tls,
|
native_tls,
|
||||||
cache,
|
cache,
|
||||||
|
@ -221,18 +221,18 @@ pub(crate) async fn run(
|
||||||
.connectivity(connectivity)
|
.connectivity(connectivity)
|
||||||
.native_tls(native_tls);
|
.native_tls(native_tls);
|
||||||
|
|
||||||
let toolchain = Toolchain::find_or_fetch(
|
let python = PythonInstallation::find_or_fetch(
|
||||||
python.as_deref().map(ToolchainRequest::parse),
|
python.as_deref().map(PythonRequest::parse),
|
||||||
// No opt-in is required for system environments, since we are not mutating it.
|
// No opt-in is required for system environments, since we are not mutating it.
|
||||||
EnvironmentPreference::Any,
|
EnvironmentPreference::Any,
|
||||||
toolchain_preference,
|
python_preference,
|
||||||
toolchain_fetch,
|
python_fetch,
|
||||||
&client_builder,
|
&client_builder,
|
||||||
cache,
|
cache,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
toolchain.into_interpreter()
|
python.into_interpreter()
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(interpreter)
|
Some(interpreter)
|
||||||
|
@ -262,11 +262,11 @@ pub(crate) async fn run(
|
||||||
.native_tls(native_tls);
|
.native_tls(native_tls);
|
||||||
|
|
||||||
// Note we force preview on during `uv run` for now since the entire interface is in preview
|
// Note we force preview on during `uv run` for now since the entire interface is in preview
|
||||||
Toolchain::find_or_fetch(
|
PythonInstallation::find_or_fetch(
|
||||||
python.as_deref().map(ToolchainRequest::parse),
|
python.as_deref().map(PythonRequest::parse),
|
||||||
EnvironmentPreference::Any,
|
EnvironmentPreference::Any,
|
||||||
toolchain_preference,
|
python_preference,
|
||||||
toolchain_fetch,
|
python_fetch,
|
||||||
&client_builder,
|
&client_builder,
|
||||||
cache,
|
cache,
|
||||||
)
|
)
|
||||||
|
|
|
@ -6,8 +6,8 @@ use uv_configuration::{Concurrency, ExtrasSpecification, PreviewMode, SetupPyStr
|
||||||
use uv_dispatch::BuildDispatch;
|
use uv_dispatch::BuildDispatch;
|
||||||
use uv_distribution::{VirtualProject, DEV_DEPENDENCIES};
|
use uv_distribution::{VirtualProject, DEV_DEPENDENCIES};
|
||||||
use uv_installer::SitePackages;
|
use uv_installer::SitePackages;
|
||||||
|
use uv_python::{PythonEnvironment, PythonFetch, PythonPreference, PythonRequest};
|
||||||
use uv_resolver::{FlatIndex, Lock};
|
use uv_resolver::{FlatIndex, Lock};
|
||||||
use uv_toolchain::{PythonEnvironment, ToolchainFetch, ToolchainPreference, ToolchainRequest};
|
|
||||||
use uv_types::{BuildIsolation, HashStrategy, InFlight};
|
use uv_types::{BuildIsolation, HashStrategy, InFlight};
|
||||||
use uv_warnings::warn_user_once;
|
use uv_warnings::warn_user_once;
|
||||||
|
|
||||||
|
@ -23,8 +23,8 @@ pub(crate) async fn sync(
|
||||||
dev: bool,
|
dev: bool,
|
||||||
modifications: Modifications,
|
modifications: Modifications,
|
||||||
python: Option<String>,
|
python: Option<String>,
|
||||||
toolchain_preference: ToolchainPreference,
|
python_preference: PythonPreference,
|
||||||
toolchain_fetch: ToolchainFetch,
|
python_fetch: PythonFetch,
|
||||||
settings: InstallerSettings,
|
settings: InstallerSettings,
|
||||||
preview: PreviewMode,
|
preview: PreviewMode,
|
||||||
connectivity: Connectivity,
|
connectivity: Connectivity,
|
||||||
|
@ -43,9 +43,9 @@ pub(crate) async fn sync(
|
||||||
// Discover or create the virtual environment.
|
// Discover or create the virtual environment.
|
||||||
let venv = project::get_or_init_environment(
|
let venv = project::get_or_init_environment(
|
||||||
project.workspace(),
|
project.workspace(),
|
||||||
python.as_deref().map(ToolchainRequest::parse),
|
python.as_deref().map(PythonRequest::parse),
|
||||||
toolchain_preference,
|
python_preference,
|
||||||
toolchain_fetch,
|
python_fetch,
|
||||||
connectivity,
|
connectivity,
|
||||||
native_tls,
|
native_tls,
|
||||||
cache,
|
cache,
|
||||||
|
|
|
@ -2,16 +2,16 @@ use anyhow::Context;
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::OwoColorize;
|
||||||
use uv_configuration::PreviewMode;
|
use uv_configuration::PreviewMode;
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
use uv_toolchain::managed::InstalledToolchains;
|
use uv_python::managed::ManagedPythonInstallations;
|
||||||
use uv_warnings::warn_user_once;
|
use uv_warnings::warn_user_once;
|
||||||
|
|
||||||
/// Show the toolchain directory.
|
/// Show the toolchain directory.
|
||||||
pub(crate) fn dir(preview: PreviewMode) -> anyhow::Result<()> {
|
pub(crate) fn dir(preview: PreviewMode) -> anyhow::Result<()> {
|
||||||
if preview.is_disabled() {
|
if preview.is_disabled() {
|
||||||
warn_user_once!("`uv toolchain dir` is experimental and may change without warning.");
|
warn_user_once!("`uv python dir` is experimental and may change without warning.");
|
||||||
}
|
}
|
||||||
let installed_toolchains =
|
let installed_toolchains = ManagedPythonInstallations::from_settings()
|
||||||
InstalledToolchains::from_settings().context("Failed to initialize toolchain settings")?;
|
.context("Failed to initialize toolchain settings")?;
|
||||||
anstream::println!(
|
anstream::println!(
|
||||||
"{}",
|
"{}",
|
||||||
installed_toolchains.root().simplified_display().cyan()
|
installed_toolchains.root().simplified_display().cyan()
|
|
@ -4,39 +4,39 @@ use std::fmt::Write;
|
||||||
use uv_cache::Cache;
|
use uv_cache::Cache;
|
||||||
use uv_configuration::PreviewMode;
|
use uv_configuration::PreviewMode;
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
use uv_toolchain::{EnvironmentPreference, Toolchain, ToolchainPreference, ToolchainRequest};
|
use uv_python::{EnvironmentPreference, PythonInstallation, PythonPreference, PythonRequest};
|
||||||
use uv_warnings::warn_user_once;
|
use uv_warnings::warn_user_once;
|
||||||
|
|
||||||
use crate::commands::ExitStatus;
|
use crate::commands::ExitStatus;
|
||||||
use crate::printer::Printer;
|
use crate::printer::Printer;
|
||||||
|
|
||||||
/// Find a toolchain.
|
/// Find a Python interpreter.
|
||||||
pub(crate) async fn find(
|
pub(crate) async fn find(
|
||||||
request: Option<String>,
|
request: Option<String>,
|
||||||
toolchain_preference: ToolchainPreference,
|
python_preference: PythonPreference,
|
||||||
preview: PreviewMode,
|
preview: PreviewMode,
|
||||||
cache: &Cache,
|
cache: &Cache,
|
||||||
printer: Printer,
|
printer: Printer,
|
||||||
) -> Result<ExitStatus> {
|
) -> Result<ExitStatus> {
|
||||||
if preview.is_disabled() {
|
if preview.is_disabled() {
|
||||||
warn_user_once!("`uv toolchain find` is experimental and may change without warning.");
|
warn_user_once!("`uv python find` is experimental and may change without warning.");
|
||||||
}
|
}
|
||||||
|
|
||||||
let request = match request {
|
let request = match request {
|
||||||
Some(request) => ToolchainRequest::parse(&request),
|
Some(request) => PythonRequest::parse(&request),
|
||||||
None => ToolchainRequest::Any,
|
None => PythonRequest::Any,
|
||||||
};
|
};
|
||||||
let toolchain = Toolchain::find(
|
let python = PythonInstallation::find(
|
||||||
&request,
|
&request,
|
||||||
EnvironmentPreference::OnlySystem,
|
EnvironmentPreference::OnlySystem,
|
||||||
toolchain_preference,
|
python_preference,
|
||||||
cache,
|
cache,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
writeln!(
|
writeln!(
|
||||||
printer.stdout(),
|
printer.stdout(),
|
||||||
"{}",
|
"{}",
|
||||||
toolchain.interpreter().sys_executable().user_display()
|
python.interpreter().sys_executable().user_display()
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(ExitStatus::Success)
|
Ok(ExitStatus::Success)
|
|
@ -5,15 +5,15 @@ use uv_cache::Cache;
|
||||||
use uv_client::Connectivity;
|
use uv_client::Connectivity;
|
||||||
use uv_configuration::PreviewMode;
|
use uv_configuration::PreviewMode;
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
use uv_toolchain::downloads::{self, DownloadResult, PythonDownload, PythonDownloadRequest};
|
use uv_python::downloads::{self, DownloadResult, ManagedPythonDownload, PythonDownloadRequest};
|
||||||
use uv_toolchain::managed::{InstalledToolchain, InstalledToolchains};
|
use uv_python::managed::{ManagedPythonInstallation, ManagedPythonInstallations};
|
||||||
use uv_toolchain::{requests_from_version_file, ToolchainRequest};
|
use uv_python::{requests_from_version_file, PythonRequest};
|
||||||
use uv_warnings::warn_user_once;
|
use uv_warnings::warn_user_once;
|
||||||
|
|
||||||
use crate::commands::ExitStatus;
|
use crate::commands::ExitStatus;
|
||||||
use crate::printer::Printer;
|
use crate::printer::Printer;
|
||||||
|
|
||||||
/// Download and install a Python toolchain.
|
/// Download and install Python versions.
|
||||||
pub(crate) async fn install(
|
pub(crate) async fn install(
|
||||||
targets: Vec<String>,
|
targets: Vec<String>,
|
||||||
force: bool,
|
force: bool,
|
||||||
|
@ -24,25 +24,25 @@ pub(crate) async fn install(
|
||||||
printer: Printer,
|
printer: Printer,
|
||||||
) -> Result<ExitStatus> {
|
) -> Result<ExitStatus> {
|
||||||
if preview.is_disabled() {
|
if preview.is_disabled() {
|
||||||
warn_user_once!("`uv toolchain install` is experimental and may change without warning.");
|
warn_user_once!("`uv python install` is experimental and may change without warning.");
|
||||||
}
|
}
|
||||||
|
|
||||||
let start = std::time::Instant::now();
|
let start = std::time::Instant::now();
|
||||||
|
|
||||||
let toolchains = InstalledToolchains::from_settings()?.init()?;
|
let installations = ManagedPythonInstallations::from_settings()?.init()?;
|
||||||
let toolchain_dir = toolchains.root();
|
let installations_dir = installations.root();
|
||||||
let _lock = toolchains.acquire_lock()?;
|
let _lock = installations.acquire_lock()?;
|
||||||
|
|
||||||
let requests: Vec<_> = if targets.is_empty() {
|
let requests: Vec<_> = if targets.is_empty() {
|
||||||
if let Some(requests) = requests_from_version_file().await? {
|
if let Some(requests) = requests_from_version_file().await? {
|
||||||
requests
|
requests
|
||||||
} else {
|
} else {
|
||||||
vec![ToolchainRequest::Any]
|
vec![PythonRequest::Any]
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
targets
|
targets
|
||||||
.iter()
|
.iter()
|
||||||
.map(|target| ToolchainRequest::parse(target.as_str()))
|
.map(|target| PythonRequest::parse(target.as_str()))
|
||||||
.collect()
|
.collect()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -51,21 +51,21 @@ pub(crate) async fn install(
|
||||||
.map(PythonDownloadRequest::from_request)
|
.map(PythonDownloadRequest::from_request)
|
||||||
.collect::<Result<Vec<_>, downloads::Error>>()?;
|
.collect::<Result<Vec<_>, downloads::Error>>()?;
|
||||||
|
|
||||||
let installed_toolchains: Vec<_> = toolchains.find_all()?.collect();
|
let installed_installations: Vec<_> = installations.find_all()?.collect();
|
||||||
let mut unfilled_requests = Vec::new();
|
let mut unfilled_requests = Vec::new();
|
||||||
for (request, download_request) in requests.iter().zip(download_requests) {
|
for (request, download_request) in requests.iter().zip(download_requests) {
|
||||||
writeln!(
|
writeln!(
|
||||||
printer.stderr(),
|
printer.stderr(),
|
||||||
"Looking for toolchain {request} ({download_request})"
|
"Looking for installation {request} ({download_request})"
|
||||||
)?;
|
)?;
|
||||||
if let Some(toolchain) = installed_toolchains
|
if let Some(installation) = installed_installations
|
||||||
.iter()
|
.iter()
|
||||||
.find(|toolchain| download_request.satisfied_by_key(toolchain.key()))
|
.find(|installation| download_request.satisfied_by_key(installation.key()))
|
||||||
{
|
{
|
||||||
writeln!(
|
writeln!(
|
||||||
printer.stderr(),
|
printer.stderr(),
|
||||||
"Found installed toolchain `{}` that satisfies {request}",
|
"Found installed installation `{}` that satisfies {request}",
|
||||||
toolchain.key()
|
installation.key()
|
||||||
)?;
|
)?;
|
||||||
if force {
|
if force {
|
||||||
unfilled_requests.push(download_request);
|
unfilled_requests.push(download_request);
|
||||||
|
@ -76,18 +76,21 @@ pub(crate) async fn install(
|
||||||
}
|
}
|
||||||
|
|
||||||
if unfilled_requests.is_empty() {
|
if unfilled_requests.is_empty() {
|
||||||
if matches!(requests.as_slice(), [ToolchainRequest::Any]) {
|
if matches!(requests.as_slice(), [PythonRequest::Any]) {
|
||||||
writeln!(
|
writeln!(
|
||||||
printer.stderr(),
|
printer.stderr(),
|
||||||
"A toolchain is already installed. Use `uv toolchain install <request>` to install a specific toolchain.",
|
"A installation is already installed. Use `uv installation install <request>` to install a specific installation.",
|
||||||
)?;
|
)?;
|
||||||
} else if requests.len() > 1 {
|
} else if requests.len() > 1 {
|
||||||
writeln!(
|
writeln!(
|
||||||
printer.stderr(),
|
printer.stderr(),
|
||||||
"All requested toolchains already installed."
|
"All requested installations already installed."
|
||||||
)?;
|
)?;
|
||||||
} else {
|
} else {
|
||||||
writeln!(printer.stderr(), "Requested toolchain already installed.")?;
|
writeln!(
|
||||||
|
printer.stderr(),
|
||||||
|
"Requested installation already installed."
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
return Ok(ExitStatus::Success);
|
return Ok(ExitStatus::Success);
|
||||||
}
|
}
|
||||||
|
@ -95,7 +98,7 @@ pub(crate) async fn install(
|
||||||
if unfilled_requests.len() > 1 {
|
if unfilled_requests.len() > 1 {
|
||||||
writeln!(
|
writeln!(
|
||||||
printer.stderr(),
|
printer.stderr(),
|
||||||
"Found {}/{} toolchains requiring installation",
|
"Found {}/{} installations requiring installation",
|
||||||
unfilled_requests.len(),
|
unfilled_requests.len(),
|
||||||
requests.len()
|
requests.len()
|
||||||
)?;
|
)?;
|
||||||
|
@ -105,8 +108,8 @@ pub(crate) async fn install(
|
||||||
.into_iter()
|
.into_iter()
|
||||||
// Populate the download requests with defaults
|
// Populate the download requests with defaults
|
||||||
.map(PythonDownloadRequest::fill)
|
.map(PythonDownloadRequest::fill)
|
||||||
.map(|request| PythonDownload::from_request(&request))
|
.map(|request| ManagedPythonDownload::from_request(&request))
|
||||||
.collect::<Result<Vec<_>, uv_toolchain::downloads::Error>>()?;
|
.collect::<Result<Vec<_>, uv_python::downloads::Error>>()?;
|
||||||
|
|
||||||
// Construct a client
|
// Construct a client
|
||||||
let client = uv_client::BaseClientBuilder::new()
|
let client = uv_client::BaseClientBuilder::new()
|
||||||
|
@ -117,7 +120,7 @@ pub(crate) async fn install(
|
||||||
let mut tasks = futures::stream::iter(downloads.iter())
|
let mut tasks = futures::stream::iter(downloads.iter())
|
||||||
.map(|download| async {
|
.map(|download| async {
|
||||||
let _ = writeln!(printer.stderr(), "Downloading {}", download.key());
|
let _ = writeln!(printer.stderr(), "Downloading {}", download.key());
|
||||||
let result = download.fetch(&client, toolchain_dir).await;
|
let result = download.fetch(&client, installations_dir).await;
|
||||||
(download.python_version(), result)
|
(download.python_version(), result)
|
||||||
})
|
})
|
||||||
.buffered(4);
|
.buffered(4);
|
||||||
|
@ -138,7 +141,7 @@ pub(crate) async fn install(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// Ensure the installations have externally managed markers
|
// Ensure the installations have externally managed markers
|
||||||
let installed = InstalledToolchain::new(path.clone())?;
|
let installed = ManagedPythonInstallation::new(path.clone())?;
|
||||||
installed.ensure_externally_managed()?;
|
installed.ensure_externally_managed()?;
|
||||||
results.push((version, path));
|
results.push((version, path));
|
||||||
}
|
}
|
||||||
|
@ -146,7 +149,7 @@ pub(crate) async fn install(
|
||||||
let s = if downloads.len() == 1 { "" } else { "s" };
|
let s = if downloads.len() == 1 { "" } else { "s" };
|
||||||
writeln!(
|
writeln!(
|
||||||
printer.stderr(),
|
printer.stderr(),
|
||||||
"Installed {} toolchain{s} in {}s",
|
"Installed {} installation{s} in {}s",
|
||||||
downloads.len(),
|
downloads.len(),
|
||||||
start.elapsed().as_secs()
|
start.elapsed().as_secs()
|
||||||
)?;
|
)?;
|
|
@ -6,16 +6,16 @@ use anyhow::Result;
|
||||||
use uv_cache::Cache;
|
use uv_cache::Cache;
|
||||||
use uv_configuration::PreviewMode;
|
use uv_configuration::PreviewMode;
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
use uv_toolchain::downloads::PythonDownloadRequest;
|
use uv_python::downloads::PythonDownloadRequest;
|
||||||
use uv_toolchain::{
|
use uv_python::{
|
||||||
find_toolchains, DiscoveryError, EnvironmentPreference, Toolchain, ToolchainFetch,
|
find_python_installations, DiscoveryError, EnvironmentPreference, PythonFetch,
|
||||||
ToolchainNotFound, ToolchainPreference, ToolchainRequest, ToolchainSource,
|
PythonInstallation, PythonNotFound, PythonPreference, PythonRequest, PythonSource,
|
||||||
};
|
};
|
||||||
use uv_warnings::warn_user_once;
|
use uv_warnings::warn_user_once;
|
||||||
|
|
||||||
use crate::commands::ExitStatus;
|
use crate::commands::ExitStatus;
|
||||||
use crate::printer::Printer;
|
use crate::printer::Printer;
|
||||||
use crate::settings::ToolchainListKinds;
|
use crate::settings::PythonListKinds;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
enum Kind {
|
enum Kind {
|
||||||
|
@ -24,26 +24,26 @@ enum Kind {
|
||||||
System,
|
System,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// List available toolchains.
|
/// List available Python installations.
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub(crate) async fn list(
|
pub(crate) async fn list(
|
||||||
kinds: ToolchainListKinds,
|
kinds: PythonListKinds,
|
||||||
all_versions: bool,
|
all_versions: bool,
|
||||||
all_platforms: bool,
|
all_platforms: bool,
|
||||||
toolchain_preference: ToolchainPreference,
|
python_preference: PythonPreference,
|
||||||
toolchain_fetch: ToolchainFetch,
|
python_fetch: PythonFetch,
|
||||||
preview: PreviewMode,
|
preview: PreviewMode,
|
||||||
cache: &Cache,
|
cache: &Cache,
|
||||||
printer: Printer,
|
printer: Printer,
|
||||||
) -> Result<ExitStatus> {
|
) -> Result<ExitStatus> {
|
||||||
if preview.is_disabled() {
|
if preview.is_disabled() {
|
||||||
warn_user_once!("`uv toolchain list` is experimental and may change without warning.");
|
warn_user_once!("`uv python list` is experimental and may change without warning.");
|
||||||
}
|
}
|
||||||
|
|
||||||
let download_request = match kinds {
|
let download_request = match kinds {
|
||||||
ToolchainListKinds::Installed => None,
|
PythonListKinds::Installed => None,
|
||||||
ToolchainListKinds::Default => {
|
PythonListKinds::Default => {
|
||||||
if toolchain_fetch.is_automatic() {
|
if python_fetch.is_automatic() {
|
||||||
Some(if all_platforms {
|
Some(if all_platforms {
|
||||||
PythonDownloadRequest::default()
|
PythonDownloadRequest::default()
|
||||||
} else {
|
} else {
|
||||||
|
@ -58,14 +58,14 @@ pub(crate) async fn list(
|
||||||
|
|
||||||
let downloads = download_request
|
let downloads = download_request
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(uv_toolchain::downloads::PythonDownloadRequest::iter_downloads)
|
.map(uv_python::downloads::PythonDownloadRequest::iter_downloads)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten();
|
.flatten();
|
||||||
|
|
||||||
let installed = find_toolchains(
|
let installed = find_python_installations(
|
||||||
&ToolchainRequest::Any,
|
&PythonRequest::Any,
|
||||||
EnvironmentPreference::OnlySystem,
|
EnvironmentPreference::OnlySystem,
|
||||||
toolchain_preference,
|
python_preference,
|
||||||
cache,
|
cache,
|
||||||
)
|
)
|
||||||
// Raise discovery errors if critical
|
// Raise discovery errors if critical
|
||||||
|
@ -75,24 +75,24 @@ pub(crate) async fn list(
|
||||||
.err()
|
.err()
|
||||||
.map_or(true, DiscoveryError::is_critical)
|
.map_or(true, DiscoveryError::is_critical)
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<Result<Toolchain, ToolchainNotFound>>, DiscoveryError>>()?
|
.collect::<Result<Vec<Result<PythonInstallation, PythonNotFound>>, DiscoveryError>>()?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
// Drop any "missing" toolchains
|
// Drop any "missing" installations
|
||||||
.filter_map(std::result::Result::ok);
|
.filter_map(std::result::Result::ok);
|
||||||
|
|
||||||
let mut output = BTreeSet::new();
|
let mut output = BTreeSet::new();
|
||||||
for toolchain in installed {
|
for installation in installed {
|
||||||
let kind = if matches!(toolchain.source(), ToolchainSource::Managed) {
|
let kind = if matches!(installation.source(), PythonSource::Managed) {
|
||||||
Kind::Managed
|
Kind::Managed
|
||||||
} else {
|
} else {
|
||||||
Kind::System
|
Kind::System
|
||||||
};
|
};
|
||||||
output.insert((
|
output.insert((
|
||||||
toolchain.python_version().clone(),
|
installation.python_version().clone(),
|
||||||
toolchain.os().to_string(),
|
installation.os().to_string(),
|
||||||
toolchain.key().clone(),
|
installation.key().clone(),
|
||||||
kind,
|
kind,
|
||||||
Some(toolchain.interpreter().sys_executable().to_path_buf()),
|
Some(installation.interpreter().sys_executable().to_path_buf()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
for download in downloads {
|
for download in downloads {
|
124
crates/uv/src/commands/python/uninstall.rs
Normal file
124
crates/uv/src/commands/python/uninstall.rs
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
use futures::StreamExt;
|
||||||
|
use itertools::Itertools;
|
||||||
|
use std::collections::BTreeSet;
|
||||||
|
use std::fmt::Write;
|
||||||
|
use uv_configuration::PreviewMode;
|
||||||
|
use uv_python::downloads::{self, PythonDownloadRequest};
|
||||||
|
use uv_python::managed::ManagedPythonInstallations;
|
||||||
|
use uv_python::PythonRequest;
|
||||||
|
use uv_warnings::warn_user_once;
|
||||||
|
|
||||||
|
use crate::commands::ExitStatus;
|
||||||
|
use crate::printer::Printer;
|
||||||
|
|
||||||
|
/// Uninstall managed Python versions.
|
||||||
|
pub(crate) async fn uninstall(
|
||||||
|
targets: Vec<String>,
|
||||||
|
preview: PreviewMode,
|
||||||
|
printer: Printer,
|
||||||
|
) -> Result<ExitStatus> {
|
||||||
|
if preview.is_disabled() {
|
||||||
|
warn_user_once!("`uv python uninstall` is experimental and may change without warning.");
|
||||||
|
}
|
||||||
|
|
||||||
|
let installations = ManagedPythonInstallations::from_settings()?.init()?;
|
||||||
|
let _lock = installations.acquire_lock()?;
|
||||||
|
|
||||||
|
let requests = targets
|
||||||
|
.iter()
|
||||||
|
.map(|target| PythonRequest::parse(target.as_str()))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let download_requests = requests
|
||||||
|
.iter()
|
||||||
|
.map(PythonDownloadRequest::from_request)
|
||||||
|
.collect::<Result<Vec<_>, downloads::Error>>()?;
|
||||||
|
|
||||||
|
let installed_installations: Vec<_> = installations.find_all()?.collect();
|
||||||
|
let mut matching_installations = BTreeSet::default();
|
||||||
|
for (request, download_request) in requests.iter().zip(download_requests) {
|
||||||
|
writeln!(
|
||||||
|
printer.stderr(),
|
||||||
|
"Looking for Python installations matching {request} ({download_request})"
|
||||||
|
)?;
|
||||||
|
let mut found = false;
|
||||||
|
for installation in installed_installations
|
||||||
|
.iter()
|
||||||
|
.filter(|installation| download_request.satisfied_by_key(installation.key()))
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
if matching_installations.insert(installation.clone()) {
|
||||||
|
writeln!(
|
||||||
|
printer.stderr(),
|
||||||
|
"Found installation `{}` that matches {request}",
|
||||||
|
installation.key()
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
writeln!(
|
||||||
|
printer.stderr(),
|
||||||
|
"No installations found matching {request}"
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if matching_installations.is_empty() {
|
||||||
|
if matches!(requests.as_slice(), [PythonRequest::Any]) {
|
||||||
|
writeln!(printer.stderr(), "No installed installations found")?;
|
||||||
|
} else if requests.len() > 1 {
|
||||||
|
writeln!(
|
||||||
|
printer.stderr(),
|
||||||
|
"No installations found matching the requests"
|
||||||
|
)?;
|
||||||
|
} else {
|
||||||
|
writeln!(
|
||||||
|
printer.stderr(),
|
||||||
|
"No installations found matching the request"
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
return Ok(ExitStatus::Failure);
|
||||||
|
}
|
||||||
|
|
||||||
|
let tasks = futures::stream::iter(matching_installations.iter())
|
||||||
|
.map(|installation| async {
|
||||||
|
(
|
||||||
|
installation.key(),
|
||||||
|
fs_err::tokio::remove_dir_all(installation.path()).await,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.buffered(4);
|
||||||
|
|
||||||
|
let results = tasks.collect::<Vec<_>>().await;
|
||||||
|
let mut failed = false;
|
||||||
|
for (key, result) in results.iter().sorted_by_key(|(key, _)| key) {
|
||||||
|
if let Err(err) = result {
|
||||||
|
failed = true;
|
||||||
|
writeln!(printer.stderr(), "Failed to uninstall `{key}`: {err}")?;
|
||||||
|
} else {
|
||||||
|
writeln!(printer.stderr(), "Uninstalled `{key}`")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if failed {
|
||||||
|
if matching_installations.len() > 1 {
|
||||||
|
writeln!(printer.stderr(), "Some Python uninstalls failed")?;
|
||||||
|
}
|
||||||
|
return Ok(ExitStatus::Failure);
|
||||||
|
}
|
||||||
|
|
||||||
|
let s = if matching_installations.len() == 1 {
|
||||||
|
""
|
||||||
|
} else {
|
||||||
|
"s"
|
||||||
|
};
|
||||||
|
|
||||||
|
writeln!(
|
||||||
|
printer.stderr(),
|
||||||
|
"Removed {} Python installation{s}",
|
||||||
|
matching_installations.len()
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(ExitStatus::Success)
|
||||||
|
}
|
|
@ -17,12 +17,12 @@ use uv_fs::replace_symlink;
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
use uv_installer::SitePackages;
|
use uv_installer::SitePackages;
|
||||||
use uv_normalize::PackageName;
|
use uv_normalize::PackageName;
|
||||||
|
use uv_python::{
|
||||||
|
EnvironmentPreference, Interpreter, PythonFetch, PythonInstallation, PythonPreference,
|
||||||
|
PythonRequest,
|
||||||
|
};
|
||||||
use uv_requirements::RequirementsSpecification;
|
use uv_requirements::RequirementsSpecification;
|
||||||
use uv_tool::{entrypoint_paths, find_executable_directory, InstalledTools, Tool, ToolEntrypoint};
|
use uv_tool::{entrypoint_paths, find_executable_directory, InstalledTools, Tool, ToolEntrypoint};
|
||||||
use uv_toolchain::{
|
|
||||||
EnvironmentPreference, Interpreter, Toolchain, ToolchainFetch, ToolchainPreference,
|
|
||||||
ToolchainRequest,
|
|
||||||
};
|
|
||||||
use uv_warnings::warn_user_once;
|
use uv_warnings::warn_user_once;
|
||||||
|
|
||||||
use crate::commands::pip::operations::Modifications;
|
use crate::commands::pip::operations::Modifications;
|
||||||
|
@ -40,8 +40,8 @@ pub(crate) async fn install(
|
||||||
force: bool,
|
force: bool,
|
||||||
settings: ResolverInstallerSettings,
|
settings: ResolverInstallerSettings,
|
||||||
preview: PreviewMode,
|
preview: PreviewMode,
|
||||||
toolchain_preference: ToolchainPreference,
|
python_preference: PythonPreference,
|
||||||
toolchain_fetch: ToolchainFetch,
|
python_fetch: PythonFetch,
|
||||||
connectivity: Connectivity,
|
connectivity: Connectivity,
|
||||||
concurrency: Concurrency,
|
concurrency: Concurrency,
|
||||||
native_tls: bool,
|
native_tls: bool,
|
||||||
|
@ -56,15 +56,15 @@ pub(crate) async fn install(
|
||||||
.connectivity(connectivity)
|
.connectivity(connectivity)
|
||||||
.native_tls(native_tls);
|
.native_tls(native_tls);
|
||||||
|
|
||||||
let python_request = python.as_deref().map(ToolchainRequest::parse);
|
let python_request = python.as_deref().map(PythonRequest::parse);
|
||||||
|
|
||||||
// Pre-emptively identify a Python interpreter. We need an interpreter to resolve any unnamed
|
// Pre-emptively identify a Python interpreter. We need an interpreter to resolve any unnamed
|
||||||
// requirements, even if we end up using a different interpreter for the tool install itself.
|
// requirements, even if we end up using a different interpreter for the tool install itself.
|
||||||
let interpreter = Toolchain::find_or_fetch(
|
let interpreter = PythonInstallation::find_or_fetch(
|
||||||
python_request.clone(),
|
python_request.clone(),
|
||||||
EnvironmentPreference::OnlySystem,
|
EnvironmentPreference::OnlySystem,
|
||||||
toolchain_preference,
|
python_preference,
|
||||||
toolchain_fetch,
|
python_fetch,
|
||||||
&client_builder,
|
&client_builder,
|
||||||
cache,
|
cache,
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,11 +14,11 @@ use uv_cli::ExternalCommand;
|
||||||
use uv_client::{BaseClientBuilder, Connectivity};
|
use uv_client::{BaseClientBuilder, Connectivity};
|
||||||
use uv_configuration::{Concurrency, PreviewMode};
|
use uv_configuration::{Concurrency, PreviewMode};
|
||||||
use uv_normalize::PackageName;
|
use uv_normalize::PackageName;
|
||||||
use uv_requirements::{RequirementsSource, RequirementsSpecification};
|
use uv_python::{
|
||||||
use uv_toolchain::{
|
EnvironmentPreference, PythonEnvironment, PythonFetch, PythonInstallation, PythonPreference,
|
||||||
EnvironmentPreference, PythonEnvironment, Toolchain, ToolchainFetch, ToolchainPreference,
|
PythonRequest,
|
||||||
ToolchainRequest,
|
|
||||||
};
|
};
|
||||||
|
use uv_requirements::{RequirementsSource, RequirementsSpecification};
|
||||||
use uv_warnings::warn_user_once;
|
use uv_warnings::warn_user_once;
|
||||||
|
|
||||||
use crate::commands::pip::operations::Modifications;
|
use crate::commands::pip::operations::Modifications;
|
||||||
|
@ -36,8 +36,8 @@ pub(crate) async fn run(
|
||||||
settings: ResolverInstallerSettings,
|
settings: ResolverInstallerSettings,
|
||||||
_isolated: bool,
|
_isolated: bool,
|
||||||
preview: PreviewMode,
|
preview: PreviewMode,
|
||||||
toolchain_preference: ToolchainPreference,
|
python_preference: PythonPreference,
|
||||||
toolchain_fetch: ToolchainFetch,
|
python_fetch: PythonFetch,
|
||||||
connectivity: Connectivity,
|
connectivity: Connectivity,
|
||||||
concurrency: Concurrency,
|
concurrency: Concurrency,
|
||||||
native_tls: bool,
|
native_tls: bool,
|
||||||
|
@ -78,11 +78,11 @@ pub(crate) async fn run(
|
||||||
debug!("Syncing ephemeral environment.");
|
debug!("Syncing ephemeral environment.");
|
||||||
|
|
||||||
// Discover an interpreter.
|
// Discover an interpreter.
|
||||||
let interpreter = Toolchain::find_or_fetch(
|
let interpreter = PythonInstallation::find_or_fetch(
|
||||||
python.as_deref().map(ToolchainRequest::parse),
|
python.as_deref().map(PythonRequest::parse),
|
||||||
EnvironmentPreference::OnlySystem,
|
EnvironmentPreference::OnlySystem,
|
||||||
toolchain_preference,
|
python_preference,
|
||||||
toolchain_fetch,
|
python_fetch,
|
||||||
&client_builder,
|
&client_builder,
|
||||||
cache,
|
cache,
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,121 +0,0 @@
|
||||||
use anyhow::Result;
|
|
||||||
use futures::StreamExt;
|
|
||||||
use itertools::Itertools;
|
|
||||||
use std::collections::BTreeSet;
|
|
||||||
use std::fmt::Write;
|
|
||||||
use uv_configuration::PreviewMode;
|
|
||||||
use uv_toolchain::downloads::{self, PythonDownloadRequest};
|
|
||||||
use uv_toolchain::managed::InstalledToolchains;
|
|
||||||
use uv_toolchain::ToolchainRequest;
|
|
||||||
use uv_warnings::warn_user_once;
|
|
||||||
|
|
||||||
use crate::commands::ExitStatus;
|
|
||||||
use crate::printer::Printer;
|
|
||||||
|
|
||||||
/// Uninstall Python toolchains.
|
|
||||||
pub(crate) async fn uninstall(
|
|
||||||
targets: Vec<String>,
|
|
||||||
preview: PreviewMode,
|
|
||||||
printer: Printer,
|
|
||||||
) -> Result<ExitStatus> {
|
|
||||||
if preview.is_disabled() {
|
|
||||||
warn_user_once!("`uv toolchain uninstall` is experimental and may change without warning.");
|
|
||||||
}
|
|
||||||
|
|
||||||
let toolchains = InstalledToolchains::from_settings()?.init()?;
|
|
||||||
let _lock = toolchains.acquire_lock()?;
|
|
||||||
|
|
||||||
let requests = targets
|
|
||||||
.iter()
|
|
||||||
.map(|target| ToolchainRequest::parse(target.as_str()))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let download_requests = requests
|
|
||||||
.iter()
|
|
||||||
.map(PythonDownloadRequest::from_request)
|
|
||||||
.collect::<Result<Vec<_>, downloads::Error>>()?;
|
|
||||||
|
|
||||||
let installed_toolchains: Vec<_> = toolchains.find_all()?.collect();
|
|
||||||
let mut matching_toolchains = BTreeSet::default();
|
|
||||||
for (request, download_request) in requests.iter().zip(download_requests) {
|
|
||||||
writeln!(
|
|
||||||
printer.stderr(),
|
|
||||||
"Looking for installed toolchains matching {request} ({download_request})"
|
|
||||||
)?;
|
|
||||||
let mut found = false;
|
|
||||||
for toolchain in installed_toolchains
|
|
||||||
.iter()
|
|
||||||
.filter(|toolchain| download_request.satisfied_by_key(toolchain.key()))
|
|
||||||
{
|
|
||||||
found = true;
|
|
||||||
if matching_toolchains.insert(toolchain.clone()) {
|
|
||||||
writeln!(
|
|
||||||
printer.stderr(),
|
|
||||||
"Found toolchain `{}` that matches {request}",
|
|
||||||
toolchain.key()
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
writeln!(printer.stderr(), "No toolchains found matching {request}")?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if matching_toolchains.is_empty() {
|
|
||||||
if matches!(requests.as_slice(), [ToolchainRequest::Any]) {
|
|
||||||
writeln!(printer.stderr(), "No installed toolchains found")?;
|
|
||||||
} else if requests.len() > 1 {
|
|
||||||
writeln!(
|
|
||||||
printer.stderr(),
|
|
||||||
"No toolchains found matching the requests"
|
|
||||||
)?;
|
|
||||||
} else {
|
|
||||||
writeln!(printer.stderr(), "No toolchains found matching the request")?;
|
|
||||||
}
|
|
||||||
return Ok(ExitStatus::Failure);
|
|
||||||
}
|
|
||||||
|
|
||||||
let tasks = futures::stream::iter(matching_toolchains.iter())
|
|
||||||
.map(|toolchain| async {
|
|
||||||
(
|
|
||||||
toolchain.key(),
|
|
||||||
fs_err::tokio::remove_dir_all(toolchain.path()).await,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.buffered(4);
|
|
||||||
|
|
||||||
let results = tasks.collect::<Vec<_>>().await;
|
|
||||||
let mut failed = false;
|
|
||||||
for (key, result) in results.iter().sorted_by_key(|(key, _)| key) {
|
|
||||||
if let Err(err) = result {
|
|
||||||
failed = true;
|
|
||||||
writeln!(
|
|
||||||
printer.stderr(),
|
|
||||||
"Failed to uninstall toolchain `{key}`: {err}"
|
|
||||||
)?;
|
|
||||||
} else {
|
|
||||||
writeln!(printer.stderr(), "Uninstalled toolchain `{key}`")?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if failed {
|
|
||||||
if matching_toolchains.len() > 1 {
|
|
||||||
writeln!(printer.stderr(), "Uninstall of some toolchains failed")?;
|
|
||||||
}
|
|
||||||
return Ok(ExitStatus::Failure);
|
|
||||||
}
|
|
||||||
|
|
||||||
let s = if matching_toolchains.len() == 1 {
|
|
||||||
""
|
|
||||||
} else {
|
|
||||||
"s"
|
|
||||||
};
|
|
||||||
|
|
||||||
writeln!(
|
|
||||||
printer.stderr(),
|
|
||||||
"Uninstalled {} toolchain{s}",
|
|
||||||
matching_toolchains.len()
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(ExitStatus::Success)
|
|
||||||
}
|
|
|
@ -22,11 +22,11 @@ use uv_configuration::{
|
||||||
use uv_dispatch::BuildDispatch;
|
use uv_dispatch::BuildDispatch;
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
use uv_git::GitResolver;
|
use uv_git::GitResolver;
|
||||||
use uv_resolver::{ExcludeNewer, FlatIndex, InMemoryIndex};
|
use uv_python::{
|
||||||
use uv_toolchain::{
|
request_from_version_file, EnvironmentPreference, PythonFetch, PythonInstallation,
|
||||||
request_from_version_file, EnvironmentPreference, Toolchain, ToolchainFetch,
|
PythonPreference, PythonRequest,
|
||||||
ToolchainPreference, ToolchainRequest,
|
|
||||||
};
|
};
|
||||||
|
use uv_resolver::{ExcludeNewer, FlatIndex, InMemoryIndex};
|
||||||
use uv_types::{BuildContext, BuildIsolation, HashStrategy, InFlight};
|
use uv_types::{BuildContext, BuildIsolation, HashStrategy, InFlight};
|
||||||
|
|
||||||
use crate::commands::{pip, ExitStatus};
|
use crate::commands::{pip, ExitStatus};
|
||||||
|
@ -42,8 +42,8 @@ use crate::shell::Shell;
|
||||||
pub(crate) async fn venv(
|
pub(crate) async fn venv(
|
||||||
path: &Path,
|
path: &Path,
|
||||||
python_request: Option<&str>,
|
python_request: Option<&str>,
|
||||||
toolchain_preference: ToolchainPreference,
|
python_preference: PythonPreference,
|
||||||
toolchain_fetch: ToolchainFetch,
|
python_fetch: PythonFetch,
|
||||||
link_mode: LinkMode,
|
link_mode: LinkMode,
|
||||||
index_locations: &IndexLocations,
|
index_locations: &IndexLocations,
|
||||||
index_strategy: IndexStrategy,
|
index_strategy: IndexStrategy,
|
||||||
|
@ -71,8 +71,8 @@ pub(crate) async fn venv(
|
||||||
connectivity,
|
connectivity,
|
||||||
seed,
|
seed,
|
||||||
preview,
|
preview,
|
||||||
toolchain_preference,
|
python_preference,
|
||||||
toolchain_fetch,
|
python_fetch,
|
||||||
allow_existing,
|
allow_existing,
|
||||||
exclude_newer,
|
exclude_newer,
|
||||||
native_tls,
|
native_tls,
|
||||||
|
@ -122,8 +122,8 @@ async fn venv_impl(
|
||||||
connectivity: Connectivity,
|
connectivity: Connectivity,
|
||||||
seed: bool,
|
seed: bool,
|
||||||
preview: PreviewMode,
|
preview: PreviewMode,
|
||||||
toolchain_preference: ToolchainPreference,
|
python_preference: PythonPreference,
|
||||||
toolchain_fetch: ToolchainFetch,
|
python_fetch: PythonFetch,
|
||||||
allow_existing: bool,
|
allow_existing: bool,
|
||||||
exclude_newer: Option<ExcludeNewer>,
|
exclude_newer: Option<ExcludeNewer>,
|
||||||
native_tls: bool,
|
native_tls: bool,
|
||||||
|
@ -134,17 +134,17 @@ async fn venv_impl(
|
||||||
.connectivity(connectivity)
|
.connectivity(connectivity)
|
||||||
.native_tls(native_tls);
|
.native_tls(native_tls);
|
||||||
|
|
||||||
let mut interpreter_request = python_request.map(ToolchainRequest::parse);
|
let mut interpreter_request = python_request.map(PythonRequest::parse);
|
||||||
if preview.is_enabled() && interpreter_request.is_none() {
|
if preview.is_enabled() && interpreter_request.is_none() {
|
||||||
interpreter_request = request_from_version_file().await.into_diagnostic()?;
|
interpreter_request = request_from_version_file().await.into_diagnostic()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Locate the Python interpreter to use in the environment
|
// Locate the Python interpreter to use in the environment
|
||||||
let interpreter = Toolchain::find_or_fetch(
|
let interpreter = PythonInstallation::find_or_fetch(
|
||||||
interpreter_request,
|
interpreter_request,
|
||||||
EnvironmentPreference::OnlySystem,
|
EnvironmentPreference::OnlySystem,
|
||||||
toolchain_preference,
|
python_preference,
|
||||||
toolchain_fetch,
|
python_fetch,
|
||||||
&client_builder,
|
&client_builder,
|
||||||
cache,
|
cache,
|
||||||
)
|
)
|
||||||
|
|
|
@ -17,9 +17,9 @@ use uv_cli::{
|
||||||
compat::CompatArgs, CacheCommand, CacheNamespace, Cli, Commands, PipCommand, PipNamespace,
|
compat::CompatArgs, CacheCommand, CacheNamespace, Cli, Commands, PipCommand, PipNamespace,
|
||||||
ProjectCommand,
|
ProjectCommand,
|
||||||
};
|
};
|
||||||
|
use uv_cli::{PythonCommand, PythonNamespace, ToolCommand, ToolNamespace};
|
||||||
#[cfg(feature = "self-update")]
|
#[cfg(feature = "self-update")]
|
||||||
use uv_cli::{SelfCommand, SelfNamespace};
|
use uv_cli::{SelfCommand, SelfNamespace};
|
||||||
use uv_cli::{ToolCommand, ToolNamespace, ToolchainCommand, ToolchainNamespace};
|
|
||||||
use uv_configuration::Concurrency;
|
use uv_configuration::Concurrency;
|
||||||
use uv_distribution::Workspace;
|
use uv_distribution::Workspace;
|
||||||
use uv_requirements::RequirementsSource;
|
use uv_requirements::RequirementsSource;
|
||||||
|
@ -288,7 +288,7 @@ async fn run() -> Result<ExitStatus> {
|
||||||
args.settings.link_mode,
|
args.settings.link_mode,
|
||||||
args.settings.python,
|
args.settings.python,
|
||||||
args.settings.system,
|
args.settings.system,
|
||||||
globals.toolchain_preference,
|
globals.python_preference,
|
||||||
args.settings.concurrency,
|
args.settings.concurrency,
|
||||||
globals.native_tls,
|
globals.native_tls,
|
||||||
globals.quiet,
|
globals.quiet,
|
||||||
|
@ -617,8 +617,8 @@ async fn run() -> Result<ExitStatus> {
|
||||||
commands::venv(
|
commands::venv(
|
||||||
&args.name,
|
&args.name,
|
||||||
args.settings.python.as_deref(),
|
args.settings.python.as_deref(),
|
||||||
globals.toolchain_preference,
|
globals.python_preference,
|
||||||
globals.toolchain_fetch,
|
globals.python_fetch,
|
||||||
args.settings.link_mode,
|
args.settings.link_mode,
|
||||||
&args.settings.index_locations,
|
&args.settings.index_locations,
|
||||||
args.settings.index_strategy,
|
args.settings.index_strategy,
|
||||||
|
@ -660,8 +660,8 @@ async fn run() -> Result<ExitStatus> {
|
||||||
args.settings,
|
args.settings,
|
||||||
globals.isolated,
|
globals.isolated,
|
||||||
globals.preview,
|
globals.preview,
|
||||||
globals.toolchain_preference,
|
globals.python_preference,
|
||||||
globals.toolchain_fetch,
|
globals.python_fetch,
|
||||||
globals.connectivity,
|
globals.connectivity,
|
||||||
Concurrency::default(),
|
Concurrency::default(),
|
||||||
globals.native_tls,
|
globals.native_tls,
|
||||||
|
@ -683,8 +683,8 @@ async fn run() -> Result<ExitStatus> {
|
||||||
args.dev,
|
args.dev,
|
||||||
args.modifications,
|
args.modifications,
|
||||||
args.python,
|
args.python,
|
||||||
globals.toolchain_preference,
|
globals.python_preference,
|
||||||
globals.toolchain_fetch,
|
globals.python_fetch,
|
||||||
args.settings,
|
args.settings,
|
||||||
globals.preview,
|
globals.preview,
|
||||||
globals.connectivity,
|
globals.connectivity,
|
||||||
|
@ -707,8 +707,8 @@ async fn run() -> Result<ExitStatus> {
|
||||||
args.python,
|
args.python,
|
||||||
args.settings,
|
args.settings,
|
||||||
globals.preview,
|
globals.preview,
|
||||||
globals.toolchain_preference,
|
globals.python_preference,
|
||||||
globals.toolchain_fetch,
|
globals.python_fetch,
|
||||||
globals.connectivity,
|
globals.connectivity,
|
||||||
Concurrency::default(),
|
Concurrency::default(),
|
||||||
globals.native_tls,
|
globals.native_tls,
|
||||||
|
@ -737,8 +737,8 @@ async fn run() -> Result<ExitStatus> {
|
||||||
args.package,
|
args.package,
|
||||||
args.python,
|
args.python,
|
||||||
args.settings,
|
args.settings,
|
||||||
globals.toolchain_preference,
|
globals.python_preference,
|
||||||
globals.toolchain_fetch,
|
globals.python_fetch,
|
||||||
globals.preview,
|
globals.preview,
|
||||||
globals.connectivity,
|
globals.connectivity,
|
||||||
Concurrency::default(),
|
Concurrency::default(),
|
||||||
|
@ -761,8 +761,8 @@ async fn run() -> Result<ExitStatus> {
|
||||||
args.dependency_type,
|
args.dependency_type,
|
||||||
args.package,
|
args.package,
|
||||||
args.python,
|
args.python,
|
||||||
globals.toolchain_preference,
|
globals.python_preference,
|
||||||
globals.toolchain_fetch,
|
globals.python_fetch,
|
||||||
globals.preview,
|
globals.preview,
|
||||||
globals.connectivity,
|
globals.connectivity,
|
||||||
Concurrency::default(),
|
Concurrency::default(),
|
||||||
|
@ -802,8 +802,8 @@ async fn run() -> Result<ExitStatus> {
|
||||||
args.settings,
|
args.settings,
|
||||||
globals.isolated,
|
globals.isolated,
|
||||||
globals.preview,
|
globals.preview,
|
||||||
globals.toolchain_preference,
|
globals.python_preference,
|
||||||
globals.toolchain_fetch,
|
globals.python_fetch,
|
||||||
globals.connectivity,
|
globals.connectivity,
|
||||||
Concurrency::default(),
|
Concurrency::default(),
|
||||||
globals.native_tls,
|
globals.native_tls,
|
||||||
|
@ -830,8 +830,8 @@ async fn run() -> Result<ExitStatus> {
|
||||||
args.force,
|
args.force,
|
||||||
args.settings,
|
args.settings,
|
||||||
globals.preview,
|
globals.preview,
|
||||||
globals.toolchain_preference,
|
globals.python_preference,
|
||||||
globals.toolchain_fetch,
|
globals.python_fetch,
|
||||||
globals.connectivity,
|
globals.connectivity,
|
||||||
Concurrency::default(),
|
Concurrency::default(),
|
||||||
globals.native_tls,
|
globals.native_tls,
|
||||||
|
@ -864,39 +864,39 @@ async fn run() -> Result<ExitStatus> {
|
||||||
commands::tool_dir(globals.preview)?;
|
commands::tool_dir(globals.preview)?;
|
||||||
Ok(ExitStatus::Success)
|
Ok(ExitStatus::Success)
|
||||||
}
|
}
|
||||||
Commands::Toolchain(ToolchainNamespace {
|
Commands::Python(PythonNamespace {
|
||||||
command: ToolchainCommand::List(args),
|
command: PythonCommand::List(args),
|
||||||
}) => {
|
}) => {
|
||||||
// Resolve the settings from the command-line arguments and workspace configuration.
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
||||||
let args = settings::ToolchainListSettings::resolve(args, filesystem);
|
let args = settings::PythonListSettings::resolve(args, filesystem);
|
||||||
show_settings!(args);
|
show_settings!(args);
|
||||||
|
|
||||||
// Initialize the cache.
|
// Initialize the cache.
|
||||||
let cache = cache.init()?;
|
let cache = cache.init()?;
|
||||||
|
|
||||||
commands::toolchain_list(
|
commands::python_list(
|
||||||
args.kinds,
|
args.kinds,
|
||||||
args.all_versions,
|
args.all_versions,
|
||||||
args.all_platforms,
|
args.all_platforms,
|
||||||
globals.toolchain_preference,
|
globals.python_preference,
|
||||||
globals.toolchain_fetch,
|
globals.python_fetch,
|
||||||
globals.preview,
|
globals.preview,
|
||||||
&cache,
|
&cache,
|
||||||
printer,
|
printer,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
Commands::Toolchain(ToolchainNamespace {
|
Commands::Python(PythonNamespace {
|
||||||
command: ToolchainCommand::Install(args),
|
command: PythonCommand::Install(args),
|
||||||
}) => {
|
}) => {
|
||||||
// Resolve the settings from the command-line arguments and workspace configuration.
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
||||||
let args = settings::ToolchainInstallSettings::resolve(args, filesystem);
|
let args = settings::PythonInstallSettings::resolve(args, filesystem);
|
||||||
show_settings!(args);
|
show_settings!(args);
|
||||||
|
|
||||||
// Initialize the cache.
|
// Initialize the cache.
|
||||||
let cache = cache.init()?;
|
let cache = cache.init()?;
|
||||||
|
|
||||||
commands::toolchain_install(
|
commands::python_install(
|
||||||
args.targets,
|
args.targets,
|
||||||
args.force,
|
args.force,
|
||||||
globals.native_tls,
|
globals.native_tls,
|
||||||
|
@ -907,37 +907,37 @@ async fn run() -> Result<ExitStatus> {
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
Commands::Toolchain(ToolchainNamespace {
|
Commands::Python(PythonNamespace {
|
||||||
command: ToolchainCommand::Uninstall(args),
|
command: PythonCommand::Uninstall(args),
|
||||||
}) => {
|
}) => {
|
||||||
// Resolve the settings from the command-line arguments and workspace configuration.
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
||||||
let args = settings::ToolchainUninstallSettings::resolve(args, filesystem);
|
let args = settings::PythonUninstallSettings::resolve(args, filesystem);
|
||||||
show_settings!(args);
|
show_settings!(args);
|
||||||
|
|
||||||
commands::toolchain_uninstall(args.targets, globals.preview, printer).await
|
commands::python_uninstall(args.targets, globals.preview, printer).await
|
||||||
}
|
}
|
||||||
Commands::Toolchain(ToolchainNamespace {
|
Commands::Python(PythonNamespace {
|
||||||
command: ToolchainCommand::Find(args),
|
command: PythonCommand::Find(args),
|
||||||
}) => {
|
}) => {
|
||||||
// Resolve the settings from the command-line arguments and workspace configuration.
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
||||||
let args = settings::ToolchainFindSettings::resolve(args, filesystem);
|
let args = settings::PythonFindSettings::resolve(args, filesystem);
|
||||||
|
|
||||||
// Initialize the cache.
|
// Initialize the cache.
|
||||||
let cache = cache.init()?;
|
let cache = cache.init()?;
|
||||||
|
|
||||||
commands::toolchain_find(
|
commands::python_find(
|
||||||
args.request,
|
args.request,
|
||||||
globals.toolchain_preference,
|
globals.python_preference,
|
||||||
globals.preview,
|
globals.preview,
|
||||||
&cache,
|
&cache,
|
||||||
printer,
|
printer,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
Commands::Toolchain(ToolchainNamespace {
|
Commands::Python(PythonNamespace {
|
||||||
command: ToolchainCommand::Dir,
|
command: PythonCommand::Dir,
|
||||||
}) => {
|
}) => {
|
||||||
commands::toolchain_dir(globals.preview)?;
|
commands::python_dir(globals.preview)?;
|
||||||
Ok(ExitStatus::Success)
|
Ok(ExitStatus::Success)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,9 @@ use uv_cli::options::{flag, installer_options, resolver_installer_options, resol
|
||||||
use uv_cli::{
|
use uv_cli::{
|
||||||
AddArgs, ColorChoice, Commands, ExternalCommand, GlobalArgs, ListFormat, LockArgs, Maybe,
|
AddArgs, ColorChoice, Commands, ExternalCommand, GlobalArgs, ListFormat, LockArgs, Maybe,
|
||||||
PipCheckArgs, PipCompileArgs, PipFreezeArgs, PipInstallArgs, PipListArgs, PipShowArgs,
|
PipCheckArgs, PipCompileArgs, PipFreezeArgs, PipInstallArgs, PipListArgs, PipShowArgs,
|
||||||
PipSyncArgs, PipTreeArgs, PipUninstallArgs, RemoveArgs, RunArgs, SyncArgs, ToolInstallArgs,
|
PipSyncArgs, PipTreeArgs, PipUninstallArgs, PythonFindArgs, PythonInstallArgs, PythonListArgs,
|
||||||
ToolListArgs, ToolRunArgs, ToolUninstallArgs, ToolchainFindArgs, ToolchainInstallArgs,
|
PythonUninstallArgs, RemoveArgs, RunArgs, SyncArgs, ToolInstallArgs, ToolListArgs, ToolRunArgs,
|
||||||
ToolchainListArgs, ToolchainUninstallArgs, VenvArgs,
|
ToolUninstallArgs, VenvArgs,
|
||||||
};
|
};
|
||||||
use uv_client::Connectivity;
|
use uv_client::Connectivity;
|
||||||
use uv_configuration::{
|
use uv_configuration::{
|
||||||
|
@ -25,13 +25,13 @@ use uv_configuration::{
|
||||||
};
|
};
|
||||||
use uv_distribution::pyproject::DependencyType;
|
use uv_distribution::pyproject::DependencyType;
|
||||||
use uv_normalize::PackageName;
|
use uv_normalize::PackageName;
|
||||||
|
use uv_python::{Prefix, PythonFetch, PythonPreference, PythonVersion, Target};
|
||||||
use uv_requirements::RequirementsSource;
|
use uv_requirements::RequirementsSource;
|
||||||
use uv_resolver::{AnnotationStyle, DependencyMode, ExcludeNewer, PreReleaseMode, ResolutionMode};
|
use uv_resolver::{AnnotationStyle, DependencyMode, ExcludeNewer, PreReleaseMode, ResolutionMode};
|
||||||
use uv_settings::{
|
use uv_settings::{
|
||||||
Combine, FilesystemOptions, InstallerOptions, Options, PipOptions, ResolverInstallerOptions,
|
Combine, FilesystemOptions, InstallerOptions, Options, PipOptions, ResolverInstallerOptions,
|
||||||
ResolverOptions,
|
ResolverOptions,
|
||||||
};
|
};
|
||||||
use uv_toolchain::{Prefix, PythonVersion, Target, ToolchainFetch, ToolchainPreference};
|
|
||||||
|
|
||||||
use crate::commands::pip::operations::Modifications;
|
use crate::commands::pip::operations::Modifications;
|
||||||
|
|
||||||
|
@ -47,8 +47,8 @@ pub(crate) struct GlobalSettings {
|
||||||
pub(crate) isolated: bool,
|
pub(crate) isolated: bool,
|
||||||
pub(crate) show_settings: bool,
|
pub(crate) show_settings: bool,
|
||||||
pub(crate) preview: PreviewMode,
|
pub(crate) preview: PreviewMode,
|
||||||
pub(crate) toolchain_preference: ToolchainPreference,
|
pub(crate) python_preference: PythonPreference,
|
||||||
pub(crate) toolchain_fetch: ToolchainFetch,
|
pub(crate) python_fetch: PythonFetch,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GlobalSettings {
|
impl GlobalSettings {
|
||||||
|
@ -64,17 +64,17 @@ impl GlobalSettings {
|
||||||
.unwrap_or(false),
|
.unwrap_or(false),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Always use preview mode toolchain preferences during preview commands
|
// Always use preview mode python preferences during preview commands
|
||||||
// TODO(zanieb): There should be a cleaner way to do this, we should probably resolve
|
// TODO(zanieb): There should be a cleaner way to do this, we should probably resolve
|
||||||
// force preview to true for these commands but it would break our experimental warning
|
// force preview to true for these commands but it would break our experimental warning
|
||||||
// right now
|
// right now
|
||||||
let default_toolchain_preference = if matches!(
|
let default_python_preference = if matches!(
|
||||||
command,
|
command,
|
||||||
Commands::Project(_) | Commands::Toolchain(_) | Commands::Tool(_)
|
Commands::Project(_) | Commands::Python(_) | Commands::Tool(_)
|
||||||
) {
|
) {
|
||||||
ToolchainPreference::default_from(PreviewMode::Enabled)
|
PythonPreference::default_from(PreviewMode::Enabled)
|
||||||
} else {
|
} else {
|
||||||
ToolchainPreference::default_from(preview)
|
PythonPreference::default_from(preview)
|
||||||
};
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
@ -111,13 +111,13 @@ impl GlobalSettings {
|
||||||
isolated: args.isolated,
|
isolated: args.isolated,
|
||||||
show_settings: args.show_settings,
|
show_settings: args.show_settings,
|
||||||
preview,
|
preview,
|
||||||
toolchain_preference: args
|
python_preference: args
|
||||||
.toolchain_preference
|
.python_preference
|
||||||
.combine(workspace.and_then(|workspace| workspace.globals.toolchain_preference))
|
.combine(workspace.and_then(|workspace| workspace.globals.python_preference))
|
||||||
.unwrap_or(default_toolchain_preference),
|
.unwrap_or(default_python_preference),
|
||||||
toolchain_fetch: args
|
python_fetch: args
|
||||||
.toolchain_fetch
|
.python_fetch
|
||||||
.combine(workspace.and_then(|workspace| workspace.globals.toolchain_fetch))
|
.combine(workspace.and_then(|workspace| workspace.globals.python_fetch))
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -314,7 +314,7 @@ impl ToolUninstallSettings {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub(crate) enum ToolchainListKinds {
|
pub(crate) enum PythonListKinds {
|
||||||
#[default]
|
#[default]
|
||||||
Default,
|
Default,
|
||||||
Installed,
|
Installed,
|
||||||
|
@ -323,26 +323,26 @@ pub(crate) enum ToolchainListKinds {
|
||||||
/// The resolved settings to use for a `tool run` invocation.
|
/// The resolved settings to use for a `tool run` invocation.
|
||||||
#[allow(clippy::struct_excessive_bools)]
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct ToolchainListSettings {
|
pub(crate) struct PythonListSettings {
|
||||||
pub(crate) kinds: ToolchainListKinds,
|
pub(crate) kinds: PythonListKinds,
|
||||||
pub(crate) all_platforms: bool,
|
pub(crate) all_platforms: bool,
|
||||||
pub(crate) all_versions: bool,
|
pub(crate) all_versions: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToolchainListSettings {
|
impl PythonListSettings {
|
||||||
/// Resolve the [`ToolchainListSettings`] from the CLI and filesystem configuration.
|
/// Resolve the [`PythonListSettings`] from the CLI and filesystem configuration.
|
||||||
#[allow(clippy::needless_pass_by_value)]
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
pub(crate) fn resolve(args: ToolchainListArgs, _filesystem: Option<FilesystemOptions>) -> Self {
|
pub(crate) fn resolve(args: PythonListArgs, _filesystem: Option<FilesystemOptions>) -> Self {
|
||||||
let ToolchainListArgs {
|
let PythonListArgs {
|
||||||
all_versions,
|
all_versions,
|
||||||
all_platforms,
|
all_platforms,
|
||||||
only_installed,
|
only_installed,
|
||||||
} = args;
|
} = args;
|
||||||
|
|
||||||
let kinds = if only_installed {
|
let kinds = if only_installed {
|
||||||
ToolchainListKinds::Installed
|
PythonListKinds::Installed
|
||||||
} else {
|
} else {
|
||||||
ToolchainListKinds::default()
|
PythonListKinds::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
@ -353,59 +353,56 @@ impl ToolchainListSettings {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The resolved settings to use for a `toolchain install` invocation.
|
/// The resolved settings to use for a `python install` invocation.
|
||||||
#[allow(clippy::struct_excessive_bools)]
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct ToolchainInstallSettings {
|
pub(crate) struct PythonInstallSettings {
|
||||||
pub(crate) targets: Vec<String>,
|
pub(crate) targets: Vec<String>,
|
||||||
pub(crate) force: bool,
|
pub(crate) force: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToolchainInstallSettings {
|
impl PythonInstallSettings {
|
||||||
/// Resolve the [`ToolchainInstallSettings`] from the CLI and filesystem configuration.
|
/// Resolve the [`PythonInstallSettings`] from the CLI and filesystem configuration.
|
||||||
#[allow(clippy::needless_pass_by_value)]
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
pub(crate) fn resolve(
|
pub(crate) fn resolve(args: PythonInstallArgs, _filesystem: Option<FilesystemOptions>) -> Self {
|
||||||
args: ToolchainInstallArgs,
|
let PythonInstallArgs { targets, force } = args;
|
||||||
_filesystem: Option<FilesystemOptions>,
|
|
||||||
) -> Self {
|
|
||||||
let ToolchainInstallArgs { targets, force } = args;
|
|
||||||
|
|
||||||
Self { targets, force }
|
Self { targets, force }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The resolved settings to use for a `toolchain uninstall` invocation.
|
/// The resolved settings to use for a `python uninstall` invocation.
|
||||||
#[allow(clippy::struct_excessive_bools)]
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct ToolchainUninstallSettings {
|
pub(crate) struct PythonUninstallSettings {
|
||||||
pub(crate) targets: Vec<String>,
|
pub(crate) targets: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToolchainUninstallSettings {
|
impl PythonUninstallSettings {
|
||||||
/// Resolve the [`ToolchainUninstallSettings`] from the CLI and filesystem configuration.
|
/// Resolve the [`PythonUninstallSettings`] from the CLI and filesystem configuration.
|
||||||
#[allow(clippy::needless_pass_by_value)]
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
pub(crate) fn resolve(
|
pub(crate) fn resolve(
|
||||||
args: ToolchainUninstallArgs,
|
args: PythonUninstallArgs,
|
||||||
_filesystem: Option<FilesystemOptions>,
|
_filesystem: Option<FilesystemOptions>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let ToolchainUninstallArgs { targets } = args;
|
let PythonUninstallArgs { targets } = args;
|
||||||
|
|
||||||
Self { targets }
|
Self { targets }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The resolved settings to use for a `toolchain find` invocation.
|
/// The resolved settings to use for a `python find` invocation.
|
||||||
#[allow(clippy::struct_excessive_bools)]
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct ToolchainFindSettings {
|
pub(crate) struct PythonFindSettings {
|
||||||
pub(crate) request: Option<String>,
|
pub(crate) request: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToolchainFindSettings {
|
impl PythonFindSettings {
|
||||||
/// Resolve the [`ToolchainFindSettings`] from the CLI and workspace configuration.
|
/// Resolve the [`PythonFindSettings`] from the CLI and workspace configuration.
|
||||||
#[allow(clippy::needless_pass_by_value)]
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
pub(crate) fn resolve(args: ToolchainFindArgs, _filesystem: Option<FilesystemOptions>) -> Self {
|
pub(crate) fn resolve(args: PythonFindArgs, _filesystem: Option<FilesystemOptions>) -> Self {
|
||||||
let ToolchainFindArgs { request } = args;
|
let PythonFindArgs { request } = args;
|
||||||
|
|
||||||
Self { request }
|
Self { request }
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,9 @@ use regex::Regex;
|
||||||
|
|
||||||
use uv_cache::Cache;
|
use uv_cache::Cache;
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
use uv_toolchain::managed::InstalledToolchains;
|
use uv_python::managed::ManagedPythonInstallations;
|
||||||
use uv_toolchain::{
|
use uv_python::{
|
||||||
EnvironmentPreference, PythonVersion, Toolchain, ToolchainPreference, ToolchainRequest,
|
EnvironmentPreference, PythonInstallation, PythonPreference, PythonRequest, PythonVersion,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Exclude any packages uploaded after this date.
|
// Exclude any packages uploaded after this date.
|
||||||
|
@ -157,7 +157,7 @@ impl TestContext {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|version| PythonVersion::from_str(version).unwrap())
|
.map(|version| PythonVersion::from_str(version).unwrap())
|
||||||
.zip(
|
.zip(
|
||||||
python_toolchains_for_versions(&temp_dir, python_versions)
|
python_installations_for_versions(&temp_dir, python_versions)
|
||||||
.expect("Failed to find test Python versions"),
|
.expect("Failed to find test Python versions"),
|
||||||
)
|
)
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -284,7 +284,7 @@ impl TestContext {
|
||||||
/// * Don't wrap text output based on the terminal we're in, the test output doesn't get printed
|
/// * Don't wrap text output based on the terminal we're in, the test output doesn't get printed
|
||||||
/// but snapshotted to a string.
|
/// but snapshotted to a string.
|
||||||
/// * Use a fake `HOME` to avoid accidentally changing the developer's machine.
|
/// * Use a fake `HOME` to avoid accidentally changing the developer's machine.
|
||||||
/// * Hide other Python toolchain with `UV_TOOLCHAIN_DIR` and installed interpreters with
|
/// * Hide other Python python with `UV_PYTHON_INSTALL_DIR` and installed interpreters with
|
||||||
/// `UV_TEST_PYTHON_PATH`.
|
/// `UV_TEST_PYTHON_PATH`.
|
||||||
/// * Increase the stack size to avoid stack overflows on windows due to large async functions.
|
/// * Increase the stack size to avoid stack overflows on windows due to large async functions.
|
||||||
pub fn add_shared_args(&self, command: &mut Command) {
|
pub fn add_shared_args(&self, command: &mut Command) {
|
||||||
|
@ -294,7 +294,7 @@ impl TestContext {
|
||||||
.env("VIRTUAL_ENV", self.venv.as_os_str())
|
.env("VIRTUAL_ENV", self.venv.as_os_str())
|
||||||
.env("UV_NO_WRAP", "1")
|
.env("UV_NO_WRAP", "1")
|
||||||
.env("HOME", self.home_dir.as_os_str())
|
.env("HOME", self.home_dir.as_os_str())
|
||||||
.env("UV_TOOLCHAIN_DIR", "")
|
.env("UV_PYTHON_INSTALL_DIR", "")
|
||||||
.env("UV_TEST_PYTHON_PATH", &self.python_path())
|
.env("UV_TEST_PYTHON_PATH", &self.python_path())
|
||||||
.env("UV_EXCLUDE_NEWER", EXCLUDE_NEWER)
|
.env("UV_EXCLUDE_NEWER", EXCLUDE_NEWER)
|
||||||
.current_dir(self.temp_dir.path());
|
.current_dir(self.temp_dir.path());
|
||||||
|
@ -371,23 +371,23 @@ impl TestContext {
|
||||||
command
|
command
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a `uv toolchain find` command with options shared across scenarios.
|
/// Create a `uv python find` command with options shared across scenarios.
|
||||||
pub fn toolchain_find(&self) -> Command {
|
pub fn python_find(&self) -> Command {
|
||||||
let mut command = Command::new(get_bin());
|
let mut command = Command::new(get_bin());
|
||||||
command
|
command
|
||||||
.arg("toolchain")
|
.arg("python")
|
||||||
.arg("find")
|
.arg("find")
|
||||||
.env("UV_PREVIEW", "1")
|
.env("UV_PREVIEW", "1")
|
||||||
.env("UV_TOOLCHAIN_DIR", "")
|
.env("UV_PYTHON_INSTALL_DIR", "")
|
||||||
.current_dir(&self.temp_dir);
|
.current_dir(&self.temp_dir);
|
||||||
self.add_shared_args(&mut command);
|
self.add_shared_args(&mut command);
|
||||||
command
|
command
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a `uv toolchain dir` command with options shared across scenarios.
|
/// Create a `uv python dir` command with options shared across scenarios.
|
||||||
pub fn toolchain_dir(&self) -> Command {
|
pub fn python_dir(&self) -> Command {
|
||||||
let mut command = Command::new(get_bin());
|
let mut command = Command::new(get_bin());
|
||||||
command.arg("toolchain").arg("dir");
|
command.arg("python").arg("dir");
|
||||||
self.add_shared_args(&mut command);
|
self.add_shared_args(&mut command);
|
||||||
command
|
command
|
||||||
}
|
}
|
||||||
|
@ -601,7 +601,7 @@ impl TestContext {
|
||||||
|
|
||||||
/// Create a new virtual environment named `.venv` in the test context.
|
/// Create a new virtual environment named `.venv` in the test context.
|
||||||
fn create_venv(&self) {
|
fn create_venv(&self) {
|
||||||
let executable = get_toolchain(
|
let executable = get_python(
|
||||||
self.python_version
|
self.python_version
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("A Python version must be provided to create a test virtual environment"),
|
.expect("A Python version must be provided to create a test virtual environment"),
|
||||||
|
@ -640,18 +640,18 @@ pub fn venv_to_interpreter(venv: &Path) -> PathBuf {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the path to the python interpreter for a specific toolchain version.
|
/// Get the path to the python interpreter for a specific python version.
|
||||||
pub fn get_toolchain(version: &PythonVersion) -> PathBuf {
|
pub fn get_python(version: &PythonVersion) -> PathBuf {
|
||||||
InstalledToolchains::from_settings()
|
ManagedPythonInstallations::from_settings()
|
||||||
.map(|installed_toolchains| {
|
.map(|installed_pythons| {
|
||||||
installed_toolchains
|
installed_pythons
|
||||||
.find_version(version)
|
.find_version(version)
|
||||||
.expect("Tests are run on a supported platform")
|
.expect("Tests are run on a supported platform")
|
||||||
.next()
|
.next()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(uv_toolchain::managed::InstalledToolchain::executable)
|
.map(uv_python::managed::ManagedPythonInstallation::executable)
|
||||||
})
|
})
|
||||||
// We'll search for the request Python on the PATH if not found in the toolchain versions
|
// We'll search for the request Python on the PATH if not found in the python versions
|
||||||
// We hack this into a `PathBuf` to satisfy the compiler but it's just a string
|
// We hack this into a `PathBuf` to satisfy the compiler but it's just a string
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.unwrap_or(PathBuf::from(version.to_string()))
|
.unwrap_or(PathBuf::from(version.to_string()))
|
||||||
|
@ -691,7 +691,7 @@ pub fn python_path_with_versions(
|
||||||
python_versions: &[&str],
|
python_versions: &[&str],
|
||||||
) -> anyhow::Result<OsString> {
|
) -> anyhow::Result<OsString> {
|
||||||
Ok(std::env::join_paths(
|
Ok(std::env::join_paths(
|
||||||
python_toolchains_for_versions(temp_dir, python_versions)?
|
python_installations_for_versions(temp_dir, python_versions)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|path| path.parent().unwrap().to_path_buf()),
|
.map(|path| path.parent().unwrap().to_path_buf()),
|
||||||
)?)
|
)?)
|
||||||
|
@ -700,7 +700,7 @@ pub fn python_path_with_versions(
|
||||||
/// Returns a list of Python executables for the given versions.
|
/// Returns a list of Python executables for the given versions.
|
||||||
///
|
///
|
||||||
/// Generally this should be used with `UV_TEST_PYTHON_PATH`.
|
/// Generally this should be used with `UV_TEST_PYTHON_PATH`.
|
||||||
pub fn python_toolchains_for_versions(
|
pub fn python_installations_for_versions(
|
||||||
temp_dir: &assert_fs::TempDir,
|
temp_dir: &assert_fs::TempDir,
|
||||||
python_versions: &[&str],
|
python_versions: &[&str],
|
||||||
) -> anyhow::Result<Vec<PathBuf>> {
|
) -> anyhow::Result<Vec<PathBuf>> {
|
||||||
|
@ -708,13 +708,13 @@ pub fn python_toolchains_for_versions(
|
||||||
let selected_pythons = python_versions
|
let selected_pythons = python_versions
|
||||||
.iter()
|
.iter()
|
||||||
.map(|python_version| {
|
.map(|python_version| {
|
||||||
if let Ok(toolchain) = Toolchain::find(
|
if let Ok(python) = PythonInstallation::find(
|
||||||
&ToolchainRequest::parse(python_version),
|
&PythonRequest::parse(python_version),
|
||||||
EnvironmentPreference::OnlySystem,
|
EnvironmentPreference::OnlySystem,
|
||||||
ToolchainPreference::Managed,
|
PythonPreference::Managed,
|
||||||
&cache,
|
&cache,
|
||||||
) {
|
) {
|
||||||
toolchain.into_interpreter().sys_executable().to_owned()
|
python.into_interpreter().sys_executable().to_owned()
|
||||||
} else {
|
} else {
|
||||||
panic!("Could not find Python {python_version} for test");
|
panic!("Could not find Python {python_version} for test");
|
||||||
}
|
}
|
||||||
|
|
|
@ -2034,13 +2034,13 @@ fn lock_requires_python() -> Result<()> {
|
||||||
.filters()
|
.filters()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(context.filters())
|
.chain(context.filters())
|
||||||
// Platform independent message for the missing toolchain
|
// Platform independent message for the missing Python installation
|
||||||
.chain([(" or `py` launcher", "")])
|
.chain([(" or `py` launcher", "")])
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// Install from the lockfile.
|
// Install from the lockfile.
|
||||||
// Note we need to disable toolchain fetches or we'll just download 3.12
|
// Note we need to disable Python fetches or we'll just download 3.12
|
||||||
uv_snapshot!(filters, context38.sync().arg("--toolchain-fetch").arg("manual"), @r###"
|
uv_snapshot!(filters, context38.sync().arg("--python-fetch").arg("manual"), @r###"
|
||||||
success: false
|
success: false
|
||||||
exit_code: 2
|
exit_code: 2
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
|
21
crates/uv/tests/python_dir.rs
Normal file
21
crates/uv/tests/python_dir.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
use assert_fs::fixture::PathChild;
|
||||||
|
use common::{uv_snapshot, TestContext};
|
||||||
|
|
||||||
|
mod common;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn python_dir() {
|
||||||
|
let context = TestContext::new("3.12");
|
||||||
|
|
||||||
|
let python_dir = context.temp_dir.child("python");
|
||||||
|
uv_snapshot!(context.filters(), context.python_dir()
|
||||||
|
.env("UV_PYTHON_INSTALL_DIR", python_dir.as_os_str()), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
[TEMP_DIR]/python
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
warning: `uv python dir` is experimental and may change without warning.
|
||||||
|
"###);
|
||||||
|
}
|
|
@ -1,17 +1,17 @@
|
||||||
#![cfg(all(feature = "python", feature = "pypi"))]
|
#![cfg(all(feature = "python", feature = "pypi"))]
|
||||||
|
|
||||||
use common::{uv_snapshot, TestContext};
|
use common::{uv_snapshot, TestContext};
|
||||||
use uv_toolchain::platform::{Arch, Os};
|
use uv_python::platform::{Arch, Os};
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn toolchain_find() {
|
fn python_find() {
|
||||||
let mut context: TestContext = TestContext::new_with_versions(&["3.11", "3.12"]);
|
let mut context: TestContext = TestContext::new_with_versions(&["3.11", "3.12"]);
|
||||||
|
|
||||||
// No interpreters on the path
|
// No interpreters on the path
|
||||||
if cfg!(windows) {
|
if cfg!(windows) {
|
||||||
uv_snapshot!(context.filters(), context.toolchain_find().env("UV_TEST_PYTHON_PATH", ""), @r###"
|
uv_snapshot!(context.filters(), context.python_find().env("UV_TEST_PYTHON_PATH", ""), @r###"
|
||||||
success: false
|
success: false
|
||||||
exit_code: 2
|
exit_code: 2
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -20,7 +20,7 @@ fn toolchain_find() {
|
||||||
error: No interpreter found in system path or `py` launcher
|
error: No interpreter found in system path or `py` launcher
|
||||||
"###);
|
"###);
|
||||||
} else {
|
} else {
|
||||||
uv_snapshot!(context.filters(), context.toolchain_find().env("UV_TEST_PYTHON_PATH", ""), @r###"
|
uv_snapshot!(context.filters(), context.python_find().env("UV_TEST_PYTHON_PATH", ""), @r###"
|
||||||
success: false
|
success: false
|
||||||
exit_code: 2
|
exit_code: 2
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -31,7 +31,7 @@ fn toolchain_find() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// We find the first interpreter on the path
|
// We find the first interpreter on the path
|
||||||
uv_snapshot!(context.filters(), context.toolchain_find(), @r###"
|
uv_snapshot!(context.filters(), context.python_find(), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -41,7 +41,7 @@ fn toolchain_find() {
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
// Request Python 3.12
|
// Request Python 3.12
|
||||||
uv_snapshot!(context.filters(), context.toolchain_find().arg("3.12"), @r###"
|
uv_snapshot!(context.filters(), context.python_find().arg("3.12"), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -51,7 +51,7 @@ fn toolchain_find() {
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
// Request Python 3.11
|
// Request Python 3.11
|
||||||
uv_snapshot!(context.filters(), context.toolchain_find().arg("3.11"), @r###"
|
uv_snapshot!(context.filters(), context.python_find().arg("3.11"), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -61,7 +61,7 @@ fn toolchain_find() {
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
// Request CPython
|
// Request CPython
|
||||||
uv_snapshot!(context.filters(), context.toolchain_find().arg("cpython"), @r###"
|
uv_snapshot!(context.filters(), context.python_find().arg("cpython"), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -71,7 +71,7 @@ fn toolchain_find() {
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
// Request CPython 3.12
|
// Request CPython 3.12
|
||||||
uv_snapshot!(context.filters(), context.toolchain_find().arg("cpython@3.12"), @r###"
|
uv_snapshot!(context.filters(), context.python_find().arg("cpython@3.12"), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -81,7 +81,7 @@ fn toolchain_find() {
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
// Request CPython 3.12 via partial key syntax
|
// Request CPython 3.12 via partial key syntax
|
||||||
uv_snapshot!(context.filters(), context.toolchain_find().arg("cpython-3.12"), @r###"
|
uv_snapshot!(context.filters(), context.python_find().arg("cpython-3.12"), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -94,7 +94,7 @@ fn toolchain_find() {
|
||||||
let os = Os::from_env();
|
let os = Os::from_env();
|
||||||
let arch = Arch::from_env();
|
let arch = Arch::from_env();
|
||||||
|
|
||||||
uv_snapshot!(context.filters(), context.toolchain_find()
|
uv_snapshot!(context.filters(), context.python_find()
|
||||||
.arg(format!("cpython-3.12-{os}-{arch}"))
|
.arg(format!("cpython-3.12-{os}-{arch}"))
|
||||||
, @r###"
|
, @r###"
|
||||||
success: true
|
success: true
|
||||||
|
@ -107,7 +107,7 @@ fn toolchain_find() {
|
||||||
|
|
||||||
// Request PyPy (which should be missing)
|
// Request PyPy (which should be missing)
|
||||||
if cfg!(windows) {
|
if cfg!(windows) {
|
||||||
uv_snapshot!(context.filters(), context.toolchain_find().arg("pypy"), @r###"
|
uv_snapshot!(context.filters(), context.python_find().arg("pypy"), @r###"
|
||||||
success: false
|
success: false
|
||||||
exit_code: 2
|
exit_code: 2
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -116,7 +116,7 @@ fn toolchain_find() {
|
||||||
error: No interpreter found for PyPy in system path or `py` launcher
|
error: No interpreter found for PyPy in system path or `py` launcher
|
||||||
"###);
|
"###);
|
||||||
} else {
|
} else {
|
||||||
uv_snapshot!(context.filters(), context.toolchain_find().arg("pypy"), @r###"
|
uv_snapshot!(context.filters(), context.python_find().arg("pypy"), @r###"
|
||||||
success: false
|
success: false
|
||||||
exit_code: 2
|
exit_code: 2
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -129,7 +129,7 @@ fn toolchain_find() {
|
||||||
// Swap the order of the Python versions
|
// Swap the order of the Python versions
|
||||||
context.python_versions.reverse();
|
context.python_versions.reverse();
|
||||||
|
|
||||||
uv_snapshot!(context.filters(), context.toolchain_find(), @r###"
|
uv_snapshot!(context.filters(), context.python_find(), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -139,7 +139,7 @@ fn toolchain_find() {
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
// Request Python 3.11
|
// Request Python 3.11
|
||||||
uv_snapshot!(context.filters(), context.toolchain_find().arg("3.11"), @r###"
|
uv_snapshot!(context.filters(), context.python_find().arg("3.11"), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue