Skip to content

Commit 9451d9c

Browse files
authored
Addons: always sort versions in descending order (#11691)
* Addons: always sort versions in descending order We were mixing ascending and descending when listing the versions, we now always sort in descending order. Even if the version fails to parse, we still sort it in descending order as fallback. Closes #11689 * Fix tests
1 parent 83f1617 commit 9451d9c

File tree

4 files changed

+178
-22
lines changed

4 files changed

+178
-22
lines changed

readthedocs/projects/tests/test_version_handling.py

+18-18
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@ def test_sort_versions_python_packaging(self):
4040
# `latest` and `stable` are at the beginning
4141
"latest",
4242
"2.5.3",
43-
"1.1",
4443
"1.1.0",
44+
"1.1",
4545
"v1.0",
4646
# Invalid versions are at the end sorted alphabetically.
47-
"another-invalid",
4847
"invalid",
48+
"another-invalid",
4949
]
5050

5151
for slug in slugs:
@@ -73,13 +73,13 @@ def test_sort_versions_python_packaging_latest_stable_not_at_beginning(self):
7373

7474
expected = [
7575
"2.5.3",
76-
"1.1",
7776
"1.1.0",
77+
"1.1",
7878
"v1.0",
7979
# Invalid versions are at the end sorted alphabetically.
80-
"another-invalid",
81-
"invalid",
8280
"latest",
81+
"invalid",
82+
"another-invalid",
8383
]
8484

8585
for slug in slugs:
@@ -121,14 +121,14 @@ def test_sort_versions_calver(self):
121121
"2022.01.22",
122122
"2021.01.22",
123123
# invalid ones (alphabetically)
124-
"1.1",
125-
"1.1.0",
126-
"2.5.3",
127-
"2001-02-27",
128-
"2001.02.2",
129-
"2001.16.32",
130-
"another-invalid",
131124
"invalid",
125+
"another-invalid",
126+
"2001.16.32",
127+
"2001.02.2",
128+
"2001-02-27",
129+
"2.5.3",
130+
"1.1.0",
131+
"1.1",
132132
]
133133

134134
for slug in slugs:
@@ -175,13 +175,13 @@ def test_sort_versions_custom_pattern(self):
175175
"v1.1",
176176
"v1.0",
177177
# invalid ones (alphabetically)
178-
"1.1",
179-
"2.5.3",
180-
"2022.01.22",
181-
"another-invalid",
182-
"invalid",
183-
"v1.1.0",
184178
"v2.3rc1",
179+
"v1.1.0",
180+
"invalid",
181+
"another-invalid",
182+
"2022.01.22",
183+
"2.5.3",
184+
"1.1",
185185
]
186186

187187
for slug in slugs:

readthedocs/projects/version_handling.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -187,15 +187,15 @@ def sort_versions_generic(
187187
alphabetically_sorted_version_list = sorted(
188188
version_list,
189189
key=operator.attrgetter("slug"),
190+
reverse=True,
190191
)
191192

192193
initial_versions = []
193194
valid_versions = []
194195
invalid_versions = []
195-
for i, version in enumerate(alphabetically_sorted_version_list):
196+
for version in alphabetically_sorted_version_list:
196197
if latest_stable_at_beginning:
197198
if version.slug in (STABLE, LATEST):
198-
# It relies on the version list sorted alphabetically first ("l" comes first than "s")
199199
initial_versions.append((version, version.slug))
200200
continue
201201

@@ -215,7 +215,8 @@ def sort_versions_generic(
215215
invalid_versions.append((version, None))
216216

217217
all_versions = (
218-
initial_versions
218+
# It relies on the version list sorted alphabetically first ("l" comes first than "s")
219+
sorted(initial_versions, key=operator.itemgetter(1))
219220
+ sorted(valid_versions, key=operator.itemgetter(1), reverse=True)
220221
+ invalid_versions
221222
)

readthedocs/proxito/tests/test_hosting.py

+155
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
from readthedocs.builds.constants import LATEST
1414
from readthedocs.builds.models import Build, Version
1515
from readthedocs.projects.constants import (
16+
ADDONS_FLYOUT_SORTING_ALPHABETICALLY,
17+
ADDONS_FLYOUT_SORTING_CALVER,
18+
ADDONS_FLYOUT_SORTING_PYTHON_PACKAGING,
1619
MULTIPLE_VERSIONS_WITH_TRANSLATIONS,
1720
PRIVATE,
1821
PUBLIC,
@@ -841,3 +844,155 @@ def test_number_of_queries_url_translations(self):
841844
},
842845
)
843846
assert r.status_code == 200
847+
848+
def test_version_ordering(self):
849+
for slug in ["1.0", "1.2", "1.12", "2.0", "2020.01.05", "a-slug", "z-slug"]:
850+
fixture.get(
851+
Version,
852+
project=self.project,
853+
privacy_level=PUBLIC,
854+
slug=slug,
855+
verbose_name=slug,
856+
built=True,
857+
active=True,
858+
)
859+
self.project.update_stable_version()
860+
self.project.versions.update(
861+
privacy_level=PUBLIC,
862+
built=True,
863+
active=True,
864+
)
865+
866+
kwargs = {
867+
"path": reverse("proxito_readthedocs_docs_addons"),
868+
"data": {
869+
"url": "https://project.dev.readthedocs.io/en/latest/",
870+
"client-version": "0.6.0",
871+
"api-version": "1.0.0",
872+
},
873+
"secure": True,
874+
"headers": {
875+
"host": "project.dev.readthedocs.io",
876+
},
877+
}
878+
879+
# Default ordering (SemVer)
880+
expected = [
881+
"latest",
882+
"stable",
883+
"2020.01.05",
884+
"2.0",
885+
"1.12",
886+
"1.2",
887+
"1.0",
888+
"z-slug",
889+
"a-slug",
890+
]
891+
r = self.client.get(**kwargs)
892+
assert r.status_code == 200
893+
assert [v["slug"] for v in r.json()["versions"]["active"]] == expected
894+
895+
self.project.refresh_from_db()
896+
addons = self.project.addons
897+
898+
# The order of latest and stable doesn't change when using semver.
899+
addons.flyout_sorting_latest_stable_at_beginning = False
900+
addons.save()
901+
r = self.client.get(**kwargs)
902+
assert r.status_code == 200
903+
assert [v["slug"] for v in r.json()["versions"]["active"]] == expected
904+
905+
addons.flyout_sorting = ADDONS_FLYOUT_SORTING_ALPHABETICALLY
906+
addons.flyout_sorting_latest_stable_at_beginning = True
907+
addons.save()
908+
expected = [
909+
"z-slug",
910+
"stable",
911+
"latest",
912+
"a-slug",
913+
"2020.01.05",
914+
"2.0",
915+
"1.2",
916+
"1.12",
917+
"1.0",
918+
]
919+
r = self.client.get(**kwargs)
920+
assert r.status_code == 200
921+
assert [v["slug"] for v in r.json()["versions"]["active"]] == expected
922+
923+
# The order of latest and stable doesn't change when using alphabetical sorting.
924+
addons.flyout_sorting_latest_stable_at_beginning = False
925+
addons.save()
926+
r = self.client.get(**kwargs)
927+
assert r.status_code == 200
928+
assert [v["slug"] for v in r.json()["versions"]["active"]] == expected
929+
930+
addons.flyout_sorting = ADDONS_FLYOUT_SORTING_PYTHON_PACKAGING
931+
addons.flyout_sorting_latest_stable_at_beginning = True
932+
addons.save()
933+
r = self.client.get(**kwargs)
934+
assert r.status_code == 200
935+
expected = [
936+
"latest",
937+
"stable",
938+
"2020.01.05",
939+
"2.0",
940+
"1.12",
941+
"1.2",
942+
"1.0",
943+
"z-slug",
944+
"a-slug",
945+
]
946+
assert [v["slug"] for v in r.json()["versions"]["active"]] == expected
947+
948+
addons.flyout_sorting_latest_stable_at_beginning = False
949+
addons.save()
950+
r = self.client.get(**kwargs)
951+
assert r.status_code == 200
952+
expected = [
953+
"2020.01.05",
954+
"2.0",
955+
"1.12",
956+
"1.2",
957+
"1.0",
958+
"z-slug",
959+
"stable",
960+
"latest",
961+
"a-slug",
962+
]
963+
assert [v["slug"] for v in r.json()["versions"]["active"]] == expected
964+
965+
addons.flyout_sorting = ADDONS_FLYOUT_SORTING_CALVER
966+
addons.flyout_sorting_latest_stable_at_beginning = True
967+
addons.save()
968+
r = self.client.get(**kwargs)
969+
assert r.status_code == 200
970+
expected = [
971+
"latest",
972+
"stable",
973+
"2020.01.05",
974+
"z-slug",
975+
"a-slug",
976+
"2.0",
977+
"1.2",
978+
"1.12",
979+
"1.0",
980+
]
981+
assert [v["slug"] for v in r.json()["versions"]["active"]] == expected
982+
983+
addons.flyout_sorting_latest_stable_at_beginning = False
984+
addons.save()
985+
r = self.client.get(**kwargs)
986+
assert r.status_code == 200
987+
expected = [
988+
"2020.01.05",
989+
"z-slug",
990+
"stable",
991+
"latest",
992+
"a-slug",
993+
"2.0",
994+
"1.2",
995+
"1.12",
996+
"1.0",
997+
]
998+
assert [v["slug"] for v in r.json()["versions"]["active"]] == expected

readthedocs/proxito/views/hosting.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ def _v1(self, project, version, build, filename, url, request):
336336
versions_active_built_not_hidden = (
337337
self._get_versions(request, project)
338338
.select_related("project")
339-
.order_by("slug")
339+
.order_by("-slug")
340340
)
341341
sorted_versions_active_built_not_hidden = versions_active_built_not_hidden
342342

0 commit comments

Comments
 (0)