-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
Ignore combinations of overrides whose intersection of markers is empty #4695
Ignore combinations of overrides whose intersection of markers is empty #4695
Conversation
f03f330
to
a8b5aa7
Compare
a8b5aa7
to
0ec6efa
Compare
Kudos, SonarCloud Quality Gate passed! 0 Bugs No Coverage information |
I am watching this hopping poetry gets improved on markers! However, let me share my concern regarding this specific PR. On the file (real use-case)
and
I observe much more overrides and longer install time than in the release 1.2.0a2 |
In order to be able to ignore irrelevant combinations of overrides, additional overrides for implicit "package not explicitly required" dependencies have to be added first. Otherwise, dependency resolution will be erroneous in some cases (see my second example in #4695 (comment)). Thus, the number of overrides can swing in both directions (less overrides if many of them can be ignored or more overrides if little of them can be ignored). This PR heavily relies on the recognition of empty markers. With further improvement of marker intersection/union/inversion, the number of overrides could often be reduced. python-poetry/poetry-core#226 is just a first step in that direction. Nevertheless, I think this PR makes dependency resolution certainly more correct, probably more robust (see linked issues with failing resolution) and hopefully more often faster than slower. I have analyzed your example. Its overrides originate in the following two multiple constraint dependencies:
Without PR Poetry is already able to ignore two of the portalocker dependencies because their python versions don't fit the project's requirement. Thus, there are two groups of multiple constraint dependencies each containing two dependencies. With PR The PR does not help in this case because there is no empty intersection of markers (assuming that the connection between In the first group, there is an implicit dependency that has to be considered: numpy is not explicitly required if In the second group, the implicit dependency is: portalocker is not explicitly required if If poetry would be able to simplify the marker of the implicit portalocker dependency and build the intersection with the project's python restriction ( |
thanks for that detailed clarification. I understand your patch may not help in this case, still increasing the number of costly operations is what worries me. Ideally I don't want the patch to be more expensive, or at least to have that communicated transparently. Per my understanding, you need to extend the logic to handle correctly some boundary cases. Do we really need that? Would they appear at al if the sub-dependencies were specified correctly? Following up on your thoughts on environmental markets, I have prepared a draft proposal #4956 (tests included) for early filtering packages. Instead of exponentially many combinations arising from splitting logic, we could have match less by early matching to the system/platform markers. Would be great to hear your opinion on this |
7e4af53
to
3dac1c3
Compare
3dac1c3
to
2e331b9
Compare
This is a workaround regarding Poetry's bug. If there are two identically constrained version specification, Poetry attempts to resolve dependency versions for every constraints combination, even if there's no intersection, which raises SolverProblemError. This behaviour isn't fixed yet but tracked in <python-poetry/poetry#3367> and will be resolved in <python-poetry/poetry#4695>.
…en building the marker intersection
2e331b9
to
bafff7d
Compare
This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Pull Request Check List
Resolves: #3367
Resolves: #4670
Resolves: #4870
Resolves: #4947
Currently, poetry tries all combinations for multiple-constraints-dependencies, even if markers exclude each other, which means that the concerning combination is not relevant. As a consequence, dependency resolution may fail even if there is a solution as in #3367 or dependency resolution will take unnecessarily long as in #4670.
Instead of considering all combinations, only combinations whose intersection of markers is not empty should be considered in the overrides.
In the following example, it is clear that only two of the four combinations are relevant (one with both dependencies for 3.6 and one with both dependencies for 3.7). Mixed combinations are not sensible.
However, there is one special case that has to be considered. Let's extend the previous example as follows:
Now, only considering the combinations whose intersection of markers is not empty is not enough because the constraint for lib2 for python 3.8 would be ignored. Thus, when determining the overrides, a dummy override with the inversion of the union of all markers of a dependency has to be added if there is no any marker dependency. In the example above, an empty constraint for lib1 with markers
not (python = "~3.6" or python = "~3.7")
(inversion of union of all markers of lib1) has to be added to the overrides. Thus, a solution for lib2 for python 3.8 can be found, not considering lib1 at all.I am aware that this solution heavily relies on poetry's ability to recognize if the intersection of markers is empty and that poetry probably will fail in this task for more complex markers. However, I think that even in that case the drawback of this solution are only some additional (unnecessary but harmless) dependency resolutions (for the dummy overrides).
PR python-poetry/poetry-core#226 improves poetry's ability to recognize if the intersection of markers is empty.