Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions crates/uv-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6032,6 +6032,12 @@ pub struct PythonFindArgs {
/// Show the Python version that would be used instead of the path to the interpreter.
#[arg(long)]
pub show_version: bool,

/// URL pointing to JSON of custom Python installations.
///
/// Note that currently, only local paths are supported.
#[arg(long)]
pub python_downloads_json_url: Option<String>,
}

#[derive(Args)]
Expand Down
15 changes: 12 additions & 3 deletions crates/uv-python/src/installation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,13 @@ impl PythonInstallation {
request: &PythonRequest,
environments: EnvironmentPreference,
preference: PythonPreference,
python_downloads_json_url: Option<&str>,
cache: &Cache,
preview: Preview,
) -> Result<Self, Error> {
let installation =
find_python_installation(request, environments, preference, cache, preview)??;
installation.warn_if_outdated_prerelease(request, None);
installation.warn_if_outdated_prerelease(request, python_downloads_json_url);
Ok(installation)
}

Expand All @@ -74,12 +75,13 @@ impl PythonInstallation {
request: &PythonRequest,
environments: EnvironmentPreference,
preference: PythonPreference,
python_downloads_json_url: Option<&str>,
cache: &Cache,
preview: Preview,
) -> Result<Self, Error> {
let installation =
find_best_python_installation(request, environments, preference, cache, preview)??;
installation.warn_if_outdated_prerelease(request, None);
installation.warn_if_outdated_prerelease(request, python_downloads_json_url);
Ok(installation)
}

Expand All @@ -102,7 +104,14 @@ impl PythonInstallation {
let request = request.unwrap_or(&PythonRequest::Default);

// Search for the installation
let err = match Self::find(request, environments, preference, cache, preview) {
let err = match Self::find(
request,
environments,
preference,
python_downloads_json_url,
cache,
preview,
) {
Ok(installation) => return Ok(installation),
Err(err) => err,
};
Expand Down
4 changes: 4 additions & 0 deletions crates/uv/src/commands/pip/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ use uv_resolver::{
InMemoryIndex, OptionsBuilder, PrereleaseMode, PylockToml, PythonRequirement, ResolutionMode,
ResolverEnvironment,
};
use uv_settings::PythonInstallMirrors;
use uv_static::EnvVars;
use uv_torch::{TorchMode, TorchSource, TorchStrategy};
use uv_types::{EmptyInstalledPackages, HashStrategy};
Expand Down Expand Up @@ -102,6 +103,7 @@ pub(crate) async fn pip_compile(
extra_build_dependencies: &ExtraBuildDependencies,
extra_build_variables: &ExtraBuildVariables,
build_options: BuildOptions,
install_mirrors: PythonInstallMirrors,
mut python_version: Option<PythonVersion>,
python_platform: Option<TargetTriple>,
universal: bool,
Expand Down Expand Up @@ -296,6 +298,7 @@ pub(crate) async fn pip_compile(
&request,
environment_preference,
python_preference,
install_mirrors.python_downloads_json_url.as_deref(),
&cache,
preview,
)
Expand All @@ -312,6 +315,7 @@ pub(crate) async fn pip_compile(
&request,
environment_preference,
python_preference,
install_mirrors.python_downloads_json_url.as_deref(),
&cache,
preview,
)
Expand Down
2 changes: 2 additions & 0 deletions crates/uv/src/commands/python/find.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub(crate) async fn find(
no_config: bool,
system: bool,
python_preference: PythonPreference,
python_downloads_json_url: Option<&str>,
cache: &Cache,
printer: Printer,
preview: Preview,
Expand Down Expand Up @@ -78,6 +79,7 @@ pub(crate) async fn find(
&python_request.unwrap_or_default(),
environment_preference,
python_preference,
python_downloads_json_url,
cache,
preview,
)?;
Expand Down
3 changes: 3 additions & 0 deletions crates/uv/src/commands/python/pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ pub(crate) async fn pin(
pin,
virtual_project,
python_preference,
install_mirrors.python_downloads_json_url.as_deref(),
cache,
preview,
);
Expand Down Expand Up @@ -264,6 +265,7 @@ fn warn_if_existing_pin_incompatible_with_project(
pin: &PythonRequest,
virtual_project: &VirtualProject,
python_preference: PythonPreference,
python_downloads_json_url: Option<&str>,
cache: &Cache,
preview: Preview,
) {
Expand All @@ -289,6 +291,7 @@ fn warn_if_existing_pin_incompatible_with_project(
pin,
EnvironmentPreference::OnlySystem,
python_preference,
python_downloads_json_url,
cache,
preview,
) {
Expand Down
4 changes: 3 additions & 1 deletion crates/uv/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
&args.settings.extra_build_dependencies,
&args.settings.extra_build_variables,
args.settings.build_options,
args.settings.install_mirrors,
args.settings.python_version,
args.settings.python_platform,
args.settings.universal,
Expand Down Expand Up @@ -1614,7 +1615,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
command: PythonCommand::Find(args),
}) => {
// Resolve the settings from the command-line arguments and workspace configuration.
let args = settings::PythonFindSettings::resolve(args, filesystem);
let args = settings::PythonFindSettings::resolve(args, filesystem, environment);

// Initialize the cache.
let cache = cache.init()?;
Expand All @@ -1641,6 +1642,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
cli.top_level.no_config,
args.system,
globals.python_preference,
args.python_downloads_json_url.as_deref(),
&cache,
printer,
globals.preview,
Expand Down
26 changes: 25 additions & 1 deletion crates/uv/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1235,26 +1235,50 @@ pub(crate) struct PythonFindSettings {
pub(crate) show_version: bool,
pub(crate) no_project: bool,
pub(crate) system: bool,
pub(crate) python_downloads_json_url: Option<String>,
}

impl PythonFindSettings {
/// Resolve the [`PythonFindSettings`] from the CLI and workspace configuration.
#[allow(clippy::needless_pass_by_value)]
pub(crate) fn resolve(args: PythonFindArgs, _filesystem: Option<FilesystemOptions>) -> Self {
pub(crate) fn resolve(
args: PythonFindArgs,
filesystem: Option<FilesystemOptions>,
environment: EnvironmentOptions,
) -> Self {
let PythonFindArgs {
request,
show_version,
no_project,
system,
no_system,
script: _,
python_downloads_json_url,
} = args;

let filesystem_install_mirrors = filesystem
.map(|fs| fs.install_mirrors.clone())
.unwrap_or_default();

let install_mirrors = PythonInstallMirrors {
python_downloads_json_url,
..Default::default()
}
.combine(environment.install_mirrors)
.combine(filesystem_install_mirrors);

let PythonInstallMirrors {
python_install_mirror: _,
pypy_install_mirror: _,
python_downloads_json_url,
} = install_mirrors;

Self {
request,
show_version,
no_project,
system: flag(system, no_system, "system").unwrap_or_default(),
python_downloads_json_url,
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions crates/uv/tests/it/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,7 @@ impl TestContext {
.iter()
.map(|version| PythonVersion::from_str(version).unwrap())
.zip(
python_installations_for_versions(&temp_dir, python_versions)
python_installations_for_versions(&temp_dir, python_versions, None)
.expect("Failed to find test Python versions"),
)
.collect();
Expand Down Expand Up @@ -1689,7 +1689,7 @@ pub fn python_path_with_versions(
python_versions: &[&str],
) -> anyhow::Result<OsString> {
Ok(env::join_paths(
python_installations_for_versions(temp_dir, python_versions)?
python_installations_for_versions(temp_dir, python_versions, None)?
.into_iter()
.map(|path| path.parent().unwrap().to_path_buf()),
)?)
Expand All @@ -1701,6 +1701,7 @@ pub fn python_path_with_versions(
pub fn python_installations_for_versions(
temp_dir: &ChildPath,
python_versions: &[&str],
python_downloads_json_url: Option<&str>,
) -> anyhow::Result<Vec<PathBuf>> {
let cache = Cache::from_path(temp_dir.child("cache").to_path_buf()).init()?;
let selected_pythons = python_versions
Expand All @@ -1710,6 +1711,7 @@ pub fn python_installations_for_versions(
&PythonRequest::parse(python_version),
EnvironmentPreference::OnlySystem,
PythonPreference::Managed,
python_downloads_json_url,
&cache,
Preview::default(),
) {
Expand Down
4 changes: 3 additions & 1 deletion docs/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -3686,7 +3686,9 @@ uv python find [OPTIONS] [REQUEST]
<p>Other command-line arguments (such as relative paths) will be resolved relative to the current working directory.</p>
<p>See <code>--directory</code> to change the working directory entirely.</p>
<p>This setting has no effect when used in the <code>uv pip</code> interface.</p>
<p>May also be set with the <code>UV_PROJECT</code> environment variable.</p></dd><dt id="uv-python-find--quiet"><a href="#uv-python-find--quiet"><code>--quiet</code></a>, <code>-q</code></dt><dd><p>Use quiet output.</p>
<p>May also be set with the <code>UV_PROJECT</code> environment variable.</p></dd><dt id="uv-python-find--python-downloads-json-url"><a href="#uv-python-find--python-downloads-json-url"><code>--python-downloads-json-url</code></a> <i>python-downloads-json-url</i></dt><dd><p>URL pointing to JSON of custom Python installations.</p>
<p>Note that currently, only local paths are supported.</p>
</dd><dt id="uv-python-find--quiet"><a href="#uv-python-find--quiet"><code>--quiet</code></a>, <code>-q</code></dt><dd><p>Use quiet output.</p>
<p>Repeating this option, e.g., <code>-qq</code>, will enable a silent mode in which uv will write no output to stdout.</p>
</dd><dt id="uv-python-find--script"><a href="#uv-python-find--script"><code>--script</code></a> <i>script</i></dt><dd><p>Find the environment for a Python script, rather than the current project</p>
</dd><dt id="uv-python-find--show-version"><a href="#uv-python-find--show-version"><code>--show-version</code></a></dt><dd><p>Show the Python version that would be used instead of the path to the interpreter</p>
Expand Down
Loading