Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 6 additions & 0 deletions downloads/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ def latest_python3(self, minor_version: int | None = None):
pattern = rf"^Python 3\.{minor_version}\."
return self.python3().filter(name__regex=pattern).order_by("-release_date")

def latest_prerelease(self):
return self.python3().filter(pre_release=True).order_by("-release_date")

def latest_pymanager(self):
return self.pymanager().filter(is_latest=True)

Expand All @@ -52,5 +55,8 @@ def latest_python2(self):
def latest_python3(self, minor_version: int | None = None):
return self.get_queryset().latest_python3(minor_version).first()

def latest_prerelease(self):
return self.get_queryset().latest_prerelease().first()

def latest_pymanager(self):
return self.get_queryset().latest_pymanager().first()
1 change: 1 addition & 0 deletions downloads/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ def purge_fastly_download_pages(sender, instance, **kwargs):
match = re.match(r'^3\.(\d+)', version)
if match:
purge_url(f'/downloads/latest/python3.{match.group(1)}/')
purge_url('/downloads/latest/prerelease/')
purge_url('/downloads/latest/pymanager/')
purge_url('/downloads/macos/')
purge_url('/downloads/source/')
Expand Down
22 changes: 22 additions & 0 deletions downloads/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,28 @@ def test_latest_python3(self):
latest_3_99 = Release.objects.latest_python3(minor_version=99)
self.assertIsNone(latest_3_99)

def test_latest_prerelease(self):
latest_prerelease = Release.objects.latest_prerelease()
self.assertEqual(latest_prerelease, self.pre_release)

# Create a newer prerelease with a future date
newer_prerelease = Release.objects.create(
version=Release.PYTHON3,
name="Python 3.9.99",
is_published=True,
pre_release=True,
release_date=self.pre_release.release_date + dt.timedelta(days=1),
)
latest_prerelease = Release.objects.latest_prerelease()
self.assertEqual(latest_prerelease, newer_prerelease)
self.assertNotEqual(latest_prerelease, self.pre_release)

def test_latest_prerelease_when_no_prerelease(self):
# Delete the prerelease
self.pre_release.delete()
latest_prerelease = Release.objects.latest_prerelease()
self.assertIsNone(latest_prerelease)

def test_get_version(self):
self.assertEqual(self.release_275.name, 'Python 2.7.5')
self.assertEqual(self.release_275.get_version(), '2.7.5')
Expand Down
12 changes: 12 additions & 0 deletions downloads/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,18 @@ def test_latest_python3x_redirects(self):
response = self.client.get(url)
self.assertRedirects(response, reverse("download:download"))

def test_latest_prerelease_redirect(self):
url = reverse("download:download_latest_prerelease")
response = self.client.get(url)
self.assertRedirects(response, self.pre_release.get_absolute_url())

def test_latest_prerelease_redirect_when_no_prerelease(self):
# Delete the prerelease to test fallback
self.pre_release.delete()
url = reverse("download:download_latest_prerelease")
response = self.client.get(url)
self.assertRedirects(response, reverse("download:download"))

def test_redirect_page_object_to_release_detail_page(self):
self.release_275.release_page = None
self.release_275.save()
Expand Down
1 change: 1 addition & 0 deletions downloads/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
re_path(r'latest/python2/?$', views.DownloadLatestPython2.as_view(), name='download_latest_python2'),
re_path(r'latest/python3/?$', views.DownloadLatestPython3.as_view(), name='download_latest_python3'),
re_path(r'latest/python3\.(?P<minor>\d+)/?$', views.DownloadLatestPython3.as_view(), name='download_latest_python3x'),
re_path(r'latest/prerelease/?$', views.DownloadLatestPrerelease.as_view(), name='download_latest_prerelease'),
re_path(r'latest/pymanager/?$', views.DownloadLatestPyManager.as_view(), name='download_latest_pymanager'),
re_path(r'latest/?$', views.DownloadLatestPython3.as_view(), name='download_latest_python3'),
path('operating-systems/', views.DownloadFullOSList.as_view(), name='download_full_os_list'),
Expand Down
17 changes: 17 additions & 0 deletions downloads/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,23 @@ def get_redirect_url(self, **kwargs):
return reverse("downloads:download")


class DownloadLatestPrerelease(RedirectView):
"""Redirect to latest Python 3 prerelease"""

permanent = False

def get_redirect_url(self, **kwargs):
try:
latest_prerelease = Release.objects.latest_prerelease()
except Release.DoesNotExist:
latest_prerelease = None

if latest_prerelease:
return latest_prerelease.get_absolute_url()
else:
return reverse("downloads:download")


class DownloadLatestPyManager(RedirectView):
""" Redirect to latest Python install manager release """
permanent = False
Expand Down
Loading