Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite4883ee

Browse files
authored
feat(python#1612): add rss feed for latest downloads (python#2569)
* feat: add rss feed for latest downloads* Update downloads/views.py* fix: query DB for releas* fix: query DB for releas* chore: add missing types* fix: update naive datetime, remove staticmethod* fix: remove staticmethodchore: apply formatting and ruuuuuff* chore: no logging needed after working* tests: add them* chore: address code reviews* chore: remove unused imports* chore: remove unused code* chore: remove unused code* fix: purge cdn cache* revert: put the code back, john
1 parent306a73d commite4883ee

File tree

4 files changed

+93
-0
lines changed

4 files changed

+93
-0
lines changed

‎downloads/models.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ def purge_fastly_download_pages(sender, instance, **kwargs):
272272
ifinstance.is_published:
273273
# Purge our common pages
274274
purge_url('/downloads/')
275+
purge_url('/downloads/feed.rss')
275276
purge_url('/downloads/latest/python2/')
276277
purge_url('/downloads/latest/python3/')
277278
purge_url('/downloads/macos/')

‎downloads/tests/test_views.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,3 +554,45 @@ def test_filter_release_file_delete_by_release(self):
554554
headers={"authorization":self.Authorization}
555555
)
556556
self.assertEqual(response.status_code,405)
557+
558+
classReleaseFeedTests(BaseDownloadTests):
559+
"""Tests for the downloads/feed.rss endpoint.
560+
561+
Content is ensured via setUp in BaseDownloadTests.
562+
"""
563+
564+
url=reverse("downloads:feed")
565+
566+
567+
deftest_endpoint_reachable(self)->None:
568+
response=self.client.get(self.url)
569+
self.assertEqual(response.status_code,200)
570+
571+
deftest_feed_content(self)->None:
572+
"""Ensure feed content is as expected.
573+
574+
Some things we want to check:
575+
- Feed title, description, pubdate
576+
- Feed items (releases) are in the correct order
577+
- We get the expected number of releases (10)
578+
"""
579+
response=self.client.get(self.url)
580+
content=response.content.decode()
581+
582+
self.assertIn("Python 2.7.5",content)
583+
self.assertIn("Python 3.10",content)
584+
# Published but hidden show up in the API and thus the feed
585+
self.assertIn("Python 0.0.0",content)
586+
587+
# No unpublished releases
588+
self.assertNotIn("Python 9.7.2",content)
589+
590+
# Pre-releases are shown
591+
self.assertIn("Python 3.9.90",content)
592+
593+
deftest_feed_item_count(self)->None:
594+
response=self.client.get(self.url)
595+
content=response.content.decode()
596+
597+
# In BaseDownloadTests, we create 5 releases, 4 of which are published, 1 of those published are hidden..
598+
self.assertEqual(content.count("<item>"),4)

‎downloads/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@
99
path('release/<slug:release_slug>/',views.DownloadReleaseDetail.as_view(),name='download_release_detail'),
1010
path('<slug:slug>/',views.DownloadOSList.as_view(),name='download_os_list'),
1111
path('',views.DownloadHome.as_view(),name='download'),
12+
path("feed.rss",views.ReleaseFeed(),name="feed"),
1213
]

‎downloads/views.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
1+
fromtypingimportAny
2+
3+
fromdatetimeimportdatetime
4+
15
fromdjango.db.modelsimportPrefetch
26
fromdjango.urlsimportreverse
7+
fromdjango.utilsimporttimezone
38
fromdjango.views.genericimportDetailView,TemplateView,ListView,RedirectView
49
fromdjango.httpimportHttp404
10+
fromdjango.contrib.syndication.viewsimportFeed
11+
fromdjango.utils.feedgeneratorimportRss201rev2Feed
512

613
from .modelsimportOS,Release,ReleaseFile
714

@@ -147,3 +154,45 @@ def get_context_data(self, **kwargs):
147154
)
148155

149156
returncontext
157+
158+
159+
classReleaseFeed(Feed):
160+
"""Generate an RSS feed of the latest Python releases.
161+
162+
.. note:: It may seem like these are unused methods, but the superclass uses them
163+
using Django's Syndication framework.
164+
Docs: https://docs.djangoproject.com/en/4.2/ref/contrib/syndication/
165+
"""
166+
167+
feed_type=Rss201rev2Feed
168+
title="Python Releases"
169+
description="Latest Python releases from Python.org"
170+
171+
@staticmethod
172+
deflink()->str:
173+
"""Return the URL to the main downloads page."""
174+
returnreverse("downloads:download")
175+
176+
defitems(self)->list[dict[str,Any]]:
177+
"""Return the latest Python releases."""
178+
returnRelease.objects.filter(is_published=True).order_by("-release_date")[:10]
179+
180+
defitem_title(self,item:Release)->str:
181+
"""Return the release name as the item title."""
182+
returnitem.name
183+
184+
defitem_description(self,item:Release)->str:
185+
"""Return the release version and release date as the item description."""
186+
returnf"Version:{item.version}, Release Date:{item.release_date}"
187+
188+
defitem_pubdate(self,item:Release)->datetime|None:
189+
"""Return the release date as the item publication date."""
190+
ifitem.release_date:
191+
iftimezone.is_naive(item.release_date):
192+
returntimezone.make_aware(item.release_date)
193+
returnitem.release_date
194+
returnNone
195+
196+
defitem_guid(self,item:Release)->str:
197+
"""Return a unique ID for the item based on DB record."""
198+
returnstr(item.pk)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp