-
Notifications
You must be signed in to change notification settings - Fork 30
CEP XXXX: "Version strings and their ordering" #132
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
base: main
Are you sure you want to change the base?
Conversation
|
|
||
| - Integers are compared numerically. | ||
| - Strings are compared lexicographically, case-insensitive. The substring `dev` is always smaller. | ||
| - Strings are considered smaller than integers, except for `post`, which is always greater. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe that strings and number can never be compared, because of this:
When a component starts with a letter, the fill value
0is inserted.
So, starting at 0, even indices will always contain a number and odd always a string
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, I think you are right here 🤔 I wonder if this bit in the docs didn't get updated once they introduced the "fill value" solution.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, given this script
from conda.models.version import VersionOrder as V
for version in (
"0.dev1beta1.b1aa",
"0.rc1BETA1.b1aa",
"0.post0beta1.b1aa",
"0.post1beta1.b1aa",
"0post1beta1.b1aa",
):
print(version, "->\n ", V(version).version)We get:
0.dev1beta1.b1aa ->
[[0], [0], [0, 'DEV', 1, 'beta', 1], [0, 'b', 1, 'aa']]
0.rc1BETA1.b1aa ->
[[0], [0], [0, 'rc', 1, 'beta', 1], [0, 'b', 1, 'aa']]
0.post0beta1.b1aa ->
[[0], [0], [0, inf, 0, 'beta', 1], [0, 'b', 1, 'aa']]
0.post1beta1.b1aa ->
[[0], [0], [0, inf, 1, 'beta', 1], [0, 'b', 1, 'aa']]
0post1beta1.b1aa -> # I really hate this one
[[0], [0, inf, 1, 'beta', 1], [0, 'b', 1, 'aa']]See how dev is special cased to uppercase (every other string gets lowercased!), and post gets converted to inf. I guess this is a hack to make it work with Python's default ordering (uppercase sorts before lowercase, and inf is always larger). However, we do see a case here where letters and numbers need to be compared (albeit after internal conversions, so I don't think the rule applies and I guess we can remove it from the spec? But it doesn't hurt to keep it either).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think both the DEV and inf here should be considered implementation details.
In mamba this is handled with a custom comparison function for literals (it checks a few special cases and then defers to string comparison). In both C++ (mamba) and Rust (rattler), comparing a number and a string is not the "naive" thing to do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm also surprised about this. Pretty sure we don't have this behaviour in mamba. Should this be part of the spec? what should be the rule?
0post1beta1.b1aa -> # I really hate this one
[[0], [0, inf, 1, 'beta', 1], [0, 'b', 1, 'aa']]
☝️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That first [0] is the omitted 0! epoch, which is covered in the spec, I think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ha yes sorry, I got confused (the epoch is stored separately in mamba). I thought it was the first segment and that there was some sort of rule that "post" cannot be in the first segment...
| - Strings are compared lexicographically, case-insensitive. The substring `dev` is always smaller. | ||
| - Strings are considered smaller than integers, except for `post`, which is always greater. | ||
| - When a component has no correspondent, the missing component is assumed to be `0`. | ||
| - Local versions are only compared when the main versions are identical. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: if we could find some example of how local versions are used out in the wild
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found these in conda-forge/(osx-arm64,noarch):
$ conda search "*[version='*+*']"
Loading channels: done
# Name Version Build Channel
py-sirius-ms 2.1+sirius6.0.3 pyhd8ed1ab_0 conda-forge
py-sirius-ms 2.1+sirius6.0.4 pyhd8ed1ab_0 conda-forge
py-sirius-ms 2.1+sirius6.0.5 pyhd8ed1ab_0 conda-forge
py-sirius-ms 2.1+sirius6.0.6 pyhd8ed1ab_0 conda-forge
py-sirius-ms 2.1+sirius6.0.7 pyhd8ed1ab_0 conda-forge
py-sirius-ms 2.1+sirius6.0.7 pyhd8ed1ab_1 conda-forge
py-sirius-ms 3.0+sirius6.1.0 pyhd8ed1ab_0 conda-forge
py-sirius-ms 3.0.1+sirius6.1.0 pyhd8ed1ab_0 conda-forge
py-sirius-ms 3.1+sirius6.1.1 pyhd8ed1ab_0 conda-forge
r-sirius-ms 2.1+sirius6.0.4 r44h57928b3_1 conda-forge
r-sirius-ms 2.1+sirius6.0.4 r44h694c41f_1 conda-forge
r-sirius-ms 2.1+sirius6.0.4 r44ha770c72_1 conda-forge
r-sirius-ms 2.1+sirius6.0.5 r44h57928b3_1 conda-forge
r-sirius-ms 2.1+sirius6.0.5 r44h694c41f_1 conda-forge
r-sirius-ms 2.1+sirius6.0.5 r44ha770c72_1 conda-forge
r-sirius-ms 2.1+sirius6.0.6 r44h57928b3_1 conda-forge
r-sirius-ms 2.1+sirius6.0.6 r44h694c41f_1 conda-forge
r-sirius-ms 2.1+sirius6.0.6 r44ha770c72_1 conda-forge
r-sirius-ms 2.1+sirius6.0.7 r44h57928b3_0 conda-forge
r-sirius-ms 2.1+sirius6.0.7 r44h57928b3_1 conda-forge
r-sirius-ms 2.1+sirius6.0.7 r44h694c41f_0 conda-forge
r-sirius-ms 2.1+sirius6.0.7 r44h694c41f_1 conda-forge
r-sirius-ms 2.1+sirius6.0.7 r44ha770c72_0 conda-forge
r-sirius-ms 2.1+sirius6.0.7 r44ha770c72_1 conda-forge
r-sirius-ms 3.0.1+sirius6.1.0 r44h57928b3_0 conda-forge
r-sirius-ms 3.0.1+sirius6.1.0 r44h694c41f_0 conda-forge
r-sirius-ms 3.0.1+sirius6.1.0 r44ha770c72_0 conda-forge
r-sirius-ms 3.1+sirius6.1.1 r44h57928b3_0 conda-forge
r-sirius-ms 3.1+sirius6.1.1 r44h694c41f_0 conda-forge
r-sirius-ms 3.1+sirius6.1.1 r44ha770c72_0 conda-forge
r-sirius-ms 3.1+sirius6.1.1 r45h57928b3_1 conda-forge
r-sirius-ms 3.1+sirius6.1.1 r45h694c41f_1 conda-forge
r-sirius-ms 3.1+sirius6.1.1 r45ha770c72_1 conda-forge
typst-test 0.0.0.post105+699b871 h6e96688_0 conda-forge
typst-test 0.0.0.post105+699b871 h6e96688_1 conda-forge
typst-test 0.0.0.post106+2b4e689 h6e96688_0 conda-forge
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added it in a new Examples section.
Co-authored-by: Jean-Christophe Morin <[email protected]>
|
|
||
| ## Examples | ||
|
|
||
| The ordering specification results in the following versions sorted in this way: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could use a comment/example of how non-empty local versions are always ordered after (right?!) the ones with empty local versions.
Checklist for submitter
cep-0000.mdnamedcep-XXXX.mdin the root level.