Fix marker merging for requirements.txt for psycopg (#11298)

Given an input in the shape:

```
foo[bar]==1.0.0; sys_platform == 'linux'
foo==1.0.0; sys_platform != 'linux'
```

We would write either

```
foo==1.0.0; sys_platform == 'linux'
```
or
```
foo==1.0.0
```

depending on the iteration order, as the first one is from the marker
proxy package and the second one from the package without marker.

The fix correctly merges graph entries when there are two nodes with
different extras and different markers.

I tried to write a packse test but it failed due to a different
iteration order showing the correct case directly instead of the failing
one we'd need.

Only `strip_extras` is affected, since `combine_extras` uses
`version_marker`.
This commit is contained in:
konsti 2025-02-06 22:31:53 +01:00 committed by GitHub
parent cfd1e670dd
commit 5493deff65
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 43 additions and 1 deletions

View file

@ -404,6 +404,13 @@ fn strip_extras<'dist>(graph: &IntermediatePetGraph<'dist>) -> RequirementsTxtGr
let index = *entry.get();
let node: &mut RequirementsTxtDist = &mut next[index];
node.extras.clear();
// Consider:
// ```
// foo[bar]==1.0.0; sys_platform == 'linux'
// foo==1.0.0; sys_platform != 'linux'
// ```
// In this case, we want to write `foo==1.0.0; sys_platform == 'linux' or sys_platform == 'windows'`
node.markers.or(dist.markers);
}
std::collections::hash_map::Entry::Vacant(entry) => {
let index = next.add_node(dist.clone());

View file

@ -9130,7 +9130,7 @@ fn universal_disjoint_extra() -> Result<()> {
# via flask
click==8.1.7 ; sys_platform == 'darwin' or sys_platform == 'linux'
# via flask
flask==3.0.2 ; sys_platform == 'linux'
flask==3.0.2 ; sys_platform == 'darwin' or sys_platform == 'linux'
# via -r requirements.in
itsdangerous==2.1.2 ; sys_platform == 'darwin' or sys_platform == 'linux'
# via flask
@ -14554,3 +14554,38 @@ fn compile_preserve_requires_python_split() -> Result<()> {
Ok(())
}
/// Regression test for <https://github.com/astral-sh/uv/issues/11279#issuecomment-2640270189>
#[test]
fn markers_on_extra_packages() -> Result<()> {
let context = TestContext::new("3.12");
let requirements_in = context.temp_dir.child("requirements.in");
requirements_in.write_str(indoc! {"
psycopg[binary]; platform_python_implementation != 'PyPy'
psycopg; platform_python_implementation == 'PyPy'
"})?;
uv_snapshot!(context
.pip_compile()
.arg("--universal")
.arg("requirements.in"), @r###"
success: true
exit_code: 0
----- stdout -----
# This file was autogenerated by uv via the following command:
# uv pip compile --cache-dir [CACHE_DIR] --universal requirements.in
psycopg==3.1.18
# via -r requirements.in
psycopg-binary==3.1.18 ; implementation_name != 'pypy' and platform_python_implementation != 'PyPy'
# via psycopg
typing-extensions==4.10.0
# via psycopg
tzdata==2024.1 ; sys_platform == 'win32'
# via psycopg
----- stderr -----
Resolved 4 packages in [TIME]
"###);
Ok(())
}