Use consistent formatting for build system errors (#9340)
Some checks are pending
CI / mkdocs (push) Waiting to run
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / Determine changes (push) Waiting to run
CI / check windows trampoline | i686 (push) Blocked by required conditions
CI / lint (push) Waiting to run
CI / cargo clippy | ubuntu (push) Blocked by required conditions
CI / cargo clippy | windows (push) Blocked by required conditions
CI / cargo dev generate-all (push) Blocked by required conditions
CI / cargo shear (push) Waiting to run
CI / check windows trampoline | x86_64 (push) Blocked by required conditions
CI / cargo test | ubuntu (push) Blocked by required conditions
CI / cargo test | macos (push) Blocked by required conditions
CI / cargo test | windows (push) Blocked by required conditions
CI / check windows trampoline | aarch64 (push) Blocked by required conditions
CI / test windows trampoline | i686 (push) Blocked by required conditions
CI / test windows trampoline | x86_64 (push) Blocked by required conditions
CI / typos (push) Waiting to run
CI / build binary | linux (push) Blocked by required conditions
CI / build binary | macos aarch64 (push) Blocked by required conditions
CI / build binary | macos x86_64 (push) Blocked by required conditions
CI / build binary | windows (push) Blocked by required conditions
CI / cargo build (msrv) (push) Blocked by required conditions
CI / build binary | freebsd (push) Blocked by required conditions
CI / ecosystem test | prefecthq/prefect (push) Blocked by required conditions
CI / ecosystem test | pallets/flask (push) Blocked by required conditions
CI / integration test | conda on ubuntu (push) Blocked by required conditions
CI / integration test | free-threaded on linux (push) Blocked by required conditions
CI / integration test | free-threaded on windows (push) Blocked by required conditions
CI / integration test | pypy on ubuntu (push) Blocked by required conditions
CI / integration test | pypy on windows (push) Blocked by required conditions
CI / integration test | graalpy on ubuntu (push) Blocked by required conditions
CI / integration test | graalpy on windows (push) Blocked by required conditions
CI / integration test | github actions (push) Blocked by required conditions
CI / integration test | determine publish changes (push) Blocked by required conditions
CI / check system | alpine (push) Blocked by required conditions
CI / integration test | uv publish (push) Blocked by required conditions
CI / check cache | ubuntu (push) Blocked by required conditions
CI / check cache | macos aarch64 (push) Blocked by required conditions
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / check system | python on opensuse (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86_64 (push) Blocked by required conditions
CI / check system | python3.10 on windows (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on linux (push) Blocked by required conditions
CI / check system | conda3.8 on linux (push) Blocked by required conditions
CI / check system | conda3.11 on macos (push) Blocked by required conditions
CI / check system | conda3.8 on macos (push) Blocked by required conditions
CI / check system | conda3.11 on windows (push) Blocked by required conditions
CI / check system | conda3.8 on windows (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions

## Summary

These look pretty different from the help / hint messages we show on
resolver failure. I've added color, backticks, and a "hint:" prefix.

Before:

![Screenshot 2024-11-21 at 5 45
40 PM](https://github.com/user-attachments/assets/71ee2551-8fc6-4715-a9d7-68055cd34547)

After:

![Screenshot 2024-11-21 at 6 05
31 PM](https://github.com/user-attachments/assets/24e7fb46-49aa-4b6f-a442-115a71a3414b)
This commit is contained in:
Charlie Marsh 2024-11-27 09:22:53 -05:00 committed by GitHub
parent 0cd9c542ad
commit ee84620e90
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 127 additions and 99 deletions

View file

@ -108,17 +108,22 @@ impl Display for MissingHeaderCause {
{ {
write!( write!(
f, f,
"This error likely indicates that you need to install a library that provides \"{header}\" for {package_name}@{package_version}", "This error likely indicates that you need to install a library that provides \"{}\" for `{}`",
header.cyan(),
format!("{package_name}@{package_version}").cyan(),
) )
} else if let Some(version_id) = &self.version_id { } else if let Some(version_id) = &self.version_id {
write!( write!(
f, f,
"This error likely indicates that you need to install a library that provides \"{header}\" for {version_id}", "This error likely indicates that you need to install a library that provides \"{}\" for `{}`",
header.cyan(),
version_id.cyan(),
) )
} else { } else {
write!( write!(
f, f,
"This error likely indicates that you need to install a library that provides \"{header}\"", "This error likely indicates that you need to install a library that provides \"{}\"",
header.cyan(),
) )
} }
} }
@ -128,17 +133,25 @@ impl Display for MissingHeaderCause {
{ {
write!( write!(
f, f,
"This error likely indicates that you need to install the library that provides a shared library for {library} for {package_name}@{package_version} (e.g., lib{library}-dev)", "This error likely indicates that you need to install the library that provides a shared library for `{}` for `{}` (e.g., `{}`)",
library.cyan(),
format!("{package_name}@{package_version}").cyan(),
format!("lib{library}-dev").cyan(),
) )
} else if let Some(version_id) = &self.version_id { } else if let Some(version_id) = &self.version_id {
write!( write!(
f, f,
"This error likely indicates that you need to install the library that provides a shared library for {library} for {version_id} (e.g., lib{library}-dev)", "This error likely indicates that you need to install the library that provides a shared library for `{}` for `{}` (e.g., `{}`)",
library.cyan(),
version_id.cyan(),
format!("lib{library}-dev").cyan(),
) )
} else { } else {
write!( write!(
f, f,
"This error likely indicates that you need to install the library that provides a shared library for {library} (e.g., lib{library}-dev)", "This error likely indicates that you need to install the library that provides a shared library for `{}` (e.g., `{}`)",
library.cyan(),
format!("lib{library}-dev").cyan(),
) )
} }
} }
@ -148,17 +161,36 @@ impl Display for MissingHeaderCause {
{ {
write!( write!(
f, f,
"This error likely indicates that {package_name}@{package_version} depends on {package}, but doesn't declare it as a build dependency. If {package_name} is a first-party package, consider adding {package} to its `build-system.requires`. Otherwise, `uv pip install {package}` into the environment and re-run with `--no-build-isolation`." "This error likely indicates that `{}` depends on `{}`, but doesn't declare it as a build dependency. If `{}` is a first-party package, consider adding `{}` to its `{}`. Otherwise, `{}` into the environment and re-run with `{}`.",
format!("{package_name}@{package_version}").cyan(),
package.cyan(),
package_name.cyan(),
package.cyan(),
"build-system.requires".green(),
format!("uv pip install {package}").green(),
"--no-build-isolation".green(),
) )
} else if let Some(version_id) = &self.version_id { } else if let Some(version_id) = &self.version_id {
write!( write!(
f, f,
"This error likely indicates that {version_id} depends on {package}, but doesn't declare it as a build dependency. If {version_id} is a first-party package, consider adding {package} to its `build-system.requires`. Otherwise, `uv pip install {package}` into the environment and re-run with `--no-build-isolation`.", "This error likely indicates that `{}` depends on `{}`, but doesn't declare it as a build dependency. If `{}` is a first-party package, consider adding `{}` to its `{}`. Otherwise, `{}` into the environment and re-run with `{}`.",
version_id.cyan(),
package.cyan(),
version_id.cyan(),
package.cyan(),
"build-system.requires".green(),
format!("uv pip install {package}").green(),
"--no-build-isolation".green(),
) )
} else { } else {
write!( write!(
f, f,
"This error likely indicates that a package depends on {package}, but doesn't declare it as a build dependency. If the package is a first-party package, consider adding {package} to its `build-system.requires`. Otherwise, `uv pip install {package}` into the environment and re-run with `--no-build-isolation`.", "This error likely indicates that a package depends on `{}`, but doesn't declare it as a build dependency. If the package is a first-party package, consider adding `{}` to its `{}`. Otherwise, `{}` into the environment and re-run with `{}`.",
package.cyan(),
package.cyan(),
"build-system.requires".green(),
format!("uv pip install {package}").green(),
"--no-build-isolation".green(),
) )
} }
} }
@ -168,12 +200,18 @@ impl Display for MissingHeaderCause {
{ {
write!( write!(
f, f,
"{package} was removed from the standard library in Python {version}. Consider adding a constraint (like `{package_name} >{package_version}`) to avoid building a version of {package_name} that depends on {package}.", "`{}` was removed from the standard library in Python {version}. Consider adding a constraint (like `{}`) to avoid building a version of `{}` that depends on `{}`.",
package.cyan(),
format!("{package_name} >{package_version}").green(),
package_name.cyan(),
package.cyan(),
) )
} else { } else {
write!( write!(
f, f,
"{package} was removed from the standard library in Python {version}. Consider adding a constraint to avoid building a package-version that depends on {package}.", "`{}` was removed from the standard library in Python {version}. Consider adding a constraint to avoid building a package that depends on `{}`.",
package.cyan(),
package.cyan(),
) )
} }
} }
@ -219,7 +257,6 @@ pub struct MissingHeaderError {
exit_code: ExitStatus, exit_code: ExitStatus,
stdout: Vec<String>, stdout: Vec<String>,
stderr: Vec<String>, stderr: Vec<String>,
#[source]
cause: MissingHeaderCause, cause: MissingHeaderCause,
} }
@ -227,21 +264,21 @@ impl Display for MissingHeaderError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{} ({})", self.message, self.exit_code)?; write!(f, "{} ({})", self.message, self.exit_code)?;
let mut non_empty = false;
if self.stdout.iter().any(|line| !line.trim().is_empty()) { if self.stdout.iter().any(|line| !line.trim().is_empty()) {
write!(f, "\n\n{}\n{}", "[stdout]".red(), self.stdout.join("\n"))?; write!(f, "\n\n{}\n{}", "[stdout]".red(), self.stdout.join("\n"))?;
non_empty = true;
} }
if self.stderr.iter().any(|line| !line.trim().is_empty()) { if self.stderr.iter().any(|line| !line.trim().is_empty()) {
write!(f, "\n\n{}\n{}", "[stderr]".red(), self.stderr.join("\n"))?; write!(f, "\n\n{}\n{}", "[stderr]".red(), self.stderr.join("\n"))?;
non_empty = true;
} }
if non_empty { write!(
writeln!(f)?; f,
} "\n\n{}{} {}",
"hint".bold().cyan(),
":".bold(),
self.cause
)?;
Ok(()) Ok(())
} }
@ -401,11 +438,9 @@ mod test {
| ^~~~~~~~~~~~~~~~~~~ | ^~~~~~~~~~~~~~~~~~~
compilation terminated. compilation terminated.
error: command '/usr/bin/gcc' failed with exit code 1 error: command '/usr/bin/gcc' failed with exit code 1
hint: This error likely indicates that you need to install a library that provides "graphviz/cgraph.h" for `pygraphviz-1.11`
"###); "###);
insta::assert_snapshot!(
std::error::Error::source(&err).unwrap(),
@r###"This error likely indicates that you need to install a library that provides "graphviz/cgraph.h" for pygraphviz-1.11"###
);
} }
#[test] #[test]
@ -447,11 +482,9 @@ mod test {
/usr/bin/ld: cannot find -lncurses: No such file or directory /usr/bin/ld: cannot find -lncurses: No such file or directory
collect2: error: ld returned 1 exit status collect2: error: ld returned 1 exit status
error: command '/usr/bin/x86_64-linux-gnu-gcc' failed with exit code 1 error: command '/usr/bin/x86_64-linux-gnu-gcc' failed with exit code 1
hint: This error likely indicates that you need to install the library that provides a shared library for `ncurses` for `pygraphviz-1.11` (e.g., `libncurses-dev`)
"###); "###);
insta::assert_snapshot!(
std::error::Error::source(&err).unwrap(),
@"This error likely indicates that you need to install the library that provides a shared library for ncurses for pygraphviz-1.11 (e.g., libncurses-dev)"
);
} }
#[test] #[test]
@ -495,11 +528,9 @@ mod test {
or: setup.py cmd --help or: setup.py cmd --help
error: invalid command 'bdist_wheel' error: invalid command 'bdist_wheel'
hint: This error likely indicates that `pygraphviz-1.11` depends on `wheel`, but doesn't declare it as a build dependency. If `pygraphviz-1.11` is a first-party package, consider adding `wheel` to its `build-system.requires`. Otherwise, `uv pip install wheel` into the environment and re-run with `--no-build-isolation`.
"###); "###);
insta::assert_snapshot!(
std::error::Error::source(&err).unwrap(),
@"This error likely indicates that pygraphviz-1.11 depends on wheel, but doesn't declare it as a build dependency. If pygraphviz-1.11 is a first-party package, consider adding wheel to its `build-system.requires`. Otherwise, `uv pip install wheel` into the environment and re-run with `--no-build-isolation`."
);
} }
#[test] #[test]
@ -536,10 +567,8 @@ mod test {
[stderr] [stderr]
import distutils.core import distutils.core
ModuleNotFoundError: No module named 'distutils' ModuleNotFoundError: No module named 'distutils'
hint: `distutils` was removed from the standard library in Python 3.12. Consider adding a constraint (like `pygraphviz >1.11`) to avoid building a version of `pygraphviz` that depends on `distutils`.
"###); "###);
insta::assert_snapshot!(
std::error::Error::source(&err).unwrap(),
@"distutils was removed from the standard library in Python 3.12. Consider adding a constraint (like `pygraphviz >1.11`) to avoid building a version of pygraphviz that depends on distutils."
);
} }
} }

View file

@ -1057,22 +1057,22 @@ impl std::fmt::Display for PubGrubHint {
Self::PrereleaseAvailable { package, version } => { Self::PrereleaseAvailable { package, version } => {
write!( write!(
f, f,
"{}{} Pre-releases are available for {} in the requested range (e.g., {}), but pre-releases weren't enabled (try: `{}`)", "{}{} Pre-releases are available for `{}` in the requested range (e.g., {}), but pre-releases weren't enabled (try: `{}`)",
"hint".bold().cyan(), "hint".bold().cyan(),
":".bold(), ":".bold(),
package.bold(), package.cyan(),
version.bold(), version.cyan(),
"--prerelease=allow".green(), "--prerelease=allow".green(),
) )
} }
Self::PrereleaseRequested { package, range } => { Self::PrereleaseRequested { package, range } => {
write!( write!(
f, f,
"{}{} {} was requested with a pre-release marker (e.g., {}), but pre-releases weren't enabled (try: `{}`)", "{}{} `{}` was requested with a pre-release marker (e.g., {}), but pre-releases weren't enabled (try: `{}`)",
"hint".bold().cyan(), "hint".bold().cyan(),
":".bold(), ":".bold(),
package.bold(), package.cyan(),
PackageRange::compatibility(package, range, None).bold(), PackageRange::compatibility(package, range, None).cyan(),
"--prerelease=allow".green(), "--prerelease=allow".green(),
) )
} }
@ -1096,7 +1096,7 @@ impl std::fmt::Display for PubGrubHint {
Self::MissingPackageMetadata { package } => { Self::MissingPackageMetadata { package } => {
write!( write!(
f, f,
"{}{} Metadata for {} could not be found, as the wheel is missing a `METADATA` file", "{}{} Metadata for `{}` could not be found, as the wheel is missing a `METADATA` file",
"hint".bold().cyan(), "hint".bold().cyan(),
":".bold(), ":".bold(),
package.bold() package.bold()
@ -1105,31 +1105,31 @@ impl std::fmt::Display for PubGrubHint {
Self::InvalidPackageMetadata { package, reason } => { Self::InvalidPackageMetadata { package, reason } => {
write!( write!(
f, f,
"{}{} Metadata for {} could not be parsed:\n{}", "{}{} Metadata for `{}` could not be parsed:\n{}",
"hint".bold().cyan(), "hint".bold().cyan(),
":".bold(), ":".bold(),
package.bold(), package.cyan(),
textwrap::indent(reason, " ") textwrap::indent(reason, " ")
) )
} }
Self::InvalidPackageStructure { package, reason } => { Self::InvalidPackageStructure { package, reason } => {
write!( write!(
f, f,
"{}{} The structure of {} was invalid:\n{}", "{}{} The structure of `{}` was invalid:\n{}",
"hint".bold().cyan(), "hint".bold().cyan(),
":".bold(), ":".bold(),
package.bold(), package.cyan(),
textwrap::indent(reason, " ") textwrap::indent(reason, " ")
) )
} }
Self::MissingVersionMetadata { package, version } => { Self::MissingVersionMetadata { package, version } => {
write!( write!(
f, f,
"{}{} Metadata for {}=={} could not be found, as the wheel is missing a `METADATA` file", "{}{} Metadata for `{}` ({}) could not be found, as the wheel is missing a `METADATA` file",
"hint".bold().cyan(), "hint".bold().cyan(),
":".bold(), ":".bold(),
package.bold(), package.cyan(),
version.bold(), format!("v{version}").cyan(),
) )
} }
Self::InvalidVersionMetadata { Self::InvalidVersionMetadata {
@ -1139,11 +1139,11 @@ impl std::fmt::Display for PubGrubHint {
} => { } => {
write!( write!(
f, f,
"{}{} Metadata for {}=={} could not be parsed:\n{}", "{}{} Metadata for `{}` ({}) could not be parsed:\n{}",
"hint".bold().cyan(), "hint".bold().cyan(),
":".bold(), ":".bold(),
package.bold(), package.cyan(),
version.bold(), format!("v{version}").cyan(),
textwrap::indent(reason, " ") textwrap::indent(reason, " ")
) )
} }
@ -1154,11 +1154,11 @@ impl std::fmt::Display for PubGrubHint {
} => { } => {
write!( write!(
f, f,
"{}{} The structure of {}=={} was invalid:\n{}", "{}{} The structure of `{}` ({}) was invalid:\n{}",
"hint".bold().cyan(), "hint".bold().cyan(),
":".bold(), ":".bold(),
package.bold(), package.cyan(),
version.bold(), format!("v{version}").cyan(),
textwrap::indent(reason, " ") textwrap::indent(reason, " ")
) )
} }
@ -1169,11 +1169,11 @@ impl std::fmt::Display for PubGrubHint {
} => { } => {
write!( write!(
f, f,
"{}{} Metadata for {}=={} was inconsistent:\n{}", "{}{} Metadata for `{}` ({}) was inconsistent:\n{}",
"hint".bold().cyan(), "hint".bold().cyan(),
":".bold(), ":".bold(),
package.bold(), package.cyan(),
version.bold(), format!("v{version}").cyan(),
textwrap::indent(reason, " ") textwrap::indent(reason, " ")
) )
} }
@ -1189,10 +1189,10 @@ impl std::fmt::Display for PubGrubHint {
"{}{} The `requires-python` value ({}) includes Python versions that are not supported by your dependencies (e.g., {} only supports {}). Consider using a more restrictive `requires-python` value (like {}).", "{}{} The `requires-python` value ({}) includes Python versions that are not supported by your dependencies (e.g., {} only supports {}). Consider using a more restrictive `requires-python` value (like {}).",
"hint".bold().cyan(), "hint".bold().cyan(),
":".bold(), ":".bold(),
requires_python.bold(), requires_python.cyan(),
PackageRange::compatibility(package, package_set, None).bold(), PackageRange::compatibility(package, package_set, None).cyan(),
package_requires_python.bold(), package_requires_python.cyan(),
package_requires_python.bold(), package_requires_python.cyan(),
) )
} }
Self::RequiresPython { Self::RequiresPython {
@ -1207,9 +1207,9 @@ impl std::fmt::Display for PubGrubHint {
"{}{} The `--python-version` value ({}) includes Python versions that are not supported by your dependencies (e.g., {} only supports {}). Consider using a higher `--python-version` value.", "{}{} The `--python-version` value ({}) includes Python versions that are not supported by your dependencies (e.g., {} only supports {}). Consider using a higher `--python-version` value.",
"hint".bold().cyan(), "hint".bold().cyan(),
":".bold(), ":".bold(),
requires_python.bold(), requires_python.cyan(),
PackageRange::compatibility(package, package_set, None).bold(), PackageRange::compatibility(package, package_set, None).cyan(),
package_requires_python.bold(), package_requires_python.cyan(),
) )
} }
Self::IncompatibleBuildRequirement { Self::IncompatibleBuildRequirement {
@ -1220,13 +1220,13 @@ impl std::fmt::Display for PubGrubHint {
} => { } => {
write!( write!(
f, f,
"{}{} The source distribution for {}=={} does not include static metadata. Generating metadata for this package requires Python {}, but Python {} is installed.", "{}{} The source distribution for `{}` ({}) does not include static metadata. Generating metadata for this package requires Python {}, but Python {} is installed.",
"hint".bold().cyan(), "hint".bold().cyan(),
":".bold(), ":".bold(),
package.bold(), package.cyan(),
version.bold(), format!("v{version}").cyan(),
requires_python.bold(), requires_python.cyan(),
python_version.bold(), python_version.cyan(),
) )
} }
Self::RequiresPython { Self::RequiresPython {
@ -1241,8 +1241,8 @@ impl std::fmt::Display for PubGrubHint {
"{}{} The Python interpreter uses a Python version that is not supported by your dependencies (e.g., {} only supports {}). Consider passing a `--python-version` value to raise the minimum supported version.", "{}{} The Python interpreter uses a Python version that is not supported by your dependencies (e.g., {} only supports {}). Consider passing a `--python-version` value to raise the minimum supported version.",
"hint".bold().cyan(), "hint".bold().cyan(),
":".bold(), ":".bold(),
PackageRange::compatibility(package, package_set, None).bold(), PackageRange::compatibility(package, package_set, None).cyan(),
package_requires_python.bold(), package_requires_python.cyan(),
) )
} }
Self::DependsOnWorkspacePackage { Self::DependsOnWorkspacePackage {
@ -1265,8 +1265,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}.", "{}{} The package `{}` depends on the package `{}` but the name is shadowed by {your_project}. Consider changing the name of {the_project}.",
"hint".bold().cyan(), "hint".bold().cyan(),
":".bold(), ":".bold(),
package.bold(), package.cyan(),
dependency.bold(), dependency.cyan(),
) )
} }
Self::UncheckedIndex { Self::UncheckedIndex {
@ -1280,7 +1280,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.", "{}{} `{}` 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(), "hint".bold().cyan(),
":".bold(), ":".bold(),
package.bold(), package.cyan(),
found_index.cyan(), found_index.cyan(),
PackageRange::compatibility(package, range, None).cyan(), PackageRange::compatibility(package, range, None).cyan(),
next_index.cyan(), next_index.cyan(),
@ -1294,7 +1294,7 @@ impl std::fmt::Display for PubGrubHint {
"hint".bold().cyan(), "hint".bold().cyan(),
":".bold(), ":".bold(),
index.redacted().cyan(), index.redacted().cyan(),
"401 Unauthorized".bold().red(), "401 Unauthorized".red(),
) )
} }
Self::ForbiddenIndex { index } => { Self::ForbiddenIndex { index } => {
@ -1304,7 +1304,7 @@ impl std::fmt::Display for PubGrubHint {
"hint".bold().cyan(), "hint".bold().cyan(),
":".bold(), ":".bold(),
index.redacted().cyan(), index.redacted().cyan(),
"403 Forbidden".bold().red(), "403 Forbidden".red(),
) )
} }
} }

View file

@ -312,7 +312,7 @@ fn format_chain(name: &PackageName, version: Option<&Version>, chain: &Derivatio
range.filter(|range| *range != Ranges::empty() && *range != Ranges::full()) range.filter(|range| *range != Ranges::empty() && *range != Ranges::full())
{ {
if let Some(extra) = &step.extra { if let Some(extra) = &step.extra {
// Ex) `flask[dotenv]>=1.0.0` (v1.2.3)` // Ex) `flask[dotenv]>=1.0.0` (v1.2.3)
format!( format!(
"`{}{}` ({})", "`{}{}` ({})",
format!("{}[{}]", step.name, extra).cyan(), format!("{}[{}]", step.name, extra).cyan(),
@ -320,7 +320,7 @@ fn format_chain(name: &PackageName, version: Option<&Version>, chain: &Derivatio
format!("v{}", step.version).cyan(), format!("v{}", step.version).cyan(),
) )
} else if let Some(group) = &step.group { } else if let Some(group) = &step.group {
// Ex) `flask:dev>=1.0.0` (v1.2.3)` // Ex) `flask:dev>=1.0.0` (v1.2.3)
format!( format!(
"`{}{}` ({})", "`{}{}` ({})",
format!("{}:{}", step.name, group).cyan(), format!("{}:{}", step.name, group).cyan(),
@ -328,7 +328,7 @@ fn format_chain(name: &PackageName, version: Option<&Version>, chain: &Derivatio
format!("v{}", step.version).cyan(), format!("v{}", step.version).cyan(),
) )
} else { } else {
// Ex) `flask>=1.0.0` (v1.2.3)` // Ex) `flask>=1.0.0` (v1.2.3)
format!( format!(
"`{}{}` ({})", "`{}{}` ({})",
step.name.cyan(), step.name.cyan(),
@ -338,21 +338,21 @@ fn format_chain(name: &PackageName, version: Option<&Version>, chain: &Derivatio
} }
} else { } else {
if let Some(extra) = &step.extra { if let Some(extra) = &step.extra {
// Ex) `flask[dotenv]` (v1.2.3)` // Ex) `flask[dotenv]` (v1.2.3)
format!( format!(
"`{}` ({})", "`{}` ({})",
format!("{}[{}]", step.name, extra).cyan(), format!("{}[{}]", step.name, extra).cyan(),
format!("v{}", step.version).cyan(), format!("v{}", step.version).cyan(),
) )
} else if let Some(group) = &step.group { } else if let Some(group) = &step.group {
// Ex) `flask:dev` (v1.2.3)` // Ex) `flask:dev` (v1.2.3)
format!( format!(
"`{}` ({})", "`{}` ({})",
format!("{}:{}", step.name, group).cyan(), format!("{}:{}", step.name, group).cyan(),
format!("v{}", step.version).cyan(), format!("v{}", step.version).cyan(),
) )
} else { } else {
// Ex) `flask` (v1.2.3)` // Ex) `flask` (v1.2.3)
format!( format!(
"`{}` ({})", "`{}` ({})",
step.name.cyan(), step.name.cyan(),

View file

@ -266,7 +266,7 @@ fn prune_unzipped() -> Result<()> {
need to be downloaded from a registry, we can conclude that iniconfig<1.0.0 cannot be used. need to be downloaded from a registry, we can conclude that iniconfig<1.0.0 cannot be used.
And because you require iniconfig, we can conclude that your requirements are unsatisfiable. And because you require iniconfig, we can conclude that your requirements are unsatisfiable.
hint: Pre-releases are available for iniconfig in the requested range (e.g., 0.2.dev0), but pre-releases weren't enabled (try: `--prerelease=allow`) hint: Pre-releases are available for `iniconfig` in the requested range (e.g., 0.2.dev0), but pre-releases weren't enabled (try: `--prerelease=allow`)
hint: Packages were unavailable because the network was disabled. When the network is disabled, registry packages may only be read from the cache. hint: Packages were unavailable because the network was disabled. When the network is disabled, registry packages may only be read from the cache.
"###); "###);

View file

@ -5202,7 +5202,7 @@ fn lock_requires_python() -> Result<()> {
"#, "#,
)?; )?;
uv_snapshot!(context.filters(), context.lock(), @r" uv_snapshot!(context.filters(), context.lock(), @r###"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@ -5222,10 +5222,10 @@ fn lock_requires_python() -> Result<()> {
cannot be used, we can conclude that pygls>=1.1.0 cannot be used. cannot be used, we can conclude that pygls>=1.1.0 cannot be used.
And because your project depends on pygls>=1.1.0, we can conclude that your project's requirements are unsatisfiable. And because your project depends on pygls>=1.1.0, we can conclude that your project's requirements are unsatisfiable.
hint: Pre-releases are available for pygls in the requested range (e.g., 2.0.0a2), but pre-releases weren't enabled (try: `--prerelease=allow`) hint: Pre-releases are available for `pygls` in the requested range (e.g., 2.0.0a2), but pre-releases weren't enabled (try: `--prerelease=allow`)
hint: The `requires-python` value (>=3.7) includes Python versions that are not supported by your dependencies (e.g., pygls>=1.1.0,<=1.2.1 only supports >=3.7.9, <4). Consider using a more restrictive `requires-python` value (like >=3.7.9, <4). hint: The `requires-python` value (>=3.7) includes Python versions that are not supported by your dependencies (e.g., pygls>=1.1.0,<=1.2.1 only supports >=3.7.9, <4). Consider using a more restrictive `requires-python` value (like >=3.7.9, <4).
"); "###);
// Require >=3.7, and allow locking to a version of `pygls` that is compatible (==1.0.1). // Require >=3.7, and allow locking to a version of `pygls` that is compatible (==1.0.1).
pyproject_toml.write_str( pyproject_toml.write_str(

View file

@ -6347,11 +6347,10 @@ fn invalid_metadata_requires_python() -> Result<()> {
× No solution found when resolving dependencies: × No solution found when resolving dependencies:
Because validation==2.0.0 has invalid metadata and you require validation==2.0.0, we can conclude that your requirements are unsatisfiable. Because validation==2.0.0 has invalid metadata and you require validation==2.0.0, we can conclude that your requirements are unsatisfiable.
hint: Metadata for validation==2.0.0 could not be parsed: hint: Metadata for `validation` (v2.0.0) could not be parsed:
Failed to parse version: Unexpected end of version specifier, expected operator: Failed to parse version: Unexpected end of version specifier, expected operator:
12 12
^^ ^^
"### "###
); );
@ -6379,7 +6378,7 @@ fn invalid_metadata_multiple_dist_info() -> Result<()> {
× No solution found when resolving dependencies: × No solution found when resolving dependencies:
Because validation==3.0.0 has an invalid package format and you require validation==3.0.0, we can conclude that your requirements are unsatisfiable. Because validation==3.0.0 has an invalid package format and you require validation==3.0.0, we can conclude that your requirements are unsatisfiable.
hint: The structure of validation==3.0.0 was invalid: hint: The structure of `validation` (v3.0.0) was invalid:
Multiple .dist-info directories found: validation-2.0.0, validation-3.0.0 Multiple .dist-info directories found: validation-2.0.0, validation-3.0.0
"### "###
); );
@ -13397,7 +13396,7 @@ fn unsupported_requires_python_dynamic_metadata() -> Result<()> {
× No solution found when resolving dependencies for split (python_full_version >= '3.10'): × No solution found when resolving dependencies for split (python_full_version >= '3.10'):
Because source-distribution{python_full_version >= '3.10'}==0.0.3 requires Python >=3.10 and you require source-distribution{python_full_version >= '3.10'}==0.0.3, we can conclude that your requirements are unsatisfiable. Because source-distribution{python_full_version >= '3.10'}==0.0.3 requires Python >=3.10 and you require source-distribution{python_full_version >= '3.10'}==0.0.3, we can conclude that your requirements are unsatisfiable.
hint: The source distribution for source-distribution{python_full_version >= '3.10'}==0.0.3 does not include static metadata. Generating metadata for this package requires Python >=3.10, but Python 3.8.[X] is installed. hint: The source distribution for `source-distribution{python_full_version >= '3.10'}` (v0.0.3) does not include static metadata. Generating metadata for this package requires Python >=3.10, but Python 3.8.[X] is installed.
"###); "###);
Ok(()) Ok(())

View file

@ -2145,7 +2145,7 @@ fn install_only_binary_all_and_no_binary_all() {
cannot be used. cannot be used.
And because you require anyio, we can conclude that your requirements are unsatisfiable. And because you require anyio, we can conclude that your requirements are unsatisfiable.
hint: Pre-releases are available for anyio in the requested range (e.g., 4.0.0rc1), but pre-releases weren't enabled (try: `--prerelease=allow`) hint: Pre-releases are available for `anyio` in the requested range (e.g., 4.0.0rc1), but pre-releases weren't enabled (try: `--prerelease=allow`)
"### "###
); );

View file

@ -2718,7 +2718,7 @@ fn package_only_prereleases_in_range() {
× No solution found when resolving dependencies: × No solution found when resolving dependencies:
Because only package-a<0.1.0 is available and you require package-a>0.1.0, we can conclude that your requirements are unsatisfiable. Because only package-a<0.1.0 is available and you require package-a>0.1.0, we can conclude that your requirements are unsatisfiable.
hint: Pre-releases are available for package-a in the requested range (e.g., 1.0.0a1), but pre-releases weren't enabled (try: `--prerelease=allow`) hint: Pre-releases are available for `package-a` in the requested range (e.g., 1.0.0a1), but pre-releases weren't enabled (try: `--prerelease=allow`)
"###); "###);
// Since there are stable versions of `a` available, prerelease versions should not be selected without explicit opt-in. // Since there are stable versions of `a` available, prerelease versions should not be selected without explicit opt-in.
@ -3250,7 +3250,7 @@ fn transitive_package_only_prereleases_in_range() {
Because only package-b<0.1 is available and package-a==0.1.0 depends on package-b>0.1, we can conclude that package-a==0.1.0 cannot be used. Because only package-b<0.1 is available and package-a==0.1.0 depends on package-b>0.1, we can conclude that package-a==0.1.0 cannot be used.
And because only package-a==0.1.0 is available and you require package-a, we can conclude that your requirements are unsatisfiable. And because only package-a==0.1.0 is available and you require package-a, we can conclude that your requirements are unsatisfiable.
hint: Pre-releases are available for package-b in the requested range (e.g., 1.0.0a1), but pre-releases weren't enabled (try: `--prerelease=allow`) hint: Pre-releases are available for `package-b` in the requested range (e.g., 1.0.0a1), but pre-releases weren't enabled (try: `--prerelease=allow`)
"###); "###);
// Since there are stable versions of `b` available, the prerelease version should not be selected without explicit opt-in. The available version is excluded by the range requested by the user. // Since there are stable versions of `b` available, the prerelease version should not be selected without explicit opt-in. The available version is excluded by the range requested by the user.
@ -3388,7 +3388,7 @@ fn transitive_prerelease_and_stable_dependency_many_versions_holes() {
we can conclude that package-a==1.0.0 cannot be used. we can conclude that package-a==1.0.0 cannot be used.
And because only package-a==1.0.0 is available and you require package-a, we can conclude that your requirements are unsatisfiable. And because only package-a==1.0.0 is available and you require package-a, we can conclude that your requirements are unsatisfiable.
hint: package-c was requested with a pre-release marker (e.g., all of: hint: `package-c` was requested with a pre-release marker (e.g., all of:
package-c>1.0.0,<2.0.0a5 package-c>1.0.0,<2.0.0a5
package-c>2.0.0a7,<2.0.0b1 package-c>2.0.0a7,<2.0.0b1
package-c>2.0.0b1,<2.0.0b5 package-c>2.0.0b1,<2.0.0b5
@ -3482,7 +3482,7 @@ fn transitive_prerelease_and_stable_dependency_many_versions() {
And because package-b==1.0.0 depends on package-c and only package-b==1.0.0 is available, we can conclude that all versions of package-a and all versions of package-b are incompatible. And because package-b==1.0.0 depends on package-c and only package-b==1.0.0 is available, we can conclude that all versions of package-a and all versions of package-b are incompatible.
And because you require package-a and package-b, we can conclude that your requirements are unsatisfiable. And because you require package-a and package-b, we can conclude that your requirements are unsatisfiable.
hint: package-c was requested with a pre-release marker (e.g., package-c>=2.0.0b1), but pre-releases weren't enabled (try: `--prerelease=allow`) hint: `package-c` was requested with a pre-release marker (e.g., package-c>=2.0.0b1), but pre-releases weren't enabled (try: `--prerelease=allow`)
"###); "###);
// Since the user did not explicitly opt-in to a prerelease, it cannot be selected. // Since the user did not explicitly opt-in to a prerelease, it cannot be selected.
@ -3618,7 +3618,7 @@ fn transitive_prerelease_and_stable_dependency() {
Because there is no version of package-c==2.0.0b1 and package-a==1.0.0 depends on package-c==2.0.0b1, we can conclude that package-a==1.0.0 cannot be used. Because there is no version of package-c==2.0.0b1 and package-a==1.0.0 depends on package-c==2.0.0b1, we can conclude that package-a==1.0.0 cannot be used.
And because only package-a==1.0.0 is available and you require package-a, we can conclude that your requirements are unsatisfiable. And because only package-a==1.0.0 is available and you require package-a, we can conclude that your requirements are unsatisfiable.
hint: package-c was requested with a pre-release marker (e.g., package-c==2.0.0b1), but pre-releases weren't enabled (try: `--prerelease=allow`) hint: `package-c` was requested with a pre-release marker (e.g., package-c==2.0.0b1), but pre-releases weren't enabled (try: `--prerelease=allow`)
"###); "###);
// Since the user did not explicitly opt-in to a prerelease, it cannot be selected. // Since the user did not explicitly opt-in to a prerelease, it cannot be selected.

View file

@ -1263,7 +1263,7 @@ fn mismatched_name() -> Result<()> {
× No solution found when resolving dependencies: × No solution found when resolving dependencies:
Because foo has an invalid package format and you require foo, we can conclude that your requirements are unsatisfiable. Because foo has an invalid package format and you require foo, we can conclude that your requirements are unsatisfiable.
hint: The structure of foo was invalid: hint: The structure of `foo` was invalid:
The .dist-info directory tomli-2.0.1 does not start with the normalized package name: foo The .dist-info directory tomli-2.0.1 does not start with the normalized package name: foo
"### "###
); );
@ -2616,7 +2616,7 @@ fn incompatible_wheel() -> Result<()> {
× No solution found when resolving dependencies: × No solution found when resolving dependencies:
Because foo has an invalid package format and you require foo, we can conclude that your requirements are unsatisfiable. Because foo has an invalid package format and you require foo, we can conclude that your requirements are unsatisfiable.
hint: The structure of foo was invalid: hint: The structure of `foo` was invalid:
Failed to read from zip file Failed to read from zip file
"### "###
); );