|
5 | 5 | from pathlib import PurePath |
6 | 6 | from urllib.parse import urljoin, urlparse, urlunsplit |
7 | 7 |
|
| 8 | +import packaging_legacy.version |
8 | 9 | from django.contrib.sessions.models import Session |
9 | 10 | from django.core.exceptions import ObjectDoesNotExist |
10 | 11 | from django.db import transaction |
@@ -425,14 +426,18 @@ def retrieve(self, request, path, package): |
425 | 426 | if not releases: |
426 | 427 | return HttpResponseNotFound(f"{normalized} does not exist.") |
427 | 428 |
|
| 429 | + sorted_releases = sorted( |
| 430 | + releases.values(), |
| 431 | + key=lambda r: (packaging_legacy.version.parse(r["version"]), r["filename"]), |
| 432 | + ) |
428 | 433 | media_type = request.accepted_renderer.media_type |
429 | 434 | headers = {"X-PyPI-Last-Serial": str(PYPI_SERIAL_CONSTANT)} |
430 | 435 |
|
431 | 436 | if media_type == PYPI_SIMPLE_V1_JSON: |
432 | | - detail_data = write_simple_detail_json(normalized, releases.values()) |
| 437 | + detail_data = write_simple_detail_json(normalized, sorted_releases) |
433 | 438 | return Response(detail_data, headers=headers) |
434 | 439 | else: |
435 | | - detail_data = write_simple_detail(normalized, releases.values()) |
| 440 | + detail_data = write_simple_detail(normalized, sorted_releases) |
436 | 441 | kwargs = {"content_type": media_type, "headers": headers} |
437 | 442 | return HttpResponse(detail_data, **kwargs) |
438 | 443 |
|
|
0 commit comments