Skip to content

Commit 12390dc

Browse files
committed
Merge branch 'main' into release
2 parents d7d5400 + 95304aa commit 12390dc

File tree

11 files changed

+74
-26
lines changed

11 files changed

+74
-26
lines changed

base-requirements.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ psycopg2-binary==2.8.6
1313
python3-openid==3.2.0
1414
python-decouple==3.4
1515
# lxml used by BeautifulSoup.
16-
lxml==4.6.3
16+
lxml==4.9.2
1717
cssselect==1.1.0
1818
feedparser==6.0.8
19-
beautifulsoup4==4.9.3
19+
beautifulsoup4==4.11.2
2020
icalendar==4.0.7
2121
chardet==4.0.0
2222
# TODO: We may drop 'django-imagekit' completely.

blogs/tests/test_views.py

-9
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,3 @@ def test_blog_home(self):
2727

2828
latest = BlogEntry.objects.latest()
2929
self.assertEqual(resp.context['latest_entry'], latest)
30-
31-
def test_blog_redirects(self):
32-
"""
33-
Test that when '/blog/' is hit, it redirects '/blogs/'
34-
"""
35-
response = self.client.get('/blog/')
36-
self.assertRedirects(response,
37-
'/blogs/',
38-
status_code=301)

config/nginx.conf.erb

+24
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ http {
8484
return 301 https://www.python.org/psf;
8585
}
8686

87+
location ~ ^/community-landing/?(.*)$ {
88+
return 301 https://www.python.org/community/;
89+
}
90+
8791
location /doc/Summary {
8892
return 301 http://legacy.python.org/doc/intros/summary;
8993
}
@@ -204,6 +208,22 @@ http {
204208
return 301 https://www.python.org/download/windows/;
205209
}
206210

211+
location /download/ {
212+
return 301 https://www.python.org/downloads/;
213+
}
214+
215+
location /download/source/ {
216+
return 301 https://www.python.org/downloads/source/;
217+
}
218+
219+
location /download/mac/ {
220+
return 301 https://www.python.org/downloads/macos/;
221+
}
222+
223+
location /download/windows/ {
224+
return 301 https://www.python.org/downloads/windows/;
225+
}
226+
207227
location /Mirrors.html {
208228
return 301 https://www.python.org/mirrors/;
209229
}
@@ -292,6 +312,10 @@ http {
292312
return 302 /blogs/;
293313
}
294314

315+
location /blog/ {
316+
return 301 https://python.org/blogs/;
317+
}
318+
295319
location /static/ {
296320
alias /app/static-root/;
297321
add_header Cache-Control "max-age=604800, public"; # 604800 is 7 days

downloads/templatetags/download_tags.py

+34
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,37 @@ def has_sigstore_materials(files):
1919
@register.filter
2020
def has_sbom(files):
2121
return any(f.sbom_spdx2_file for f in files)
22+
23+
24+
@register.filter
25+
def sort_windows(files):
26+
if not files:
27+
return files
28+
29+
# Put Windows files in preferred order
30+
files = list(files)
31+
windows_files = []
32+
other_files = []
33+
for preferred in (
34+
'Windows installer (64-bit)',
35+
'Windows installer (32-bit)',
36+
'Windows installer (ARM64)',
37+
'Windows help file',
38+
'Windows embeddable package (64-bit)',
39+
'Windows embeddable package (32-bit)',
40+
'Windows embeddable package (ARM64)',
41+
):
42+
for file in files:
43+
if file.name == preferred:
44+
windows_files.append(file)
45+
files.remove(file)
46+
break
47+
48+
# Then append any remaining Windows files
49+
for file in files:
50+
if file.name.startswith('Windows'):
51+
windows_files.append(file)
52+
else:
53+
other_files.append(file)
54+
55+
return other_files + windows_files

downloads/tests/base.py

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ def setUp(self):
6464
is_source=True,
6565
description='Gzipped source',
6666
url='ftp/python/2.7.5/Python-2.7.5.tgz',
67+
filesize=12345678,
6768
)
6869

6970
self.draft_release = Release.objects.create(

downloads/tests/test_views.py

+3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ def test_download_release_detail(self):
4040
response = self.client.get(url)
4141
self.assertEqual(response.status_code, 200)
4242

43+
with self.subTest("Release file sizes should be human-readable"):
44+
self.assertInHTML("<td>11.8 MB</td>", response.content.decode())
45+
4346
url = reverse('download:download_release_detail', kwargs={'release_slug': 'fake_slug'})
4447
response = self.client.get(url)
4548
self.assertEqual(response.status_code, 404)

fixtures/boxes.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,9 @@
174174
"created": "2013-10-28T19:27:20.963Z",
175175
"updated": "2022-01-05T15:42:59.645Z",
176176
"label": "widget-use-python-for",
177-
"content": "<h2 class=\"widget-title\"><span aria-hidden=\"true\" class=\"icon-python\"></span>Use Python for&hellip;</h2>\r\n<p class=\"give-me-more\"><a href=\"/about/apps\" title=\"More Applications\">More</a></p>\r\n\r\n<ul class=\"menu\">\r\n <li><b>Web Development</b>:\r\n <span class=\"tag-wrapper\"><a class=\"tag\" href=\"http://www.djangoproject.com/\">Django</a>, <a class=\"tag\" href=\"http://www.pylonsproject.org/\">Pyramid</a>, <a class=\"tag\" href=\"http://bottlepy.org\">Bottle</a>, <a class=\"tag\" href=\"http://tornadoweb.org\">Tornado</a>, <a href=\"http://flask.pocoo.org/\" class=\"tag\">Flask</a>, <a class=\"tag\" href=\"http://www.web2py.com/\">web2py</a></span></li>\r\n <li><b>GUI Development</b>:\r\n <span class=\"tag-wrapper\"><a class=\"tag\" href=\"http://wiki.python.org/moin/TkInter\">tkInter</a>, <a class=\"tag\" href=\"https://wiki.gnome.org/Projects/PyGObject\">PyGObject</a>, <a class=\"tag\" href=\"http://www.riverbankcomputing.co.uk/software/pyqt/intro\">PyQt</a>, <a class=\"tag\" href=\"https://wiki.qt.io/PySide\">PySide</a>, <a class=\"tag\" href=\"https://kivy.org/\">Kivy</a>, <a class=\"tag\" href=\"http://www.wxpython.org/\">wxPython</a></span></li>\r\n <li><b>Scientific and Numeric</b>:\r\n <span class=\"tag-wrapper\">\r\n<a class=\"tag\" href=\"http://www.scipy.org\">SciPy</a>, <a class=\"tag\" href=\"http://pandas.pydata.org/\">Pandas</a>, <a href=\"http://ipython.org\" class=\"tag\">IPython</a></span></li>\r\n <li><b>Software Development</b>:\r\n <span class=\"tag-wrapper\"><a class=\"tag\" href=\"http://buildbot.net/\">Buildbot</a>, <a class=\"tag\" href=\"http://trac.edgewall.org/\">Trac</a>, <a class=\"tag\" href=\"http://roundup.sourceforge.net/\">Roundup</a></span></li>\r\n <li><b>System Administration</b>:\r\n <span class=\"tag-wrapper\"><a class=\"tag\" href=\"http://www.ansible.com\">Ansible</a>, <a class=\"tag\" href=\"https://saltproject.io\">Salt</a>, <a class=\"tag\" href=\"https://www.openstack.org\">OpenStack</a>, <a class=\"tag\" href=\"https://xon.sh\">xonsh</a></span></li>\r\n</ul>",
177+
"content": "<h2 class=\"widget-title\"><span aria-hidden=\"true\" class=\"icon-python\"></span>Use Python for&hellip;</h2>\r\n<p class=\"give-me-more\"><a href=\"/about/apps\" title=\"More Applications\">More</a></p>\r\n\r\n<ul class=\"menu\">\r\n <li><b>Web Development</b>:\r\n <span class=\"tag-wrapper\"><a class=\"tag\" href=\"http://www.djangoproject.com/\">Django</a>, <a class=\"tag\" href=\"http://www.pylonsproject.org/\">Pyramid</a>, <a class=\"tag\" href=\"http://bottlepy.org\">Bottle</a>, <a class=\"tag\" href=\"http://tornadoweb.org\">Tornado</a>, <a href=\"http://flask.pocoo.org/\" class=\"tag\">Flask</a>, <a class=\"tag\" href=\"http://www.web2py.com/\">web2py</a></span></li>\r\n <li><b>GUI Development</b>:\r\n <span class=\"tag-wrapper\"><a class=\"tag\" href=\"http://wiki.python.org/moin/TkInter\">tkInter</a>, <a class=\"tag\" href=\"https://wiki.gnome.org/Projects/PyGObject\">PyGObject</a>, <a class=\"tag\" href=\"http://www.riverbankcomputing.co.uk/software/pyqt/intro\">PyQt</a>, <a class=\"tag\" href=\"https://wiki.qt.io/PySide\">PySide</a>, <a class=\"tag\" href=\"https://kivy.org/\">Kivy</a>, <a class=\"tag\" href=\"http://www.wxpython.org/\">wxPython</a>, <a class=\"tag\" href=\"https://dearpygui.readthedocs.io/en/latest/\">DearPyGui</a></span></li>\r\n <li><b>Scientific and Numeric</b>:\r\n <span class=\"tag-wrapper\">\r\n<a class=\"tag\" href=\"http://www.scipy.org\">SciPy</a>, <a class=\"tag\" href=\"http://pandas.pydata.org/\">Pandas</a>, <a href=\"http://ipython.org\" class=\"tag\">IPython</a></span></li>\r\n <li><b>Software Development</b>:\r\n <span class=\"tag-wrapper\"><a class=\"tag\" href=\"http://buildbot.net/\">Buildbot</a>, <a class=\"tag\" href=\"http://trac.edgewall.org/\">Trac</a>, <a class=\"tag\" href=\"http://roundup.sourceforge.net/\">Roundup</a></span></li>\r\n <li><b>System Administration</b>:\r\n <span class=\"tag-wrapper\"><a class=\"tag\" href=\"http://www.ansible.com\">Ansible</a>, <a class=\"tag\" href=\"https://saltproject.io\">Salt</a>, <a class=\"tag\" href=\"https://www.openstack.org\">OpenStack</a>, <a class=\"tag\" href=\"https://xon.sh\">xonsh</a></span></li>\r\n</ul>",
178178
"content_markup_type": "html",
179-
"_content_rendered": "<h2 class=\"widget-title\"><span aria-hidden=\"true\" class=\"icon-python\"></span>Use Python for&hellip;</h2>\r\n<p class=\"give-me-more\"><a href=\"/about/apps\" title=\"More Applications\">More</a></p>\r\n\r\n<ul class=\"menu\">\r\n <li><b>Web Development</b>:\r\n <span class=\"tag-wrapper\"><a class=\"tag\" href=\"http://www.djangoproject.com/\">Django</a>, <a class=\"tag\" href=\"http://www.pylonsproject.org/\">Pyramid</a>, <a class=\"tag\" href=\"http://bottlepy.org\">Bottle</a>, <a class=\"tag\" href=\"http://tornadoweb.org\">Tornado</a>, <a href=\"http://flask.pocoo.org/\" class=\"tag\">Flask</a>, <a class=\"tag\" href=\"http://www.web2py.com/\">web2py</a></span></li>\r\n <li><b>GUI Development</b>:\r\n <span class=\"tag-wrapper\"><a class=\"tag\" href=\"http://wiki.python.org/moin/TkInter\">tkInter</a>, <a class=\"tag\" href=\"https://wiki.gnome.org/Projects/PyGObject\">PyGObject</a>, <a class=\"tag\" href=\"http://www.riverbankcomputing.co.uk/software/pyqt/intro\">PyQt</a>, <a class=\"tag\" href=\"https://wiki.qt.io/PySide\">PySide</a>, <a class=\"tag\" href=\"https://kivy.org/\">Kivy</a>, <a class=\"tag\" href=\"http://www.wxpython.org/\">wxPython</a></span></li>\r\n <li><b>Scientific and Numeric</b>:\r\n <span class=\"tag-wrapper\">\r\n<a class=\"tag\" href=\"http://www.scipy.org\">SciPy</a>, <a class=\"tag\" href=\"http://pandas.pydata.org/\">Pandas</a>, <a href=\"http://ipython.org\" class=\"tag\">IPython</a></span></li>\r\n <li><b>Software Development</b>:\r\n <span class=\"tag-wrapper\"><a class=\"tag\" href=\"http://buildbot.net/\">Buildbot</a>, <a class=\"tag\" href=\"http://trac.edgewall.org/\">Trac</a>, <a class=\"tag\" href=\"http://roundup.sourceforge.net/\">Roundup</a></span></li>\r\n <li><b>System Administration</b>:\r\n <span class=\"tag-wrapper\"><a class=\"tag\" href=\"http://www.ansible.com\">Ansible</a>, <a class=\"tag\" href=\"https://saltproject.io\">Salt</a>, <a class=\"tag\" href=\"https://www.openstack.org\">OpenStack</a>, <a class=\"tag\" href=\"https://xon.sh\">xonsh</a></span></li>\r\n</ul>"
179+
"_content_rendered": "<h2 class=\"widget-title\"><span aria-hidden=\"true\" class=\"icon-python\"></span>Use Python for&hellip;</h2>\r\n<p class=\"give-me-more\"><a href=\"/about/apps\" title=\"More Applications\">More</a></p>\r\n\r\n<ul class=\"menu\">\r\n <li><b>Web Development</b>:\r\n <span class=\"tag-wrapper\"><a class=\"tag\" href=\"http://www.djangoproject.com/\">Django</a>, <a class=\"tag\" href=\"http://www.pylonsproject.org/\">Pyramid</a>, <a class=\"tag\" href=\"http://bottlepy.org\">Bottle</a>, <a class=\"tag\" href=\"http://tornadoweb.org\">Tornado</a>, <a href=\"http://flask.pocoo.org/\" class=\"tag\">Flask</a>, <a class=\"tag\" href=\"http://www.web2py.com/\">web2py</a></span></li>\r\n <li><b>GUI Development</b>:\r\n <span class=\"tag-wrapper\"><a class=\"tag\" href=\"http://wiki.python.org/moin/TkInter\">tkInter</a>, <a class=\"tag\" href=\"https://wiki.gnome.org/Projects/PyGObject\">PyGObject</a>, <a class=\"tag\" href=\"http://www.riverbankcomputing.co.uk/software/pyqt/intro\">PyQt</a>, <a class=\"tag\" href=\"https://wiki.qt.io/PySide\">PySide</a>, <a class=\"tag\" href=\"https://kivy.org/\">Kivy</a>, <a class=\"tag\" href=\"http://www.wxpython.org/\">wxPython</a>, <a class=\"tag\" href=\"https://dearpygui.readthedocs.io/en/latest/\">DearPyGui</a></span></li>\r\n <li><b>Scientific and Numeric</b>:\r\n <span class=\"tag-wrapper\">\r\n<a class=\"tag\" href=\"http://www.scipy.org\">SciPy</a>, <a class=\"tag\" href=\"http://pandas.pydata.org/\">Pandas</a>, <a href=\"http://ipython.org\" class=\"tag\">IPython</a></span></li>\r\n <li><b>Software Development</b>:\r\n <span class=\"tag-wrapper\"><a class=\"tag\" href=\"http://buildbot.net/\">Buildbot</a>, <a class=\"tag\" href=\"http://trac.edgewall.org/\">Trac</a>, <a class=\"tag\" href=\"http://roundup.sourceforge.net/\">Roundup</a></span></li>\r\n <li><b>System Administration</b>:\r\n <span class=\"tag-wrapper\"><a class=\"tag\" href=\"http://www.ansible.com\">Ansible</a>, <a class=\"tag\" href=\"https://saltproject.io\">Salt</a>, <a class=\"tag\" href=\"https://www.openstack.org\">OpenStack</a>, <a class=\"tag\" href=\"https://xon.sh\">xonsh</a></span></li>\r\n</ul>"
180180
}
181181
},
182182
{

pydotorg/urls.py

+1-8
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
44
from django.conf.urls.static import static
55
from django.urls import path, re_path
6-
from django.views.generic.base import TemplateView, RedirectView
6+
from django.views.generic.base import TemplateView
77
from django.conf import settings
88

99
from cms.views import custom_404
@@ -24,18 +24,11 @@
2424
# python section landing pages
2525
path('about/', TemplateView.as_view(template_name="python/about.html"), name='about'),
2626

27-
# Redirect old download links to new downloads pages
28-
path('download/', RedirectView.as_view(url='https://www.python.org/downloads/', permanent=True)),
29-
path('download/source/', RedirectView.as_view(url='https://www.python.org/downloads/source/', permanent=True)),
30-
path('download/mac/', RedirectView.as_view(url='https://www.python.org/downloads/macos/', permanent=True)),
31-
path('download/windows/', RedirectView.as_view(url='https://www.python.org/downloads/windows/', permanent=True)),
32-
3327
# duplicated downloads to getit to bypass China's firewall. See
3428
# https://github.com/python/pythondotorg/issues/427 for more info.
3529
path('getit/', include('downloads.urls', namespace='getit')),
3630
path('downloads/', include('downloads.urls', namespace='download')),
3731
path('doc/', views.DocumentationIndexView.as_view(), name='documentation'),
38-
path('blog/', RedirectView.as_view(url='/blogs/', permanent=True)),
3932
path('blogs/', include('blogs.urls')),
4033
path('inner/', TemplateView.as_view(template_name="python/inner.html"), name='inner'),
4134

templates/base.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ <h1 class="site-headline">
236236
<li class="tier-1 last" aria-haspopup="true">
237237
<a href="#" class="action-trigger">Socialize</a>
238238
<ul class="subnav menu">
239-
<li class="tier-2 element-1" role="treeitem"><a href="https://www.linkedin.com/company/python-software-foundation/"><i aria-hidden="true" class="fa fa-linkedin-square"></i></span>LinkedIn</a></li>
239+
<li class="tier-2 element-1" role="treeitem"><a href="https://www.linkedin.com/company/python-software-foundation/"><i aria-hidden="true" class="fa fa-linkedin-square"></i>LinkedIn</a></li>
240240
<li class="tier-2 element-2" role="treeitem"><a href="https://fosstodon.org/@ThePSF"><span aria-hidden="true" class="icon-mastodon"></span>Mastodon</a></li>
241241
<li class="tier-2 element-3" role="treeitem"><a href="/community/irc/"><span aria-hidden="true" class="icon-freenode"></span>Chat on IRC</a></li>
242242
<li class="tier-2 element-4" role="treeitem"><a href="https://twitter.com/ThePSF"><span aria-hidden="true" class="icon-twitter"></span>Twitter</a></li>

templates/downloads/os_list.html

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{% extends "downloads/base.html" %}
22
{% load boxes %}
33
{% load sitetree %}
4+
{% load sort_windows from download_tags %}
45

56
{% block body_attributes %}class="python download"{% endblock %}
67

@@ -45,7 +46,7 @@ <h2>Stable Releases</h2>
4546
{% endif %}
4647
{% endif %}
4748
<ul>
48-
{% for f in r.files.all %}
49+
{% for f in r.files.all|sort_windows %}
4950
<li>Download <a href="{{ f.url }}">{{ f.name }}</a></li>
5051
{% empty %}
5152
<li>No files for this release.</li>
@@ -63,7 +64,7 @@ <h2>Pre-releases</h2>
6364
<li>
6465
<a href="{{ r.get_absolute_url }}">{{ r.name }} - {{ r.release_date|date }}</a>
6566
<ul>
66-
{% for f in r.files.all %}
67+
{% for f in r.files.all|sort_windows %}
6768
<li>Download <a href="{{ f.url }}">{{ f.name }}</a></li>
6869
{% empty %}
6970
<li>No files for this release.</li>

templates/downloads/release_detail.html

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
{% load sitetree %}
44
{% load has_sigstore_materials from download_tags %}
55
{% load has_sbom from download_tags %}
6+
{% load sort_windows from download_tags %}
67

78
{% block body_attributes %}class="python downloads"{% endblock %}
89

@@ -60,13 +61,13 @@ <h1 class="page-title">Files</h1>
6061
</tr>
6162
</thead>
6263
<tbody>
63-
{% for f in release_files %}
64+
{% for f in release_files|sort_windows %}
6465
<tr>
6566
<td><a href="{{ f.url }}">{{ f.name }}</a></td>
6667
<td>{{ f.os.name }}</td>
6768
<td>{{ f.description }}</td>
6869
<td>{{ f.md5_sum }}</td>
69-
<td>{{ f.filesize }}</td>
70+
<td>{{ f.filesize|filesizeformat }}</td>
7071
<td>{% if f.gpg_signature_file %}<a href="{{ f.gpg_signature_file }}">SIG</a>{% endif %}</td>
7172
{% if release_files|has_sigstore_materials %}
7273
{% if f.sigstore_bundle_file %}

0 commit comments

Comments
 (0)