But that is, in my view, an extremely liberal interpretation of “explicitly requesting” something, and it’s definitely not covered in the spec. And it could easily have been - a simple example could have been given stating that “
>=1.0a1
is an example of the user explicitly requesting pre-releases”.
Well, one thing I would say is user workflows rely on this interpretation, e.g.: https://discuss.python.org/t/handling-of-pre-releases-when-backtracking/40505/24. So this would be a breaking change in more than a nuanced technical way.
There is an argument that this line explicitly supports the current interpretation:
Allowing pre-releases that are earlier than, but not equal to a specific pre-release may be accomplished by using <V.rc1 or similar.
As discussed here: https://github.com/pypa/packaging/issues/788
Well, resolvelib needs to check if a candidate matches a specifier. That’s the obvious example.
Filtering is how pip gets a list of candidate versions from the index (the finder). That’s where we include (or don’t) pre-releases. Matching is what the resolver uses to confirm if a candidate matches a newly discovered constraint.
Yeah, and this might be a good example of why matching semantics are not useful.
So first of all by “resolvelib” we’re actually talking about the pip resolvelib provider (as an aside resolvelib proper is super generic and has no concept of prereleases, or even versions or specifiers, it asks the provider, that given a bunch of constraints, “are there any candidates?”).
Within the pip resolvelib provider every time it uses the match semantics (i.e. Specifier.contains
) it has to use prereleases=True
, and rely on the the filtering semantics during collection to get the right version candidates:
- https://github.com/pypa/pip/blob/24.3.1/src/pip/_internal/resolution/resolvelib/base.py#L57
- https://github.com/pypa/pip/blob/24.3.1/src/pip/_internal/resolution/resolvelib/factory.py#L291
- https://github.com/pypa/pip/blob/24.3.1/src/pip/_internal/resolution/resolvelib/requirements.py#L119
- https://github.com/pypa/pip/blob/24.3.1/src/pip/_internal/resolution/resolvelib/requirements.py#L198
- https://github.com/pypa/pip/blob/24.3.1/src/pip/_internal/resolution/resolvelib/requirements.py#L207
Actually, everywhere pip uses Specifier.contains
it uses prereleases=True
, probably for the same reason.
This does seem to me that match semantics needs to be “fixed”, or removed, and filter semantics need to be preserved. But perhaps I am drawing the wrong conclusions.