Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't recommend --prerelease=allow during build requirement resolution errors #8192

Merged
merged 1 commit into from
Oct 15, 2024
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
5 changes: 3 additions & 2 deletions crates/uv-dispatch/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ use uv_installer::{Installer, Plan, Planner, Preparer, SitePackages};
use uv_pypi_types::Requirement;
use uv_python::{Interpreter, PythonEnvironment};
use uv_resolver::{
ExcludeNewer, FlatIndex, InMemoryIndex, Manifest, OptionsBuilder, PythonRequirement, Resolver,
ResolverMarkers,
ExcludeNewer, FlatIndex, Flexibility, InMemoryIndex, Manifest, OptionsBuilder,
PythonRequirement, Resolver, ResolverMarkers,
};
use uv_types::{BuildContext, BuildIsolation, EmptyInstalledPackages, HashStrategy, InFlight};

Expand Down Expand Up @@ -170,6 +170,7 @@ impl<'a> BuildContext for BuildDispatch<'a> {
OptionsBuilder::new()
.exclude_newer(self.exclude_newer)
.index_strategy(self.index_strategy)
.flexibility(Flexibility::Fixed)
.build(),
&python_requirement,
ResolverMarkers::specific_environment(markers),
Expand Down
5 changes: 5 additions & 0 deletions crates/uv-resolver/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::pubgrub::{
use crate::python_requirement::PythonRequirement;
use crate::resolution::ConflictingDistributionError;
use crate::resolver::{IncompletePackage, ResolverMarkers, UnavailablePackage, UnavailableReason};
use crate::Options;
use tracing::trace;
use uv_distribution_types::{BuiltDist, IndexLocations, IndexUrl, InstalledDist, SourceDist};
use uv_normalize::PackageName;
Expand Down Expand Up @@ -117,6 +118,7 @@ pub struct NoSolutionError {
fork_urls: ForkUrls,
markers: ResolverMarkers,
workspace_members: BTreeSet<PackageName>,
options: Options,
}

impl NoSolutionError {
Expand All @@ -133,6 +135,7 @@ impl NoSolutionError {
fork_urls: ForkUrls,
markers: ResolverMarkers,
workspace_members: BTreeSet<PackageName>,
options: Options,
) -> Self {
Self {
error,
Expand All @@ -146,6 +149,7 @@ impl NoSolutionError {
fork_urls,
markers,
workspace_members,
options,
}
}

Expand Down Expand Up @@ -250,6 +254,7 @@ impl std::fmt::Display for NoSolutionError {
&self.fork_urls,
&self.markers,
&self.workspace_members,
self.options,
&mut additional_hints,
);
for hint in additional_hints {
Expand Down
2 changes: 1 addition & 1 deletion crates/uv-resolver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub use lock::{
Lock, LockError, RequirementsTxtExport, ResolverManifest, SatisfiesResult, TreeDisplay,
};
pub use manifest::Manifest;
pub use options::{Options, OptionsBuilder};
pub use options::{Flexibility, Options, OptionsBuilder};
pub use preferences::{Preference, PreferenceError, Preferences};
pub use prerelease::PrereleaseMode;
pub use pubgrub::{PubGrubSpecifier, PubGrubSpecifierError};
Expand Down
24 changes: 23 additions & 1 deletion crates/uv-resolver/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ use uv_configuration::IndexStrategy;
use crate::{DependencyMode, ExcludeNewer, PrereleaseMode, ResolutionMode};

/// Options for resolving a manifest.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, serde::Deserialize)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub struct Options {
pub resolution_mode: ResolutionMode,
pub prerelease_mode: PrereleaseMode,
pub dependency_mode: DependencyMode,
pub exclude_newer: Option<ExcludeNewer>,
pub index_strategy: IndexStrategy,
pub flexibility: Flexibility,
}

/// Builder for [`Options`].
Expand All @@ -20,6 +21,7 @@ pub struct OptionsBuilder {
dependency_mode: DependencyMode,
exclude_newer: Option<ExcludeNewer>,
index_strategy: IndexStrategy,
flexibility: Flexibility,
}

impl OptionsBuilder {
Expand Down Expand Up @@ -63,6 +65,13 @@ impl OptionsBuilder {
self
}

/// Sets the [`Flexibility`].
#[must_use]
pub fn flexibility(mut self, flexibility: Flexibility) -> Self {
self.flexibility = flexibility;
self
}

/// Builds the options.
pub fn build(self) -> Options {
Options {
Expand All @@ -71,6 +80,19 @@ impl OptionsBuilder {
dependency_mode: self.dependency_mode,
exclude_newer: self.exclude_newer,
index_strategy: self.index_strategy,
flexibility: self.flexibility,
}
}
}

/// Whether the [`Options`] are configurable or fixed.
///
/// Applies to the [`ResolutionMode`], [`PrereleaseMode`], and [`DependencyMode`] fields.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum Flexibility {
/// The setting is configurable.
#[default]
Configurable,
/// The setting is fixed.
Fixed,
}
44 changes: 26 additions & 18 deletions crates/uv-resolver/src/pubgrub/report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::fork_urls::ForkUrls;
use crate::prerelease::AllowPrerelease;
use crate::python_requirement::{PythonRequirement, PythonRequirementSource};
use crate::resolver::{IncompletePackage, UnavailablePackage, UnavailableReason};
use crate::{RequiresPython, ResolverMarkers};
use crate::{Flexibility, Options, RequiresPython, ResolverMarkers};

use super::{PubGrubPackage, PubGrubPackageInner, PubGrubPython};

Expand Down Expand Up @@ -511,6 +511,7 @@ impl PubGrubReportFormatter<'_> {
fork_urls: &ForkUrls,
markers: &ResolverMarkers,
workspace_members: &BTreeSet<PackageName>,
options: Options,
output_hints: &mut IndexSet<PubGrubHint>,
) {
match derivation_tree {
Expand All @@ -519,15 +520,17 @@ impl PubGrubReportFormatter<'_> {
) => {
if let PubGrubPackageInner::Package { name, .. } = &**package {
// Check for no versions due to pre-release options.
if !fork_urls.contains_key(name) {
self.prerelease_available_hint(
package,
name,
set,
selector,
markers,
output_hints,
);
if options.flexibility == Flexibility::Configurable {
if !fork_urls.contains_key(name) {
self.prerelease_available_hint(
package,
name,
set,
selector,
markers,
output_hints,
);
}
}

// Check for no versions due to no `--find-links` flat index.
Expand Down Expand Up @@ -592,6 +595,7 @@ impl PubGrubReportFormatter<'_> {
fork_urls,
markers,
workspace_members,
options,
output_hints,
);
self.generate_hints(
Expand All @@ -604,6 +608,7 @@ impl PubGrubReportFormatter<'_> {
fork_urls,
markers,
workspace_members,
options,
output_hints,
);
}
Expand Down Expand Up @@ -995,29 +1000,32 @@ impl std::fmt::Display for PubGrubHint {
Self::PrereleaseAvailable { package, version } => {
write!(
f,
"{}{} Pre-releases are available for {} in the requested range (e.g., {}), but pre-releases weren't enabled (try: `--prerelease=allow`)",
"{}{} Pre-releases are available for {} in the requested range (e.g., {}), but pre-releases weren't enabled (try: `{}`)",
"hint".bold().cyan(),
":".bold(),
package.bold(),
version.bold()
version.bold(),
"--prerelease=allow".green(),
)
}
Self::PrereleaseRequested { package, range } => {
write!(
f,
"{}{} {} was requested with a pre-release marker (e.g., {}), but pre-releases weren't enabled (try: `--prerelease=allow`)",
"{}{} {} was requested with a pre-release marker (e.g., {}), but pre-releases weren't enabled (try: `{}`)",
"hint".bold().cyan(),
":".bold(),
package.bold(),
PackageRange::compatibility(package, range, None).bold()
PackageRange::compatibility(package, range, None).bold(),
"--prerelease=allow".green(),
)
}
Self::NoIndex => {
write!(
f,
"{}{} Packages were unavailable because index lookups were disabled and no additional package locations were provided (try: `--find-links <uri>`)",
"{}{} Packages were unavailable because index lookups were disabled and no additional package locations were provided (try: `{}`)",
"hint".bold().cyan(),
":".bold(),
"--find-links <uri>".green(),
)
}
Self::Offline => {
Expand Down Expand Up @@ -1183,8 +1191,8 @@ impl std::fmt::Display for PubGrubHint {
"{}{} The package `{}` depends on the package `{}` but the name is shadowed by {your_project}. Consider changing the name of {the_project}.",
"hint".bold().cyan(),
":".bold(),
package,
dependency,
package.bold(),
dependency.bold(),
)
}
Self::UncheckedIndex {
Expand All @@ -1198,7 +1206,7 @@ impl std::fmt::Display for PubGrubHint {
"{}{} `{}` was found on {}, but not at the requested version ({}). A compatible version may be available on a subsequent index (e.g., {}). By default, uv will only consider versions that are published on the first index that contains a given package, to avoid dependency confusion attacks. If all indexes are equally trusted, use `{}` to consider all versions from all indexes, regardless of the order in which they were defined.",
"hint".bold().cyan(),
":".bold(),
package,
package.bold(),
found_index.cyan(),
PackageRange::compatibility(package, range, None).cyan(),
next_index.cyan(),
Expand Down
1 change: 1 addition & 0 deletions crates/uv-resolver/src/resolver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1989,6 +1989,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
fork_urls,
markers,
self.workspace_members.clone(),
self.options,
))
}

Expand Down
4 changes: 2 additions & 2 deletions crates/uv/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -966,7 +966,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
// Initialize the cache.
let cache = cache.init()?.with_refresh(Refresh::All(Timestamp::now()));

commands::tool_upgrade(
Box::pin(commands::tool_upgrade(
args.name,
args.python,
globals.connectivity,
Expand All @@ -978,7 +978,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
globals.native_tls,
&cache,
printer,
)
))
.await
}
Commands::Tool(ToolNamespace {
Expand Down
37 changes: 37 additions & 0 deletions crates/uv/tests/it/pip_install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2243,6 +2243,43 @@ fn only_binary_editable_setup_py() {
);
}

/// We should not recommend `--prerelease=allow` in source distribution build failures, since we
/// don't propagate the `--prerelease` flag to the source distribution build regardless.
#[test]
fn no_prerelease_hint_source_builds() -> Result<()> {
let context = TestContext::new("3.12");

let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(indoc! {r#"
[project]
name = "project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = []
[build-system]
requires = ["setuptools>=40.8.0"]
build-backend = "setuptools.build_meta"
"#})?;

uv_snapshot!(context.filters(), context.pip_install().arg(".").env("UV_EXCLUDE_NEWER", "2018-10-08"), @r###"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
Resolved 1 package in [TIME]
error: Failed to prepare distributions
Caused by: Failed to fetch wheel: project @ file://[TEMP_DIR]/
Caused by: Failed to resolve requirements from `setup.py` build
Caused by: No solution found when resolving: `setuptools>=40.8.0`
Caused by: Because only setuptools<40.8.0 is available and you require setuptools>=40.8.0, we can conclude that your requirements are unsatisfiable.
"###
);

Ok(())
}

#[test]
fn cache_priority() {
let context = TestContext::new("3.12");
Expand Down
Loading