You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add incompatibility from proxy to base package (#15200)
Add an incompatibility that lets pubgrub skip of marker packages when
the base package already has an incompatible version to improve the
error messages (#15199).
The change is also a small perf improvement. Overall this should be able
to improve performance in slow cases by avoiding trying proxy package
versions that are impossible anyway, for a (ideally very small cost) for
tracking the additional incompatibility and tracking the base package
for each proxy package.
```
$ hhyperfine --warmup 2 "uv pip compile --universal scripts/requirements/airflow.in" "target/release/uv pip compile --universal scripts/requirements/airflow.in"
Benchmark 1: uv pip compile --universal scripts/requirements/airflow.in
Time (mean ± σ): 145.5 ms ± 3.9 ms [User: 154.7 ms, System: 140.7 ms]
Range (min … max): 139.2 ms … 153.4 ms 20 runs
Benchmark 2: target/release/uv pip compile --universal scripts/requirements/airflow.in
Time (mean ± σ): 128.7 ms ± 5.5 ms [User: 141.9 ms, System: 137.3 ms]
Range (min … max): 121.8 ms … 142.0 ms 23 runs
Summary
target/release/uv pip compile --universal scripts/requirements/airflow.in ran
1.13 ± 0.06 times faster than uv pip compile --universal scripts/requirements/airflow.in
```
This implementation is the basic version: When we see a proxy
`foo{...}>=x,<y` we add a dependency edge `foo{...}>=x,<y` ->
`foo>=x,<y`. There are several way to extend this, which likely help
more with performance than with error messages.
One idea is that if we see `foo{...}>=x,<y` but we already made a
selection for `foo==z` outside that range, we can insert a dependency
`foo{...}!=z` -> `foo!=z`. This avoids trying any version of the proxy
package except the version that matches our previous selection.
Another is that if we see a dependency `foo>=x,<y`, we also add
`foo{...}>=x,y` -> `foo>=x,<y`. This allows backtracking beyond `foo`
immediately if all version of `foo{...}>=x,<y` are incompatible, since
`foo{...}>=x,<y` incompatible -> `foo>=x,<y` incompatible -> the package
that depended of `foo>=x,<y` is incompatible.
The cost for each of these operations is tracking an additional
incompatibility per virtual package. An alternative approach is to only
add the incompatibility lazily, only when we've tried several version of
the virtual package already. This needs to be weighed of with the better
error messages that the incompatibility gives, we unfortunately have
only few large reference examples.
Requires astral-sh/pubgrub#45Closes#15199
╰─▶ Because only datasets<=2.18.0 is available and your project depends on datasets>=2.19, we can conclude that your project's requirements are unsatisfiable.
13106
+
╰─▶ Because your project depends on datasets<2.19 and datasets>=2.19, we can conclude that your project's requirements are unsatisfiable.
╰─▶ Because only project{sys_platform == 'win32'}<=0.1 is available and your project depends on itself at an incompatible version (project{sys_platform == 'win32'}>0.1), we can conclude that your project's requirements are unsatisfiable.
26796
+
╰─▶ Because your project depends on itself at an incompatible version (project{sys_platform == 'win32'}>0.1), we can conclude that your project's requirements are unsatisfiable.
26797
26797
26798
26798
hint: The project `project` depends on itself at an incompatible version. This is likely a mistake. If you intended to depend on a third-party package named `project`, consider renaming the project `project` to avoid creating a conflict.
× No solution found when resolving dependencies for split (markers: python_full_version >= '3.11'):
29968
-
╰─▶ Because only the following versions of numpy{python_full_version >= '3.10'} are available:
29969
-
numpy{python_full_version >= '3.10'}<=1.21.0
29970
-
numpy{python_full_version >= '3.10'}==1.21.1
29971
-
numpy{python_full_version >= '3.10'}==1.21.2
29972
-
numpy{python_full_version >= '3.10'}==1.21.3
29973
-
numpy{python_full_version >= '3.10'}==1.21.4
29974
-
numpy{python_full_version >= '3.10'}==1.21.5
29975
-
numpy{python_full_version >= '3.10'}==1.21.6
29976
-
numpy{python_full_version >= '3.10'}==1.22.0
29977
-
numpy{python_full_version >= '3.10'}==1.22.1
29978
-
numpy{python_full_version >= '3.10'}==1.22.2
29979
-
numpy{python_full_version >= '3.10'}==1.22.3
29980
-
numpy{python_full_version >= '3.10'}==1.22.4
29981
-
numpy{python_full_version >= '3.10'}==1.23.0
29982
-
numpy{python_full_version >= '3.10'}==1.23.1
29983
-
numpy{python_full_version >= '3.10'}==1.23.2
29984
-
numpy{python_full_version >= '3.10'}==1.23.3
29985
-
numpy{python_full_version >= '3.10'}==1.23.4
29986
-
numpy{python_full_version >= '3.10'}==1.23.5
29987
-
numpy{python_full_version >= '3.10'}==1.24.0
29988
-
numpy{python_full_version >= '3.10'}==1.24.1
29989
-
numpy{python_full_version >= '3.10'}==1.24.2
29990
-
numpy{python_full_version >= '3.10'}==1.24.3
29991
-
numpy{python_full_version >= '3.10'}==1.24.4
29992
-
numpy{python_full_version >= '3.10'}==1.25.0
29993
-
numpy{python_full_version >= '3.10'}==1.25.1
29994
-
numpy{python_full_version >= '3.10'}==1.25.2
29995
-
numpy{python_full_version >= '3.10'}==1.26.0
29996
-
numpy{python_full_version >= '3.10'}==1.26.1
29997
-
numpy{python_full_version >= '3.10'}==1.26.2
29998
-
numpy{python_full_version >= '3.10'}==1.26.3
29999
-
numpy{python_full_version >= '3.10'}==1.26.4
30000
-
and pandas==1.5.3 depends on numpy{python_full_version >= '3.10'}>=1.21.0, we can conclude that pandas==1.5.3 depends on numpy>=1.21.0.
30001
-
And because your project depends on numpy==1.20.3 and pandas==1.5.3, we can conclude that your project's requirements are unsatisfiable.
29968
+
╰─▶ Because pandas==1.5.3 depends on numpy{python_full_version >= '3.10'}>=1.21.0 and your project depends on numpy==1.20.3, we can conclude that your project and pandas==1.5.3 are incompatible.
29969
+
And because your project depends on pandas==1.5.3, we can conclude that your project's requirements are unsatisfiable.
30002
29970
30003
29971
hint: While the active Python version is 3.9, the resolution failed for other Python versions supported by your project. Consider limiting your project's supported Python versions using `requires-python`.
× No solution found when resolving dependencies for split (markers: sys_platform == 'exotic'):
30222
-
╰─▶ Because only the following versions of numpy{sys_platform == 'exotic'} are available:
30223
-
numpy{sys_platform == 'exotic'}<=1.24.0
30224
-
numpy{sys_platform == 'exotic'}==1.24.1
30225
-
numpy{sys_platform == 'exotic'}==1.24.2
30226
-
numpy{sys_platform == 'exotic'}==1.24.3
30227
-
numpy{sys_platform == 'exotic'}==1.24.4
30228
-
numpy{sys_platform == 'exotic'}==1.25.0
30229
-
numpy{sys_platform == 'exotic'}==1.25.1
30230
-
numpy{sys_platform == 'exotic'}==1.25.2
30231
-
numpy{sys_platform == 'exotic'}>1.26
30232
-
and your project depends on numpy{sys_platform == 'exotic'}>=1.24,<1.26, we can conclude that your project depends on numpy>=1.24.0,<=1.25.2.
30233
-
And because your project depends on numpy>=1.26, we can conclude that your project's requirements are unsatisfiable.
30190
+
╰─▶ Because your project depends on numpy{sys_platform == 'exotic'}>=1.24,<1.26 and numpy>=1.26, we can conclude that your project's requirements are unsatisfiable.
30234
30191
30235
30192
hint: The resolution failed for an environment that is not the current one, consider limiting the environments with `tool.uv.environments`.
× No solution found when resolving dependencies for split (markers: python_full_version < '3.14' and sys_platform == 'other'):
31688
+
╰─▶ Because your project depends on anyio{sys_platform == 'other'} and anyio{python_full_version < '3.14'}>=4.4.0, we can conclude that your project's requirements are unsatisfiable.
31689
+
31690
+
hint: The resolution failed for an environment that is not the current one, consider limiting the environments with `tool.uv.environments`.
╰─▶ Because package-a==1.0.0 depends on package-c<2.0.0 and package-b==1.0.0 depends on package-c>=2.0.0, we can conclude that package-a{sys_platform == 'linux'}==1.0.0 and package-b{sys_platform == 'darwin'}==1.0.0 are incompatible.
3151
+
╰─▶ Because package-a==1.0.0 depends on package-c<2.0.0 and package-b==1.0.0 depends on package-c>=2.0.0, we can conclude that package-b==1.0.0 and package-a{sys_platform == 'linux'}==1.0.0 are incompatible.
3152
3152
And because your project depends on package-a{sys_platform == 'linux'}==1.0.0 and package-b{sys_platform == 'darwin'}==1.0.0, we can conclude that your project's requirements are unsatisfiable.
╰─▶ Because package-a==1.0.0 depends on package-c{sys_platform == 'linux'}<2.0.0 and only the following versions of package-c{sys_platform == 'linux'} are available:
3224
-
package-c{sys_platform == 'linux'}==1.0.0
3225
-
package-c{sys_platform == 'linux'}>2.0.0
3226
-
we can conclude that package-a==1.0.0 depends on package-c{sys_platform == 'linux'}==1.0.0.
3227
-
And because only package-c{sys_platform == 'darwin'}<=2.0.0 is available and package-b==1.0.0 depends on package-c{sys_platform == 'darwin'}>=2.0.0, we can conclude that package-a==1.0.0 and package-b==1.0.0 are incompatible.
3223
+
╰─▶ Because package-a==1.0.0 depends on package-c{sys_platform == 'linux'}<2.0.0 and package-b==1.0.0 depends on package-c{sys_platform == 'darwin'}>=2.0.0, we can conclude that package-a==1.0.0 and package-b==1.0.0 are incompatible.
3228
3224
And because your project depends on package-a==1.0.0 and package-b==1.0.0, we can conclude that your project's requirements are unsatisfiable.
0 commit comments