This is like pypa/pip#9071, but in a more generic sense. I suppose that this may ties to the algorithm, but I don't think the current algo requires this to be done. In short, before doing any resolution work, the resolver tries to find all the matches for each of the initial requirements:
|
for r in requirements: |
|
try: |
|
name, crit = self._merge_into_criterion(r, parent=None) |
|
except RequirementsConflicted as e: |
|
raise ResolutionImpossible(e.criterion.information) |
|
self.state.criteria[name] = crit |
|
|
|
self._r.starting() |
Now suppose I have [A, B>6], where the first match for A is version 42 and A 42 depends on B<9, and that Provider.find_matches([B>6]) and Provider.find_matches([B>6,B<9]) do totally different things (or that the result of the underlying expensive operations can't be shared), then Provider.find_matches([B>6]) is wasteful.
In pip's case, of course the majority of the time it's reaching to simple repositories, which has an index shared for all B, so with caching/memoization it's not a problem though.
This is like pypa/pip#9071, but in a more generic sense. I suppose that this may ties to the algorithm, but I don't think the current algo requires this to be done. In short, before doing any resolution work, the resolver tries to find all the matches for each of the initial requirements:
resolvelib/src/resolvelib/resolvers.py
Lines 280 to 287 in 73c6605
Now suppose I have
[A, B>6], where the first match for A is version 42 and A 42 depends onB<9, and thatProvider.find_matches([B>6])andProvider.find_matches([B>6,B<9])do totally different things (or that the result of the underlying expensive operations can't be shared), thenProvider.find_matches([B>6])is wasteful.In pip's case, of course the majority of the time it's reaching to simple repositories, which has an index shared for all B, so with caching/memoization it's not a problem though.