Allow pre-releases for requirements in constraints files (#2069)

## Summary

If a pre-release marker is present on a requirement in a constraint
file, we should allow pre-releases for that package.

Closes https://github.com/astral-sh/uv/issues/2063.
This commit is contained in:
Charlie Marsh 2024-02-28 20:16:23 -05:00 committed by GitHub
parent 69fb9c37fb
commit 1bc5485094
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 55 additions and 3 deletions

View file

@ -32,6 +32,8 @@ impl CandidateSelector {
prerelease_strategy: PreReleaseStrategy::from_mode( prerelease_strategy: PreReleaseStrategy::from_mode(
options.prerelease_mode, options.prerelease_mode,
manifest.requirements.as_slice(), manifest.requirements.as_slice(),
manifest.constraints.as_slice(),
manifest.overrides.as_slice(),
), ),
preferences: Preferences::from(manifest.preferences.as_slice()), preferences: Preferences::from(manifest.preferences.as_slice()),
} }

View file

@ -48,14 +48,21 @@ pub(crate) enum PreReleaseStrategy {
} }
impl PreReleaseStrategy { impl PreReleaseStrategy {
pub(crate) fn from_mode(mode: PreReleaseMode, direct_dependencies: &[Requirement]) -> Self { pub(crate) fn from_mode(
mode: PreReleaseMode,
requirements: &[Requirement],
constraints: &[Requirement],
overrides: &[Requirement],
) -> Self {
match mode { match mode {
PreReleaseMode::Disallow => Self::Disallow, PreReleaseMode::Disallow => Self::Disallow,
PreReleaseMode::Allow => Self::Allow, PreReleaseMode::Allow => Self::Allow,
PreReleaseMode::IfNecessary => Self::IfNecessary, PreReleaseMode::IfNecessary => Self::IfNecessary,
PreReleaseMode::Explicit => Self::Explicit( PreReleaseMode::Explicit => Self::Explicit(
direct_dependencies requirements
.iter() .iter()
.chain(constraints.iter())
.chain(overrides.iter())
.filter(|requirement| { .filter(|requirement| {
let Some(version_or_url) = &requirement.version_or_url else { let Some(version_or_url) = &requirement.version_or_url else {
return false; return false;
@ -74,8 +81,10 @@ impl PreReleaseStrategy {
.collect(), .collect(),
), ),
PreReleaseMode::IfNecessaryOrExplicit => Self::IfNecessaryOrExplicit( PreReleaseMode::IfNecessaryOrExplicit => Self::IfNecessaryOrExplicit(
direct_dependencies requirements
.iter() .iter()
.chain(constraints.iter())
.chain(overrides.iter())
.filter(|requirement| { .filter(|requirement| {
let Some(version_or_url) = &requirement.version_or_url else { let Some(version_or_url) = &requirement.version_or_url else {
return false; return false;

View file

@ -4386,6 +4386,47 @@ fn pre_alias() -> Result<()> {
Ok(()) Ok(())
} }
/// Allow a pre-release for a version specifier in a constraint file.
#[test]
fn pre_release_constraint() -> Result<()> {
let context = TestContext::new("3.12");
let requirements_in = context.temp_dir.child("requirements.in");
requirements_in.write_str("flask")?;
let constraints_txt = context.temp_dir.child("constraints.txt");
constraints_txt.write_str("flask<=2.0.0rc2")?;
uv_snapshot!(context.compile()
.arg("requirements.in")
.arg("--constraint")
.arg("constraints.txt"), @r###"
success: true
exit_code: 0
----- stdout -----
# This file was autogenerated by uv via the following command:
# uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2023-11-18T12:00:00Z requirements.in --constraint constraints.txt
click==8.1.7
# via flask
flask==2.0.0rc2
itsdangerous==2.1.2
# via flask
jinja2==3.1.2
# via flask
markupsafe==2.1.3
# via
# jinja2
# werkzeug
werkzeug==3.0.1
# via flask
----- stderr -----
Resolved 6 packages in [TIME]
"###
);
Ok(())
}
/// Resolve from a `pyproject.toml` file with a recursive extra. /// Resolve from a `pyproject.toml` file with a recursive extra.
#[test] #[test]
fn compile_pyproject_toml_recursive_extra() -> Result<()> { fn compile_pyproject_toml_recursive_extra() -> Result<()> {