Skip to content

Versions are sorted by ASCII rather than version or commit date #6010

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

Closed
davidism opened this issue Jul 29, 2019 · 17 comments · Fixed by #6012
Closed

Versions are sorted by ASCII rather than version or commit date #6010

davidism opened this issue Jul 29, 2019 · 17 comments · Fixed by #6012
Labels
Accepted Accepted issue on our roadmap Improvement Minor improvement to code Support Support question

Comments

@davidism
Copy link

davidism commented Jul 29, 2019

Details

Expected Result

During the build and in the rendered docs popup, versions are sorted in version order, newest to oldest. Baring that, since slugs might not be valid versions (2.10.1 vs 2.10.x), version slugs should be sorted by commit date.

Actual Result

Versions are ASCII sorted, so 2.9.x ends up greater than 2.10.x.


When building Jinja's docs, Pallets-Sphinx-Themes examines html_context["versions"] and html_context["current_version"], injected by RTD, to show a banner at the top of the page. This worked fine for our previous projects, like Flask, which had versions 1.0.x and 1.1.x. However, Jinja has 2.9.x and 2.10.x, and it became apparent that RTD was sorting these in ASCII order, which becomes inconsistent across ones and tens digits. This is problematic because we were relying on RTD to report versions in a consistent newest to oldest order.

This shows up in html_context["versions"]:

[
    ("master", "/en/master/"),
    ("2.9.x", "/en/2.9.x/"),
    ("2.10.x", "/en/2.10.x/"),
]

And in the versions popup:

jinja

Compare to Flask's version popup:

flask

The order is not consistent with version or commit date ordering.

@dojutsu-user dojutsu-user added the Support Support question label Jul 29, 2019
@humitos
Copy link
Member

humitos commented Jul 29, 2019

Hi @davidism! We are aware of this already.

We do sort the version using PEP440 (https://docs.readthedocs.io/en/stable/versions.html#how-we-envision-versions-working). Although, if the version does not follow this schema, it's ASCII sorted --as you found. In your case 2.9.x makes packaging.version.Version to fail when initialized and so Read the Docs consider it as a non-valid version number.

This issue was already reported at #5291 and there is an idea to track the commit date at #5649

I think that sorting by commit date won't work either, because your 1.0.x could have a more recent commit than 1.1.x, right?

I'm not sure what's the best path to follow here. Naming docs versions with x for the patch number is the way that I personally prefer, but I also found this issue.

@davidism
Copy link
Author

Hmm, I see what you mean with commit date. The way I handle sorting in the theme is a small wrapper that strips off a configured suffix first, so that they are valid sortable versions again.

@humitos
Copy link
Member

humitos commented Jul 29, 2019

Maybe we can fallback to numerical sorting if the version does not follow the PEP440 scheme with one of these proposal solution: https://stackoverflow.com/questions/2574080/sorting-a-list-of-dot-separated-numbers-like-software-versions --what do you think?

@humitos
Copy link
Member

humitos commented Jul 29, 2019

natsort seems to be what we want: https://pypi.org/project/natsort/#sorting-versions

@davidfischer
Copy link
Contributor

@humitos Are you proposing ripping out packaging.version.Version from

def parse_version_failsafe(version_string):
"""
Parse a version in string form and return Version object.
If there is an error parsing the string, ``None`` is returned.
:param version_string: version as string object (e.g. '3.10.1')
:type version_string: str or unicode
:returns: version object created from a string object
:rtype: packaging.version.Version
"""
if not isinstance(version_string, str):
uni_version = version_string.decode('utf-8')
else:
uni_version = version_string
try:
normalized_version = unicodedata.normalize('NFKD', uni_version)
ascii_version = normalized_version.encode('ascii', 'ignore')
final_form = ascii_version.decode('ascii')
return Version(final_form)
except (UnicodeError, InvalidVersion):
return None
and instead use natsort? We could definitely test that. Alternatively, this does seem common enough where we could replace .x and call parse_version_failsafe again.

@humitos
Copy link
Member

humitos commented Jul 29, 2019

@davidfischer No. I'm "thinking aloud without looking at the code" that we could fallback to natsort when the version is not parseable by packaging.version.Version. I haven't taken a deep look yet.

@davidfischer
Copy link
Contributor

I put one possible solution into #6012.

@humitos humitos added Accepted Accepted issue on our roadmap Improvement Minor improvement to code labels Jul 30, 2019
@ericholscher
Copy link
Member

This is now shipped, let me know if it's resolved 👍

@davidism
Copy link
Author

davidism commented Aug 8, 2019

I checked https://jinja.palletsprojects.com/. 2.10.x sorts above 2.9.x, but now master sorts last. Looking at the PR, I'm not sure why, and when I was looking at the code initially I thought there was a special case for master, so I'm not sure what happened.

@stsewd
Copy link
Member

stsewd commented Aug 8, 2019

@davidism you need to activate the master version that says "latest"

Screenshot_2019-08-07 Versions Read the Docs

@davidism
Copy link
Author

davidism commented Aug 8, 2019

Any chance since "latest" points to "master" that they both can sort higher? I've been deliberately using master so all docs versions would match branches, and it was sorting as expected before. #4672 is somewhat related to this choice, latest was fixed so that it wasn't reactivated on commits to master.

@stsewd
Copy link
Member

stsewd commented Aug 8, 2019

Any chance since "latest" points to "master" that they both can sort higher?

Internally rtd creates a version named latest that points to master (that's how it gets sorted). You are using the plane version of master.

it was sorting as expected before. #4672

My guess, like the other branches (2.x), master was failing too, so it was being sorted by the ascii value ('master' > '2.x') is True.

I haven't tried this, but I think maybe you can still have master as latest. Can you try going to advanced settings and select master in Default branch?
Screenshot_2019-08-07 Edit Advanced Project Settings Read the Docs

@stsewd
Copy link
Member

stsewd commented Aug 8, 2019

I haven't tried this, but I think maybe you can still have master as latest. Can you try going to advanced settings and select master in Default branch?

Nope, that doesn't work.

We should treat master and trunk (whatever master is in other VCS) like we do with latest, or show the real version name in the selector, not the slug

@stsewd
Copy link
Member

stsewd commented Aug 8, 2019

Changing the slug to the real name is a big chance, I'm making a patch for the first option

@stsewd
Copy link
Member

stsewd commented Aug 8, 2019

PR at #6049

@stsewd
Copy link
Member

stsewd commented Aug 8, 2019

@davidism master should be sorted first now

@davidism
Copy link
Author

davidism commented Aug 8, 2019

Awesome, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Accepted Accepted issue on our roadmap Improvement Minor improvement to code Support Support question
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants