diff --git a/crates/uv-distribution/src/metadata/lowering.rs b/crates/uv-distribution/src/metadata/lowering.rs index bd8f69971..b265c92b8 100644 --- a/crates/uv-distribution/src/metadata/lowering.rs +++ b/crates/uv-distribution/src/metadata/lowering.rs @@ -40,8 +40,6 @@ pub enum LoweringError { ForbiddenFragment(Url), #[error("`workspace = false` is not yet supported")] WorkspaceFalse, - #[error("`tool.uv.sources` is a preview feature; use `--preview` or set `UV_PREVIEW=1` to enable it")] - MissingPreview, #[error("Editable must refer to a local directory, not a file: `{0}`")] EditableFile(String), #[error(transparent)] // Function attaches the context @@ -95,7 +93,7 @@ pub(crate) fn lower_requirement( }; if preview.is_disabled() { - return Err(LoweringError::MissingPreview); + warn_user_once!("`uv.sources` is experimental and may change without warning."); } let source = match source { diff --git a/crates/uv/src/commands/project/add.rs b/crates/uv/src/commands/project/add.rs index 7eebc95dc..30e2d5366 100644 --- a/crates/uv/src/commands/project/add.rs +++ b/crates/uv/src/commands/project/add.rs @@ -1,19 +1,19 @@ use anyhow::{Context, Result}; + +use uv_cache::Cache; use uv_client::{BaseClientBuilder, Connectivity, FlatIndexClient, RegistryClientBuilder}; +use uv_configuration::{Concurrency, ExtrasSpecification, PreviewMode, SetupPyStrategy}; use uv_dispatch::BuildDispatch; use uv_distribution::pyproject::{Source, SourceError}; use uv_distribution::pyproject_mut::PyProjectTomlMut; +use uv_distribution::{DistributionDatabase, ProjectWorkspace, Workspace}; use uv_git::GitResolver; +use uv_normalize::PackageName; use uv_requirements::{NamedRequirementsResolver, RequirementsSource, RequirementsSpecification}; use uv_resolver::{FlatIndex, InMemoryIndex}; use uv_toolchain::{ToolchainPreference, ToolchainRequest}; use uv_types::{BuildIsolation, HashStrategy, InFlight}; - -use uv_cache::Cache; -use uv_configuration::{Concurrency, ExtrasSpecification, PreviewMode, SetupPyStrategy}; -use uv_distribution::{DistributionDatabase, ProjectWorkspace, Workspace}; -use uv_normalize::PackageName; -use uv_warnings::warn_user; +use uv_warnings::warn_user_once; use crate::commands::pip::operations::Modifications; use crate::commands::pip::resolution_environment; @@ -44,7 +44,7 @@ pub(crate) async fn add( printer: Printer, ) -> Result { if preview.is_disabled() { - warn_user!("`uv add` is experimental and may change without warning."); + warn_user_once!("`uv add` is experimental and may change without warning."); } // Find the project in the workspace. diff --git a/crates/uv/src/commands/project/lock.rs b/crates/uv/src/commands/project/lock.rs index b887761fe..da6ba310d 100644 --- a/crates/uv/src/commands/project/lock.rs +++ b/crates/uv/src/commands/project/lock.rs @@ -15,7 +15,7 @@ use uv_resolver::{ }; use uv_toolchain::{Interpreter, ToolchainPreference, ToolchainRequest}; use uv_types::{BuildIsolation, EmptyInstalledPackages, HashStrategy, InFlight}; -use uv_warnings::warn_user; +use uv_warnings::{warn_user, warn_user_once}; use crate::commands::project::{find_requires_python, ProjectError}; use crate::commands::{pip, project, ExitStatus}; @@ -36,7 +36,7 @@ pub(crate) async fn lock( printer: Printer, ) -> anyhow::Result { if preview.is_disabled() { - warn_user!("`uv lock` is experimental and may change without warning."); + warn_user_once!("`uv lock` is experimental and may change without warning."); } // Find the project requirements. diff --git a/crates/uv/src/commands/project/remove.rs b/crates/uv/src/commands/project/remove.rs index a245aea1e..03beeee8e 100644 --- a/crates/uv/src/commands/project/remove.rs +++ b/crates/uv/src/commands/project/remove.rs @@ -7,7 +7,7 @@ use uv_configuration::{Concurrency, ExtrasSpecification, PreviewMode}; use uv_distribution::pyproject_mut::PyProjectTomlMut; use uv_distribution::{ProjectWorkspace, Workspace}; use uv_toolchain::{ToolchainPreference, ToolchainRequest}; -use uv_warnings::warn_user; +use uv_warnings::{warn_user, warn_user_once}; use crate::commands::pip::operations::Modifications; use crate::commands::{project, ExitStatus}; @@ -30,7 +30,7 @@ pub(crate) async fn remove( printer: Printer, ) -> Result { if preview.is_disabled() { - warn_user!("`uv remove` is experimental and may change without warning."); + warn_user_once!("`uv remove` is experimental and may change without warning."); } // Find the project in the workspace. diff --git a/crates/uv/src/commands/project/run.rs b/crates/uv/src/commands/project/run.rs index e7194d2e3..ce5e0ee46 100644 --- a/crates/uv/src/commands/project/run.rs +++ b/crates/uv/src/commands/project/run.rs @@ -18,7 +18,7 @@ use uv_toolchain::{ EnvironmentPreference, Interpreter, PythonEnvironment, Toolchain, ToolchainPreference, ToolchainRequest, }; -use uv_warnings::warn_user; +use uv_warnings::warn_user_once; use crate::commands::pip::operations::Modifications; use crate::commands::{project, ExitStatus}; @@ -45,7 +45,7 @@ pub(crate) async fn run( printer: Printer, ) -> Result { if preview.is_disabled() { - warn_user!("`uv run` is experimental and may change without warning."); + warn_user_once!("`uv run` is experimental and may change without warning."); } // Discover and sync the base environment. diff --git a/crates/uv/src/commands/project/sync.rs b/crates/uv/src/commands/project/sync.rs index c8303cdc4..6bf101ab7 100644 --- a/crates/uv/src/commands/project/sync.rs +++ b/crates/uv/src/commands/project/sync.rs @@ -13,7 +13,7 @@ use uv_normalize::PackageName; use uv_resolver::{FlatIndex, InMemoryIndex, Lock}; use uv_toolchain::{PythonEnvironment, ToolchainPreference, ToolchainRequest}; use uv_types::{BuildIsolation, HashStrategy, InFlight}; -use uv_warnings::warn_user; +use uv_warnings::warn_user_once; use crate::commands::pip::operations::Modifications; use crate::commands::project::ProjectError; @@ -38,7 +38,7 @@ pub(crate) async fn sync( printer: Printer, ) -> Result { if preview.is_disabled() { - warn_user!("`uv sync` is experimental and may change without warning."); + warn_user_once!("`uv sync` is experimental and may change without warning."); } // Find the project requirements. diff --git a/crates/uv/src/commands/tool/install.rs b/crates/uv/src/commands/tool/install.rs index 521053023..d95971923 100644 --- a/crates/uv/src/commands/tool/install.rs +++ b/crates/uv/src/commands/tool/install.rs @@ -15,7 +15,7 @@ use uv_installer::SitePackages; use uv_requirements::RequirementsSource; use uv_tool::{entrypoint_paths, find_executable_directory, InstalledTools, Tool}; use uv_toolchain::{EnvironmentPreference, Toolchain, ToolchainPreference, ToolchainRequest}; -use uv_warnings::warn_user; +use uv_warnings::warn_user_once; use crate::commands::project::update_environment; use crate::commands::ExitStatus; @@ -39,7 +39,7 @@ pub(crate) async fn install( printer: Printer, ) -> Result { if preview.is_disabled() { - warn_user!("`uv tool install` is experimental and may change without warning."); + warn_user_once!("`uv tool install` is experimental and may change without warning."); } let installed_tools = InstalledTools::from_settings()?; diff --git a/crates/uv/src/commands/tool/run.rs b/crates/uv/src/commands/tool/run.rs index 619c8e686..e1ed923b7 100644 --- a/crates/uv/src/commands/tool/run.rs +++ b/crates/uv/src/commands/tool/run.rs @@ -13,7 +13,7 @@ use uv_requirements::RequirementsSource; use uv_toolchain::{ EnvironmentPreference, PythonEnvironment, Toolchain, ToolchainPreference, ToolchainRequest, }; -use uv_warnings::warn_user; +use uv_warnings::warn_user_once; use crate::commands::project::update_environment; use crate::commands::ExitStatus; @@ -38,7 +38,7 @@ pub(crate) async fn run( printer: Printer, ) -> Result { if preview.is_disabled() { - warn_user!("`uv tool run` is experimental and may change without warning."); + warn_user_once!("`uv tool run` is experimental and may change without warning."); } let (target, args) = command.split(); diff --git a/crates/uv/src/commands/toolchain/find.rs b/crates/uv/src/commands/toolchain/find.rs index 370e790f8..8f9d6ecaa 100644 --- a/crates/uv/src/commands/toolchain/find.rs +++ b/crates/uv/src/commands/toolchain/find.rs @@ -5,7 +5,7 @@ use uv_cache::Cache; use uv_configuration::PreviewMode; use uv_fs::Simplified; use uv_toolchain::{EnvironmentPreference, Toolchain, ToolchainPreference, ToolchainRequest}; -use uv_warnings::warn_user; +use uv_warnings::warn_user_once; use crate::commands::ExitStatus; use crate::printer::Printer; @@ -19,7 +19,7 @@ pub(crate) async fn find( printer: Printer, ) -> Result { if preview.is_disabled() { - warn_user!("`uv toolchain find` is experimental and may change without warning."); + warn_user_once!("`uv toolchain find` is experimental and may change without warning."); } let request = match request { diff --git a/crates/uv/src/commands/toolchain/install.rs b/crates/uv/src/commands/toolchain/install.rs index 63daafac6..d77b2a84e 100644 --- a/crates/uv/src/commands/toolchain/install.rs +++ b/crates/uv/src/commands/toolchain/install.rs @@ -9,7 +9,7 @@ use uv_fs::Simplified; use uv_toolchain::downloads::{self, DownloadResult, PythonDownload, PythonDownloadRequest}; use uv_toolchain::managed::{InstalledToolchain, InstalledToolchains}; use uv_toolchain::{requests_from_version_file, ToolchainRequest}; -use uv_warnings::warn_user; +use uv_warnings::warn_user_once; use crate::commands::ExitStatus; use crate::printer::Printer; @@ -25,7 +25,7 @@ pub(crate) async fn install( printer: Printer, ) -> Result { if preview.is_disabled() { - warn_user!("`uv toolchain install` is experimental and may change without warning."); + warn_user_once!("`uv toolchain install` is experimental and may change without warning."); } let start = std::time::Instant::now(); diff --git a/crates/uv/src/commands/toolchain/list.rs b/crates/uv/src/commands/toolchain/list.rs index 899d7cc6d..d9a144af6 100644 --- a/crates/uv/src/commands/toolchain/list.rs +++ b/crates/uv/src/commands/toolchain/list.rs @@ -11,7 +11,7 @@ use uv_toolchain::{ find_toolchains, DiscoveryError, EnvironmentPreference, Toolchain, ToolchainNotFound, ToolchainPreference, ToolchainRequest, ToolchainSource, }; -use uv_warnings::warn_user; +use uv_warnings::warn_user_once; use crate::commands::ExitStatus; use crate::printer::Printer; @@ -35,7 +35,7 @@ pub(crate) async fn list( printer: Printer, ) -> Result { if preview.is_disabled() { - warn_user!("`uv toolchain list` is experimental and may change without warning."); + warn_user_once!("`uv toolchain list` is experimental and may change without warning."); } let download_request = match kinds { diff --git a/crates/uv/tests/pip_install.rs b/crates/uv/tests/pip_install.rs index 52b6c4029..175b8aabe 100644 --- a/crates/uv/tests/pip_install.rs +++ b/crates/uv/tests/pip_install.rs @@ -5485,26 +5485,27 @@ fn tool_uv_sources_is_in_preview() -> Result<()> { name = "foo" version = "0.0.0" dependencies = [ - "tqdm>4,<=5", + "iniconfig>1,<=2", ] [tool.uv.sources] - tqdm = { url = "https://files.pythonhosted.org/packages/a5/d6/502a859bac4ad5e274255576cd3e15ca273cdb91731bc39fb840dd422ee9/tqdm-4.66.0-py3-none-any.whl" } + iniconfig = { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl" } "#})?; // Install the editable packages. - uv_snapshot!(context.filters(), windows_filters=false, context.pip_install() + uv_snapshot!(context.filters(), context.pip_install() .arg("-r") - .arg("pyproject.toml") - .arg("--extra") - .arg("utils"), @r###" - success: false - exit_code: 2 + .arg("pyproject.toml"), @r###" + success: true + exit_code: 0 ----- stdout ----- ----- stderr ----- - error: Failed to parse entry for: `tqdm` - Caused by: `tool.uv.sources` is a preview feature; use `--preview` or set `UV_PREVIEW=1` to enable it + warning: `uv.sources` is experimental and may change without warning. + Resolved 1 package in [TIME] + Prepared 1 package in [TIME] + Installed 1 package in [TIME] + + iniconfig==2.0.0 (from https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl) "### );