'How do transitive dependencies work in Python pip?

I have an automated machine build that installs a Python package (Package A) with a ton of dependencies (Packages X, Y, and Z). Package A doesn't pin the versions of packages X, Y, or Z, so even though I pin the version for package A, there have been a bunch of times when my builds fail because of a breaking update in package X.

To fix this, I was planning on making a requirements.txt file that pinned explicit versions of A, X, Y, and Z (rather than just A, which is what happens now). This should work assuming pip has proper support for both pinning and transitive dependency resolution.

It seems like this works with my current version of pip, but I've found a lot of conflicting information about how pip handles these things (eg, this thread with 100 comments talking about how pip dependency resolution isn't great).

So my questions:

  1. How does dependency resolution work in pip? If package A depends on X>=7, and my top-level requirements.txt specifies X==8, is it possible that pip would install X version 9 because it looks at A first and tries to get the most recent version of transitive dependencies?
  2. Is there a canonical / authoritative source describing how dependency resolution works in pip? The best I've been able to find is this page, but some of the comments I've seen online make it seem like that page isn't 100% correct where transitive dependencies are concerned.

Thanks!



Solution 1:[1]

pip introduced a new resolver in 20.3 and from 21.0 this is now the default resolver.

The new resolver fixes the inconsistencies outlined in your first question and not only that. When dependency packages are inconsistent (e.g. X>=7 and X==6) it will reject the installation all together.

The new resolver is resolvelib based so you can find details about the algorithm there but pip also updated the docs about dependency resolution with some details like the backtracking they do.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Andrea Bergonzo