Skip to content

Commit a56a2d4

Browse files
committed
Remove plural from unavailable package
1 parent d663d8f commit a56a2d4

File tree

6 files changed

+65
-87
lines changed

6 files changed

+65
-87
lines changed

crates/uv-resolver/src/pubgrub/report.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,19 @@ impl ReportFormatter<PubGrubPackage, Range<Version>, UnavailableReason>
114114
PubGrubPackage::Root(None) => {
115115
format!("your requirements cannot be used because {reason}")
116116
}
117-
_ => {
118-
format!(
119-
"{}{reason}",
120-
Padded::new("", &PackageRange::compatibility(package, set), " ")
121-
)
122-
}
117+
_ => match reason {
118+
UnavailableReason::Package(reason) => {
119+
// While there may be a term attached, this error applies to the entire
120+
// package, so we show it for the entire package
121+
format!("{}{reason}", Padded::new("", &package, " "))
122+
}
123+
UnavailableReason::Version(reason) => {
124+
format!(
125+
"{}{reason}",
126+
Padded::new("", &PackageRange::compatibility(package, set), " ")
127+
)
128+
}
129+
},
123130
},
124131
External::FromDependencyOf(package, package_set, dependency, dependency_set) => {
125132
let package_set = self.simplify_set(package_set, package);

crates/uv-resolver/src/resolver/mod.rs

Lines changed: 30 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ use itertools::Itertools;
1414
use pubgrub::error::PubGrubError;
1515
use pubgrub::range::Range;
1616
use pubgrub::solver::{Incompatibility, State};
17-
use pubgrub::term::Term;
1817
use rustc_hash::{FxHashMap, FxHashSet};
1918
use tokio_stream::wrappers::ReceiverStream;
2019
use tracing::{debug, enabled, info_span, instrument, trace, warn, Instrument, Level};
@@ -69,58 +68,22 @@ mod urls;
6968

7069
/// The reason why a package or a version cannot be used.
7170
#[derive(Debug, Clone, Eq, PartialEq)]
72-
pub(crate) struct UnavailableReason {
73-
term: Term<Range<Version>>,
74-
reason: UnavailableMetadataTypes,
75-
}
76-
77-
impl UnavailableReason {
78-
/// Returns a boolean indicating if the predicate following this package range should
79-
/// be singular or plural e.g. if false use "<range> has <...>" and
80-
/// if true use "<range> have <...>"
81-
fn plural(&self) -> bool {
82-
self.term == Term::Positive(Range::full())
83-
}
71+
pub(crate) enum UnavailableReason {
72+
/// The entire package cannot be used.
73+
Package(UnavailablePackage),
74+
/// A single version cannot be used.
75+
Version(UnavailableVersion),
8476
}
8577

8678
impl Display for UnavailableReason {
8779
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
88-
match &self.reason {
89-
UnavailableMetadataTypes::Version(version) => Display::fmt(version, f),
90-
UnavailableMetadataTypes::Package(package) => match package {
91-
UnavailablePackage::NoIndex => {
92-
f.write_str(if self.plural() { "were" } else { "was" })?;
93-
f.write_str(" not found in the provided package locations")
94-
}
95-
UnavailablePackage::Offline => {
96-
f.write_str(if self.plural() { "were" } else { "was" })?;
97-
f.write_str(" not found in the cache")
98-
}
99-
UnavailablePackage::NotFound => {
100-
f.write_str(if self.plural() { "were" } else { "was" })?;
101-
f.write_str(" not found in the package registry")
102-
}
103-
UnavailablePackage::InvalidMetadata(_) => {
104-
f.write_str(if self.plural() { "have" } else { "has" })?;
105-
f.write_str(" invalid metadata")
106-
}
107-
UnavailablePackage::InvalidStructure(_) => {
108-
f.write_str(if self.plural() { "have" } else { "has" })?;
109-
f.write_str(" an invalid package format")
110-
}
111-
},
80+
match self {
81+
Self::Version(version) => Display::fmt(version, f),
82+
Self::Package(package) => Display::fmt(package, f),
11283
}
11384
}
11485
}
11586

116-
#[derive(Debug, Clone, Eq, PartialEq)]
117-
pub(crate) enum UnavailableMetadataTypes {
118-
/// The entire package cannot be used.
119-
Package(UnavailablePackage),
120-
/// A single version cannot be used.
121-
Version(UnavailableVersion),
122-
}
123-
12487
/// The package version is unavailable and cannot be used. Unlike [`PackageUnavailable`], this
12588
/// applies to a single version of the package.
12689
///
@@ -172,6 +135,24 @@ pub(crate) enum UnavailablePackage {
172135
InvalidStructure(String),
173136
}
174137

138+
impl UnavailablePackage {
139+
pub(crate) fn as_str(&self) -> &'static str {
140+
match self {
141+
UnavailablePackage::NoIndex => "was not found in the provided package locations",
142+
UnavailablePackage::Offline => "was not found in the cache",
143+
UnavailablePackage::NotFound => "was not found in the package registry",
144+
UnavailablePackage::InvalidMetadata(_) => "has invalid metadata",
145+
UnavailablePackage::InvalidStructure(_) => "has an invalid package format",
146+
}
147+
}
148+
}
149+
150+
impl Display for UnavailablePackage {
151+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
152+
f.write_str(self.as_str())
153+
}
154+
}
155+
175156
/// The package is unavailable at specific versions.
176157
#[derive(Debug, Clone)]
177158
pub(crate) enum IncompletePackage {
@@ -444,15 +425,11 @@ impl<'a, Provider: ResolverProvider, InstalledPackages: InstalledPackagesProvide
444425

445426
// Check if the decision was due to the package being unavailable
446427
if let PubGrubPackage::Package(ref package_name, _, _) = next {
447-
if let Some(entry) = self.unavailable_packages.borrow()
448-
.get(package_name) {
428+
if let Some(entry) = self.unavailable_packages.borrow().get(package_name) {
449429
state.add_incompatibility(Incompatibility::custom_term(
450430
next.clone(),
451431
term_intersection.clone(),
452-
UnavailableReason {
453-
term: term_intersection.clone(),
454-
reason: UnavailableMetadataTypes::Package(entry.clone()),
455-
},
432+
UnavailableReason::Package(entry.clone()),
456433
));
457434
continue;
458435
}
@@ -500,10 +477,7 @@ impl<'a, Provider: ResolverProvider, InstalledPackages: InstalledPackagesProvide
500477
state.add_incompatibility(Incompatibility::custom_version(
501478
next.clone(),
502479
version.clone(),
503-
UnavailableReason {
504-
term: term_intersection.clone(),
505-
reason: UnavailableMetadataTypes::Version(reason),
506-
},
480+
UnavailableReason::Version(reason),
507481
));
508482
continue;
509483
}
@@ -537,10 +511,7 @@ impl<'a, Provider: ResolverProvider, InstalledPackages: InstalledPackagesProvide
537511
state.add_incompatibility(Incompatibility::custom_version(
538512
package.clone(),
539513
version.clone(),
540-
UnavailableReason {
541-
term: term_intersection.clone(),
542-
reason: UnavailableMetadataTypes::Version(reason),
543-
},
514+
UnavailableReason::Version(reason),
544515
));
545516
continue;
546517
}

crates/uv/tests/pip_compile.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4560,7 +4560,7 @@ fn no_index_requirements_txt() -> Result<()> {
45604560
45614561
----- stderr -----
45624562
× No solution found when resolving dependencies:
4563-
╰─▶ Because all versions of tqdm were not found in the provided package locations and you require tqdm, we can conclude that the requirements are unsatisfiable.
4563+
╰─▶ Because tqdm was not found in the provided package locations and you require tqdm, we can conclude that the requirements are unsatisfiable.
45644564
45654565
hint: Packages were unavailable because index lookups were disabled and no additional package locations were provided (try: `--find-links <uri>`)
45664566
"###
@@ -4668,7 +4668,7 @@ fn offline_registry() -> Result<()> {
46684668
46694669
----- stderr -----
46704670
× No solution found when resolving dependencies:
4671-
╰─▶ Because black==23.10.1 was not found in the cache and you require black==23.10.1, we can conclude that the requirements are unsatisfiable.
4671+
╰─▶ Because black was not found in the cache and you require black==23.10.1, we can conclude that the requirements are unsatisfiable.
46724672
46734673
hint: Packages were unavailable because the network was disabled
46744674
"###
@@ -4795,7 +4795,7 @@ fn offline_find_links() -> Result<()> {
47954795
47964796
----- stderr -----
47974797
× No solution found when resolving dependencies:
4798-
╰─▶ Because all versions of tqdm were not found in the cache and you require tqdm, we can conclude that the requirements are unsatisfiable.
4798+
╰─▶ Because tqdm was not found in the cache and you require tqdm, we can conclude that the requirements are unsatisfiable.
47994799
48004800
hint: Packages were unavailable because the network was disabled
48014801
"###
@@ -4814,7 +4814,7 @@ fn offline_find_links() -> Result<()> {
48144814
48154815
----- stderr -----
48164816
× No solution found when resolving dependencies:
4817-
╰─▶ Because all versions of tqdm were not found in the cache and you require tqdm, we can conclude that the requirements are unsatisfiable.
4817+
╰─▶ Because tqdm was not found in the cache and you require tqdm, we can conclude that the requirements are unsatisfiable.
48184818
48194819
hint: Packages were unavailable because the network was disabled
48204820
"###
@@ -5171,7 +5171,7 @@ fn index_url_in_requirements() -> Result<()> {
51715171
51725172
----- stderr -----
51735173
× No solution found when resolving dependencies:
5174-
╰─▶ Because anyio<4 was not found in the package registry and you require anyio<4, we can conclude that the requirements are unsatisfiable.
5174+
╰─▶ Because anyio was not found in the package registry and you require anyio<4, we can conclude that the requirements are unsatisfiable.
51755175
"###
51765176
);
51775177

crates/uv/tests/pip_install.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -994,7 +994,7 @@ fn install_no_index() {
994994
995995
----- stderr -----
996996
× No solution found when resolving dependencies:
997-
╰─▶ Because all versions of flask were not found in the provided package locations and you require flask, we can conclude that the requirements are unsatisfiable.
997+
╰─▶ Because flask was not found in the provided package locations and you require flask, we can conclude that the requirements are unsatisfiable.
998998
999999
hint: Packages were unavailable because index lookups were disabled and no additional package locations were provided (try: `--find-links <uri>`)
10001000
"###
@@ -1018,7 +1018,7 @@ fn install_no_index_version() {
10181018
10191019
----- stderr -----
10201020
× No solution found when resolving dependencies:
1021-
╰─▶ Because flask==3.0.0 was not found in the provided package locations and you require flask==3.0.0, we can conclude that the requirements are unsatisfiable.
1021+
╰─▶ Because flask was not found in the provided package locations and you require flask==3.0.0, we can conclude that the requirements are unsatisfiable.
10221022
10231023
hint: Packages were unavailable because index lookups were disabled and no additional package locations were provided (try: `--find-links <uri>`)
10241024
"###
@@ -3564,7 +3564,7 @@ fn reinstall_no_index() {
35643564
35653565
----- stderr -----
35663566
× No solution found when resolving dependencies:
3567-
╰─▶ Because all versions of anyio were not found in the provided package locations and you require anyio, we can conclude that the requirements are unsatisfiable.
3567+
╰─▶ Because anyio was not found in the provided package locations and you require anyio, we can conclude that the requirements are unsatisfiable.
35683568
35693569
hint: Packages were unavailable because index lookups were disabled and no additional package locations were provided (try: `--find-links <uri>`)
35703570
"###
@@ -3682,7 +3682,7 @@ fn already_installed_dependent_editable() {
36823682
36833683
----- stderr -----
36843684
× No solution found when resolving dependencies:
3685-
╰─▶ Because all versions of first-editable were not found in the provided package locations and second-editable==0.0.1 depends on first-editable, we can conclude that second-editable==0.0.1 cannot be used.
3685+
╰─▶ Because first-editable was not found in the provided package locations and second-editable==0.0.1 depends on first-editable, we can conclude that second-editable==0.0.1 cannot be used.
36863686
And because only second-editable==0.0.1 is available and you require second-editable, we can conclude that the requirements are unsatisfiable.
36873687
"###
36883688
);
@@ -3778,7 +3778,7 @@ fn already_installed_local_path_dependent() {
37783778
37793779
----- stderr -----
37803780
× No solution found when resolving dependencies:
3781-
╰─▶ Because all versions of first-local were not found in the provided package locations and second-local==0.1.0 depends on first-local, we can conclude that second-local==0.1.0 cannot be used.
3781+
╰─▶ Because first-local was not found in the provided package locations and second-local==0.1.0 depends on first-local, we can conclude that second-local==0.1.0 cannot be used.
37823782
And because only second-local==0.1.0 is available and you require second-local, we can conclude that the requirements are unsatisfiable.
37833783
"###
37843784
);
@@ -3818,7 +3818,7 @@ fn already_installed_local_path_dependent() {
38183818
38193819
----- stderr -----
38203820
× No solution found when resolving dependencies:
3821-
╰─▶ Because all versions of first-local were not found in the provided package locations and second-local==0.1.0 depends on first-local, we can conclude that second-local==0.1.0 cannot be used.
3821+
╰─▶ Because first-local was not found in the provided package locations and second-local==0.1.0 depends on first-local, we can conclude that second-local==0.1.0 cannot be used.
38223822
And because only second-local==0.1.0 is available and you require second-local, we can conclude that the requirements are unsatisfiable.
38233823
"###
38243824
);
@@ -3890,7 +3890,7 @@ fn already_installed_local_version_of_remote_package() {
38903890
38913891
----- stderr -----
38923892
× No solution found when resolving dependencies:
3893-
╰─▶ Because anyio==4.2.0 was not found in the provided package locations and you require anyio==4.2.0, we can conclude that the requirements are unsatisfiable.
3893+
╰─▶ Because anyio was not found in the provided package locations and you require anyio==4.2.0, we can conclude that the requirements are unsatisfiable.
38943894
38953895
hint: Packages were unavailable because index lookups were disabled and no additional package locations were provided (try: `--find-links <uri>`)
38963896
"###
@@ -4143,7 +4143,7 @@ fn already_installed_remote_url() {
41434143
41444144
----- stderr -----
41454145
× No solution found when resolving dependencies:
4146-
╰─▶ Because all versions of uv-public-pypackage were not found in the provided package locations and you require uv-public-pypackage, we can conclude that the requirements are unsatisfiable.
4146+
╰─▶ Because uv-public-pypackage was not found in the provided package locations and you require uv-public-pypackage, we can conclude that the requirements are unsatisfiable.
41474147
41484148
hint: Packages were unavailable because index lookups were disabled and no additional package locations were provided (try: `--find-links <uri>`)
41494149
"###);
@@ -4188,7 +4188,7 @@ fn already_installed_remote_url() {
41884188
41894189
----- stderr -----
41904190
× No solution found when resolving dependencies:
4191-
╰─▶ Because uv-public-pypackage==0.2.0 was not found in the provided package locations and you require uv-public-pypackage==0.2.0, we can conclude that the requirements are unsatisfiable.
4191+
╰─▶ Because uv-public-pypackage was not found in the provided package locations and you require uv-public-pypackage==0.2.0, we can conclude that the requirements are unsatisfiable.
41924192
41934193
hint: Packages were unavailable because index lookups were disabled and no additional package locations were provided (try: `--find-links <uri>`)
41944194
"###);

crates/uv/tests/pip_install_scenarios.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ fn requires_package_does_not_exist() {
9191
9292
----- stderr -----
9393
× No solution found when resolving dependencies:
94-
╰─▶ Because all versions of package-a were not found in the package registry and you require package-a, we can conclude that the requirements are unsatisfiable.
94+
╰─▶ Because package-a was not found in the package registry and you require package-a, we can conclude that the requirements are unsatisfiable.
9595
"###);
9696

9797
assert_not_installed(
@@ -254,7 +254,7 @@ fn transitive_requires_package_does_not_exist() {
254254
255255
----- stderr -----
256256
× No solution found when resolving dependencies:
257-
╰─▶ Because all versions of package-b were not found in the package registry and package-a==1.0.0 depends on package-b, we can conclude that package-a==1.0.0 cannot be used.
257+
╰─▶ Because package-b was not found in the package registry and package-a==1.0.0 depends on package-b, we can conclude that package-a==1.0.0 cannot be used.
258258
And because only package-a==1.0.0 is available and you require package-a, we can conclude that the requirements are unsatisfiable.
259259
"###);
260260

0 commit comments

Comments
 (0)