Skip to content

Commit 65942a4

Browse files
committed
Generate page of docs by version
1 parent ea671db commit 65942a4

File tree

3 files changed

+173
-0
lines changed

3 files changed

+173
-0
lines changed

pydotorg/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
path('getit/', include('downloads.urls', namespace='getit')),
3333
path('downloads/', include('downloads.urls', namespace='download')),
3434
path('doc/', views.DocumentationIndexView.as_view(), name='documentation'),
35+
path('doc/versions2/', views.DocsByVersionView.as_view(), name='docs-versions'),
3536
path('blogs/', include('blogs.urls')),
3637
path('inner/', TemplateView.as_view(template_name="python/inner.html"), name='inner'),
3738

pydotorg/views.py

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
import datetime as dt
12
import json
23
import os
4+
import re
5+
from collections import defaultdict
6+
37
from django.conf import settings
48
from django.http import HttpResponse, JsonResponse
59
from django.views.generic.base import RedirectView, TemplateView
@@ -67,3 +71,113 @@ def get_redirect_url(self, *args, **kwargs):
6771
settings.AWS_STORAGE_BUCKET_NAME,
6872
image_path,
6973
])
74+
75+
76+
class DocsByVersionView(TemplateView):
77+
template_name = "python/versions.html"
78+
79+
def get_context_data(self, **kwargs):
80+
context = super().get_context_data(**kwargs)
81+
82+
releases = Release.objects.filter(
83+
is_published=True,
84+
pre_release=False,
85+
).order_by("-release_date")
86+
87+
# Some releases have no documentation
88+
no_docs = {"2.3.6", "2.3.7", "2.4.5", "2.4.6", "2.5.5", "2.5.6"}
89+
90+
# We'll group releases by major.minor version
91+
version_groups = defaultdict(list)
92+
93+
for release in releases:
94+
# Extract version number from name ("Python 3.14.0" -> "3.14.0")
95+
version_match = re.match(r"Python ([\d.]+)", release.name)
96+
if version_match:
97+
full_version = version_match.group(1)
98+
99+
if full_version in no_docs:
100+
continue
101+
102+
# Get major.minor version ("3.14.0" -> "3.14")
103+
version_parts = full_version.split(".")
104+
major_minor = f"{version_parts[0]}.{version_parts[1]}"
105+
106+
# For 3.2.0 and earlier, use X.Y instead of X.Y.0
107+
if len(version_parts) == 3:
108+
major, minor, patch = map(int, version_parts)
109+
# For versions <= 3.2.0 where patch is 0
110+
if (major, minor, patch) <= (3, 2, 0) and patch == 0:
111+
full_version = major_minor
112+
113+
release_data = {
114+
"stage": full_version,
115+
"date": release.release_date.replace(tzinfo=None),
116+
}
117+
version_groups[major_minor].append(release_data)
118+
119+
# Add legacy releases not in the database
120+
legacy_releases_data = {
121+
"2.2": [
122+
{"stage": "2.2p1", "date": dt.datetime(2002, 3, 29)},
123+
],
124+
"2.1": [
125+
{"stage": "2.1.2", "date": dt.datetime(2002, 1, 16)},
126+
{"stage": "2.1.1", "date": dt.datetime(2001, 7, 20)},
127+
{"stage": "2.1", "date": dt.datetime(2001, 4, 15)},
128+
],
129+
"2.0": [
130+
{"stage": "2.0", "date": dt.datetime(2000, 10, 16)},
131+
],
132+
"1.6": [
133+
{"stage": "1.6", "date": dt.datetime(2000, 9, 5)},
134+
],
135+
"1.5": [
136+
{"stage": "1.5.2p2", "date": dt.datetime(2000, 3, 22)},
137+
{"stage": "1.5.2p1", "date": dt.datetime(1999, 7, 6)},
138+
{"stage": "1.5.2", "date": dt.datetime(1999, 4, 30)},
139+
{"stage": "1.5.1p1", "date": dt.datetime(1998, 8, 6)},
140+
{"stage": "1.5.1", "date": dt.datetime(1998, 4, 14)},
141+
{"stage": "1.5", "date": dt.datetime(1998, 2, 17)},
142+
],
143+
"1.4": [
144+
{"stage": "1.4", "date": dt.datetime(1996, 10, 25)},
145+
],
146+
}
147+
148+
# Merge legacy releases in
149+
for version, items in legacy_releases_data.items():
150+
version_groups[version].extend(items)
151+
152+
# Convert to list for template and sort releases within each version
153+
version_list = []
154+
for version, releases in version_groups.items():
155+
# Sort x.y.z newest first
156+
releases = sorted(
157+
releases,
158+
key=lambda x: x.get("date", dt.datetime.min),
159+
reverse=True,
160+
)
161+
for release in releases:
162+
release["date"] = release["date"].strftime("%-d %B %Y")
163+
164+
version_list.append(
165+
{
166+
"version": version,
167+
"releases": releases,
168+
}
169+
)
170+
171+
# Sort x.y versions (newest first)
172+
version_list.sort(
173+
key=lambda x: [
174+
int(n) if n.isdigit() else n for n in x["version"].split(".")
175+
],
176+
reverse=True,
177+
)
178+
179+
context.update({
180+
"version_list": version_list,
181+
})
182+
183+
return context

templates/python/versions.html

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
{% extends "base.html" %}
2+
{% load boxes %}
3+
{% load sitetree %}
4+
5+
{% block page_title %}Python documentation by version | {{ SITE_INFO.site_name }}{% endblock %}
6+
7+
{% block body_attributes %}class="python pages default-page"{% endblock %}
8+
9+
{% block breadcrumbs %}
10+
{% sitetree_breadcrumbs from "main" %}
11+
{% endblock breadcrumbs %}
12+
13+
{% block content_attributes %}with-left-sidebar{% endblock %}
14+
15+
{% block content %}
16+
<article class="text">
17+
<header class="article-header">
18+
<h1 class="page-title">Python documentation by version</h1>
19+
</header>
20+
21+
<p>Some previous versions of the documentation remain available online. Use the list below to select a version to view.</p>
22+
23+
<p>For unreleased (in development) documentation, see <a href="#in-development-versions">In development versions</a>.</p>
24+
25+
<h2>Release versions</h2>
26+
27+
{% for version_data in version_list %}
28+
<h3>Python {{ version_data.version }}</h3>
29+
<ul>
30+
{% for release in version_data.releases %}
31+
<li>
32+
{% if release.stage %}
33+
<a href="https://docs.python.org/release/{{ release.stage|cut:" " }}/">Python {{ release.stage }}</a>{% if release.date %}, documentation released on {{ release.date }}{% endif %}
34+
{% endif %}
35+
</li>
36+
{% endfor %}
37+
</ul>
38+
{% endfor %}
39+
40+
<h2 id="in-development-versions">In development versions</h2>
41+
<p>The latest, and unreleased, documentation for versions of Python still under development:</p>
42+
<ul>
43+
<li><a href="https://docs.python.org/dev/">Development version</a></li>
44+
<li><a href="https://docs.python.org/3/">Python 3.x</a></li>
45+
</ul>
46+
47+
</article>
48+
{% endblock content %}
49+
50+
{% block left_sidebar %}
51+
<aside class="left-sidebar" role="secondary">
52+
{% include "components/navigation-widget.html" %}
53+
54+
<div class="psf-sidebar-widget sidebar-widget">
55+
{% box 'widget-sidebar-aboutpsf' %}
56+
</div>
57+
</aside>
58+
{% endblock left_sidebar %}

0 commit comments

Comments
 (0)