Skip to content

Addons: refactor sorting versions for flyout #11278

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

Merged
merged 2 commits into from
Apr 23, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 56 additions & 47 deletions readthedocs/projects/version_handling.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,23 +169,27 @@ def determine_stable_version(version_list):
return None


def sort_versions_python_packaging(version_list, latest_stable_at_beginning):
def sort_versions_generic(
version_list,
exception,
parse_version,
latest_stable_at_beginning,
raw_pattern=None,
):
"""
Sort Read the Docs versions list using ``packaging`` algorithm.
Sort Read the Docs versions based on ``parse_version`` function.

All the invalid version (raise ``InvalidVersion``) are added at the end
sorted alphabetically.
``parse_version`` function is called with ``slug=`` and ``raw_pattern=`` to decide how to sort them.

https://pypi.org/project/packaging/
https://packaging.python.org/en/latest/specifications/version-specifiers/
All the invalid version (raise ``exception``) are added at the end sorted alphabetically.
"""

alphabetically_sorted_version_list = sorted(
version_list,
key=operator.attrgetter("slug"),
)

initial_versions = []

valid_versions = []
invalid_versions = []
for i, version in enumerate(alphabetically_sorted_version_list):
Expand All @@ -196,8 +200,16 @@ def sort_versions_python_packaging(version_list, latest_stable_at_beginning):
continue

try:
valid_versions.append((version, Version(version.slug)))
except InvalidVersion:
valid_versions.append(
(
version,
parse_version(
slug=version.slug,
raw_pattern=raw_pattern,
),
)
)
except exception:
# When the version is invalid, we put it at the end while keeping
# the alphabetically sorting between the invalid ones.
invalid_versions.append((version, None))
Expand All @@ -207,19 +219,28 @@ def sort_versions_python_packaging(version_list, latest_stable_at_beginning):
+ sorted(valid_versions, key=operator.itemgetter(1), reverse=True)
+ invalid_versions
)

return [item[0] for item in all_versions if item[0] is not None]


def sort_versions_calver(version_list, latest_stable_at_beginning):
def sort_versions_python_packaging(version_list, latest_stable_at_beginning):
"""
Sort Read the Docs versions using CalVer pattern: ``YYYY.0M.0M``.
Sort Read the Docs versions list using ``packaging`` algorithm.

All the invalid version are added at the end sorted alphabetically.
All the invalid version (raise ``InvalidVersion``) are added at the end
sorted alphabetically.

https://pypi.org/project/packaging/
https://packaging.python.org/en/latest/specifications/version-specifiers/
"""
raw_pattern = "YYYY.0M.0D"
return sort_versions_custom_pattern(
version_list, raw_pattern, latest_stable_at_beginning

def parse_version(*args, slug=None, **kwargs):
return Version(slug)

return sort_versions_generic(
version_list,
InvalidVersion,
parse_version,
latest_stable_at_beginning,
)


Expand All @@ -233,40 +254,28 @@ def sort_versions_custom_pattern(version_list, raw_pattern, latest_stable_at_beg
It uses ``Bumpver`` behinds the scenes for the parsing and sorting.
https://github.com/mbarkhau/bumpver
"""
alphabetically_sorted_version_list = sorted(

def parse_version(*args, slug=None, raw_pattern=None, **kwargs):
return parse_version_info(slug, raw_pattern=raw_pattern)

return sort_versions_generic(
version_list,
key=operator.attrgetter("slug"),
PatternError,
parse_version,
latest_stable_at_beginning,
raw_pattern,
)

initial_versions = []
valid_versions = []
invalid_versions = []
for i, version in enumerate(alphabetically_sorted_version_list):
if latest_stable_at_beginning:
if version.slug in (STABLE, LATEST):
# It relies on the version list sorted alphabetically first ("l" comes first than "s")
initial_versions.append((version, version.slug))
continue

try:
valid_versions.append(
(
version,
parse_version_info(
version.slug,
raw_pattern=raw_pattern,
),
)
)
except PatternError:
# When the version is invalid, we put it at the end while keeping
# the alphabetically sorting between the invalid ones.
invalid_versions.append((version, None))
def sort_versions_calver(version_list, latest_stable_at_beginning):
"""
Sort Read the Docs versions using CalVer pattern: ``YYYY.0M.0M``.

all_versions = (
initial_versions
+ sorted(valid_versions, key=operator.itemgetter(1), reverse=True)
+ invalid_versions
All the invalid version are added at the end sorted alphabetically.
"""
raw_pattern = "YYYY.0M.0D"
return sort_versions_custom_pattern(
version_list,
raw_pattern,
latest_stable_at_beginning,
)

return [item[0] for item in all_versions if item[0] is not None]