-
Notifications
You must be signed in to change notification settings - Fork 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
PEP 440 Version and Specifiers #1894
Conversation
Oh yea, and all the actual changes to pip are in dstufft@09f612c |
Oh one other thing about this. The packaging library (and pip's extensions of it) properly handles combining the same requirement from two different packages. This PR doesn't fix that longstanding issue in pip, but it could be leveraged to do so. |
neat!
i.e. combining top-level "double requirements"? and not just doing "first found wins" for sub-requirements? |
does this indirectly handle #1505? or no? one of drivers of that was versions like how would that get handled here? |
Yes on combining requirements. This doesn't handle it yet, but basically it'd just need code so that if you have two reqs you do So the latest round of PEP 440 (which this implements) uses This does not give some global way to just blindly allow non PEP 440 versions however it also does not have the We do not attempt to sort versions that we cannot parse with PEP 440, which is why you can only pin to a non PEP 440 version and you can't do anything else. |
Obviously there are still edge cases broken in the PR, hence it being a proof of concept. |
hmm, no attempt at sorting? this will break stuff where people want to sort pkg_resources-style fork versions (i.e "1.3-fork1"). We have forks like this at my job.
so, only an escape hatch for your own top-level requirements? #1505 was imagining a |
To be specific, if you use |
yes, I got that, just thinking of legacy packaging. |
The Here's the compatibility numbers by the way:
An option we could do is if we can't find any PEP 440 compatible versions is fall back to One of the important things here I think, is that if we can't parse a version then we really don't know how it should sort. An extreme example is which is the latest version, It's possible that PEP 440 could be expanded to treat |
Those numbers are from what's on PyPI btw, which of course is unlikely to have many forks. |
Paging @ncoghlan to get an opinion on normalizing -anything to +anything as long as it doesn't match one of the pre-release normalizations. |
I quite like the idea of trying to use the more permissive local version
Only if even the mostly-lexical sorting offered by local versions failed |
Ok, I'll see about implementing that in packaging and seeing what that does to our compatibility. |
I started with compatibility numbers that looked like: $ invoke check.pep440 --cached
Total Version Compatibility: 233644/241356 (96.80%)
Total Sorting Compatibility (Unfiltered): 43231/45649 (94.70%)
Total Sorting Compatibility (Filtered): 45625/45649 (99.95%)
Projects with No Compatible Versions: 800/45649 (1.75%)
Projects with Differing Latest Version: 1169/45649 (2.56%) Then I made the it so that $ invoke check.pep440 --cached
Total Version Compatibility: 237764/241356 (98.51%)
Total Sorting Compatibility (Unfiltered): 44379/45649 (97.22%)
Total Sorting Compatibility (Filtered): 45526/45649 (99.73%)
Projects with No Compatible Versions: 398/45649 (0.87%)
Projects with Differing Latest Version: 576/45649 (1.26%) Then I made it so that $ invoke check.pep440 --cached
Total Version Compatibility: 238325/241356 (98.74%)
Total Sorting Compatibility (Unfiltered): 44501/45649 (97.49%)
Total Sorting Compatibility (Filtered): 45509/45649 (99.69%)
Projects with No Compatible Versions: 343/45649 (0.75%)
Projects with Differing Latest Version: 508/45649 (1.11%) Then I made it so that we allow a $ invoke check.pep440 --cached
Total Version Compatibility: 238684/241356 (98.89%)
Total Sorting Compatibility (Unfiltered): 44562/45649 (97.62%)
Total Sorting Compatibility (Filtered): 45488/45649 (99.65%)
Projects with No Compatible Versions: 292/45649 (0.64%)
Projects with Differing Latest Version: 464/45649 (1.02%) Then I made it so that we allow a $ invoke check.pep440 --cached
Total Version Compatibility: 238879/241356 (98.97%)
Total Sorting Compatibility (Unfiltered): 44618/45649 (97.74%)
Total Sorting Compatibility (Filtered): 45495/45649 (99.66%)
Projects with No Compatible Versions: 278/45649 (0.61%)
Projects with Differing Latest Version: 438/45649 (0.96%) I'm not sure what else we can add to get even more compatible. This brings us back to the question of how compatible is compatible enough. So far every change slightly lowers our filtered sorting compatibility (this tells us how much alike we're sorting similar to Here's the list of versions which I still treat as invalid: https://gist.github.com/dstufft/c24bcacef202a3837600. I really only want to consider things that can be implemented by adjusting the regex/parsing and nothing that requires transforming the version itself. I think they are way easier to explain and implement and are far less likely to have bugs related to apply stacks of text transforms. |
Also I'm not sure which of the above modifications we want to allow, all of them? some of them? |
Here's another thing I tried, I allowed $ invoke check.pep440 --cached
Total Version Compatibility: 240446/241356 (99.62%)
Total Sorting Compatibility (Unfiltered): 44884/45649 (98.32%)
Total Sorting Compatibility (Filtered): 45301/45649 (99.24%)
Projects with No Compatible Versions: 171/45649 (0.37%)
Projects with Differing Latest Version: 304/45649 (0.67%) |
To be specific, the |
Another thing I tried, I allow $ invoke check.pep440 --cached
Total Version Compatibility: 238967/241356 (99.01%)
Total Sorting Compatibility (Unfiltered): 44634/45649 (97.78%)
Total Sorting Compatibility (Filtered): 45483/45649 (99.64%)
Projects with No Compatible Versions: 271/45649 (0.59%)
Projects with Differing Latest Version: 432/45649 (0.95%) The same rule, but including the dangerous thing above: $ invoke check.pep440 --cached
Total Version Compatibility: 240533/241356 (99.66%)
Total Sorting Compatibility (Unfiltered): 44903/45649 (98.37%)
Total Sorting Compatibility (Filtered): 45294/45649 (99.22%)
Projects with No Compatible Versions: 165/45649 (0.36%)
Projects with Differing Latest Version: 296/45649 (0.65%) |
Another thing I thought, this is another one that I'm not sure about. I don't think it's as dangerous as the other one though. An implied leading "0" on any version which does not have a leading numeral for the release segment. This allows versions like Compatibility numbers with this also applied are (without the above dangerous change): $ invoke check.pep440 --cached
Total Version Compatibility: 239196/241356 (99.11%)
Total Sorting Compatibility (Unfiltered): 44740/45649 (98.01%)
Total Sorting Compatibility (Filtered): 45481/45649 (99.63%)
Projects with No Compatible Versions: 209/45649 (0.46%)
Projects with Differing Latest Version: 367/45649 (0.80%) With the dangerous change: $ invoke check.pep440 --cached
Total Version Compatibility: 240768/241356 (99.76%)
Total Sorting Compatibility (Unfiltered): 45007/45649 (98.59%)
Total Sorting Compatibility (Filtered): 45287/45649 (99.21%)
Projects with No Compatible Versions: 102/45649 (0.22%)
Projects with Differing Latest Version: 233/45649 (0.51%) |
Another thing: Allowing Without the "dangerous" change: $ invoke check.pep440 --cached
Total Version Compatibility: 239714/241356 (99.32%)
Total Sorting Compatibility (Unfiltered): 44797/45649 (98.13%)
Total Sorting Compatibility (Filtered): 45422/45649 (99.50%)
Projects with No Compatible Versions: 170/45649 (0.37%)
Projects with Differing Latest Version: 328/45649 (0.72%) With the "dangerous" change: $ invoke check.pep440 --cached
Total Version Compatibility: 240878/241356 (99.80%)
Total Sorting Compatibility (Unfiltered): 45019/45649 (98.62%)
Total Sorting Compatibility (Filtered): 45280/45649 (99.19%)
Projects with No Compatible Versions: 90/45649 (0.20%)
Projects with Differing Latest Version: 223/45649 (0.49%) |
Oh, a side effect of the implicit leading |
Ok, another change. In the release segment allow omiting a numeral anywhere which is an implicit Without "dangerous" change: $ invoke check.pep440 --cached
Total Version Compatibility: 239747/241356 (99.33%)
Total Sorting Compatibility (Unfiltered): 44822/45649 (98.19%)
Total Sorting Compatibility (Filtered): 45422/45649 (99.50%)
Projects with No Compatible Versions: 163/45649 (0.36%)
Projects with Differing Latest Version: 321/45649 (0.70%) With "dangerous" change: $ invoke check.pep440 --cached
Total Version Compatibility: 240907/241356 (99.81%)
Total Sorting Compatibility (Unfiltered): 45043/45649 (98.67%)
Total Sorting Compatibility (Filtered): 45283/45649 (99.20%)
Projects with No Compatible Versions: 83/45649 (0.18%)
Projects with Differing Latest Version: 216/45649 (0.47%) |
Scanning the list of "still incompatible" options, I see the following major points:
So, I like most of your changes, except:
|
And Another change! This time, allow "empty" segments in the local version, essentially allowing Without "dangerous" change: $ invoke check.pep440 --cached
Total Version Compatibility: 239843/241356 (99.37%)
Total Sorting Compatibility (Unfiltered): 44875/45649 (98.30%)
Total Sorting Compatibility (Filtered): 45420/45649 (99.50%)
Projects with No Compatible Versions: 157/45649 (0.34%)
Projects with Differing Latest Version: 310/45649 (0.68%) With "dangerous" change: $ invoke check.pep440 --cached
Total Version Compatibility: 241004/241356 (99.85%)
Total Sorting Compatibility (Unfiltered): 45097/45649 (98.79%)
Total Sorting Compatibility (Filtered): 45282/45649 (99.20%)
Projects with No Compatible Versions: 76/45649 (0.17%)
Projects with Differing Latest Version: 204/45649 (0.45%) |
Now I really am out of ideas :) |
So, the reason I treated |
Ok, so that's two people who don't like the implicit |
Could you put together two lists? The versions from the "no compatible versions" projects and the old selection & new selection for the "latest version changed" projects? |
Ah, if the "r" is referring to svn revisions, then yes, it would count as a "dev" release. I don't really mind including that one, since it would only change the sort order if that was used together with a/b/c style numbering. |
Yep, I think this one looks like a winner. It would be nice to support the "YYYY-MM-DD" date based releases along with the "-N" patch level notation, but I agree that lets too much nonsense through and makes things overly confusing. |
And yes, it would be good to get setuptools applying the normalisation (and complaining about incompatible versions) before we publish a corresponding version of pip. It would also give us an easier way to advise owners of incompatible packages to update their version numbers. |
Ok I lied, I have one more possible thing. Techincally What we did not try, is normalizing This should not be ambiguous if we only allow the A quick look at what this does on PyPI is it brings our numbers down to:
This adds an additional 123 projects which couldn't be installed previously, but now can and reduces the number of projects which can be installed, but which the latest version is silently different from 282 to 210. It also gives us the last remaining style of version from |
I checked the difference between allowing only |
Allowing a trailing "-N" by normalising it to ".postN" sounds good to me. I think that change will also greatly increase the odds of the new answer being better than the pkg_resources answer when they're different. |
72407fa
to
e7dfc87
Compare
5ccc243
to
58cf39d
Compare
4ab614a
to
86a0a47
Compare
2ecce15
to
c4ac447
Compare
c4ac447
to
a83037f
Compare
a83037f
to
84377cd
Compare
84377cd
to
6f64d3e
Compare
PEP 440 Version and Specifiers
So basically this uses a slightly modified copy of pypa/packaging#1 to implement PEP 440 in pip. This is mostly a proof of concept for right now however it "works" in that I can install stuff successfully with it. It implements all of the specifiers from PEP 440 including
~=
,==X.*
, and===
. These likely cannot be used inside of an install_requires because setuptools does not support them however they can be used in a requirements.txt file and on the command line. Additionally they could also be used inside of a Wheel file. It does give the new semantics towards<
and>
as well as the semantics around local versions.Some notes for those not up to date on the latest PEP 440 draft:
1.0+debian3
) to be semantically equivalent to whatever the public version is (1.0
in the example). So1.0+debian3
is==1.0
.<
, and>
work smarter with regards towards pre-releases, so<3
does not match3.0.dev1
.===
operator which causes things to fall back to a simple case insensitive string comparison.There is probably lots of bugs and corner cases and the like (hence proof of concept) but I think it's pretty cool!