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

Different version pins compared to pip-compile when multiple equivalent resolutions are possible #7575

Closed
jf2 opened this issue Sep 20, 2024 · 2 comments
Assignees
Labels
question Asking for clarification or support

Comments

@jf2
Copy link

jf2 commented Sep 20, 2024

I've been trying out uv to use as replacement for my workflows and so far, am very impressed by how much has been achieved in such a short period of time.

Problem Description and Reproduction

The issue below is somewhat tricky, as the behavior is not wrong per se, but the outputs are different when comparing with pip-compile output. To demonstrate, below the simple requirements manifest:

numpy
pandas < 2.2

Using uv

uv pip compile requirements.in

Which yields the following output:

numpy==2.1.1
    # via
    #   -r requirements.in
    #   pandas
pandas==2.1.1
    # via -r requirements.in
...

Using pip-compile

pip-compile requirements.in

Which yields the following output:

numpy==1.26.4

    # via
    #   -r test-requirements.in
    #   pandas
pandas==2.1.4
    # via -r test-requirements.in
...

I think that both resolutions are satisfying constraints. The original sin is that pandas 2.1.1 did not limit numpy < 2, whereas 2.1.4 does. uv first takes numpy and finds the latest possible version. It then tries to find a pandas version for which the numpy == 2.1.1 is satisfied, which correctly resolves to pandas == 2.1.1 (since this one doesn't limit numpy below 2 yet). pip-compile appears to resolve it differently, but also correctly.

Interestingly, if you change the order in the requirements manifest file:

pandas < 2.2
numpy

then uv also yields the same output as pip-compile. So this is now a tangential issue whereby the order of dependencies influences how the versions are resolved (should that be the case?)

How to Fix

  • Make version resolution independent of the dependency order (possibly enforcing just by sorting the dependency list after parsing)
  • (opinionated) When dependency A == vA limits dependency B < vB, do not check whether a lower version of A (A < vA) satisfies B == vB.

System

  • pip-compile: 7.4.1
  • uv: 0.4.8
  • Python: 3.11.7
  • OS: AlmaLinux 8.9

Additional clarifications

This particular can easily be fixed by removing numpy as a dependency, which will ensure equivalent output to pip-compile. In this particular case it's easy, since the dependency list is easy. In more general case, an app might specify dependency A and B as they are both needed in the project, with the author being fully oblivious to the fact that A also depends on B.

@charliermarsh
Copy link
Member

Thanks for the clear write-up. I think this is roughly by-design. Absent other information, we prioritize dependencies in the order in which they're provided. See, e.g., #5474. IMO, if you want to ensure that you get a certain resolution, the best thing to do is add an additional constraint. (It's also documented, see #6211.)

@charliermarsh charliermarsh added the question Asking for clarification or support label Sep 20, 2024
@charliermarsh charliermarsh self-assigned this Sep 20, 2024
@jf2
Copy link
Author

jf2 commented Sep 20, 2024

Yes, after reading through some comments and issues I’ve come to the same conclusion, being that this behaviour is intended.

I think we can close this issue, it will possibly serve as a reference.

@jf2 jf2 closed this as completed Sep 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Asking for clarification or support
Projects
None yet
Development

No branches or pull requests

2 participants