Skip to content

Commit a8786b7

Browse files
committed
Generate release cycle chart and CSV
1 parent 71f3b76 commit a8786b7

10 files changed

+409
-19
lines changed

Makefile

+16-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ help:
3838
@echo " linkcheck to check all external links for integrity"
3939
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
4040
@echo " check to run a check for frequent markup errors"
41+
@echo " versions to update release cycle after changing release-cycle.json"
4142

4243
.PHONY: clean
4344
clean: clean-venv
@@ -66,7 +67,7 @@ ensure-venv:
6667
fi
6768

6869
.PHONY: html
69-
html: ensure-venv
70+
html: ensure-venv versions
7071
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
7172
@echo
7273
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
@@ -186,3 +187,17 @@ check: ensure-venv
186187
serve:
187188
@echo "The 'serve' target was removed, use 'htmlview' instead" \
188189
"(see https://github.com/python/cpython/issues/80510)"
190+
191+
# TODO make.bat
192+
include/branches.csv: include/release-cycle.json
193+
$(PYTHON) generate-release-cycle.py
194+
195+
include/end-of-life.csv: include/release-cycle.json
196+
$(PYTHON) generate-release-cycle.py
197+
198+
include/release-cycle.mmd: include/release-cycle.json
199+
$(PYTHON) generate-release-cycle.py
200+
201+
.PHONY: versions
202+
versions: include/branches.csv include/end-of-life.csv include/release-cycle.mmd
203+
@echo Release cycle data generated.

_static/devguide_overrides.css

+65
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,68 @@
55
width: 111px;
66
height: 110px;
77
}
8+
9+
/* Release cycle chart */
10+
#python-release-cycle .mermaid .active0,
11+
#python-release-cycle .mermaid .active1,
12+
#python-release-cycle .mermaid .active2,
13+
#python-release-cycle .mermaid .active3 {
14+
fill: #00dd00;
15+
stroke: darkgreen;
16+
}
17+
18+
#python-release-cycle .mermaid .done0,
19+
#python-release-cycle .mermaid .done1,
20+
#python-release-cycle .mermaid .done2,
21+
#python-release-cycle .mermaid .done3 {
22+
fill: orange;
23+
stroke: darkorange;
24+
}
25+
26+
#python-release-cycle .mermaid .task0,
27+
#python-release-cycle .mermaid .task1,
28+
#python-release-cycle .mermaid .task2,
29+
#python-release-cycle .mermaid .task3 {
30+
fill: #007acc;
31+
stroke: #004455;
32+
}
33+
34+
#python-release-cycle .mermaid .section0,
35+
#python-release-cycle .mermaid .section2 {
36+
fill: darkgrey;
37+
}
38+
39+
/* Set master colours */
40+
:root {
41+
--mermaid-section1-3: white;
42+
--mermaid-text-color: black;
43+
}
44+
45+
@media (prefers-color-scheme: dark) {
46+
body[data-theme=auto] {
47+
--mermaid-section1-3: black;
48+
--mermaid-text-color: #ffffffcc;
49+
}
50+
}
51+
body[data-theme=dark] {
52+
--mermaid-section1-3: black;
53+
--mermaid-text-color: #ffffffcc;
54+
}
55+
56+
#python-release-cycle .mermaid .section1,
57+
#python-release-cycle .mermaid .section3 {
58+
fill: var(--mermaid-section1-3);
59+
}
60+
61+
#python-release-cycle .mermaid .grid .tick text,
62+
#python-release-cycle .mermaid .sectionTitle0,
63+
#python-release-cycle .mermaid .sectionTitle1,
64+
#python-release-cycle .mermaid .sectionTitle2,
65+
#python-release-cycle .mermaid .sectionTitle3,
66+
#python-release-cycle .mermaid .taskTextOutside0,
67+
#python-release-cycle .mermaid .taskTextOutside1,
68+
#python-release-cycle .mermaid .taskTextOutside2,
69+
#python-release-cycle .mermaid .taskTextOutside3,
70+
#python-release-cycle .mermaid .titleText {
71+
fill: var(--mermaid-text-color);
72+
}

conf.py

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
'sphinx.ext.intersphinx',
1111
'sphinx.ext.todo',
1212
'sphinx_copybutton',
13+
'sphinxcontrib.mermaid',
1314
'sphinxext.rediraffe',
1415
]
1516

generate-release-cycle.py

+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
"""
2+
Read in a JSON and generate two CSVs and a Mermaid file
3+
"""
4+
from __future__ import annotations
5+
6+
import csv
7+
import datetime as dt
8+
import json
9+
10+
MERMAID_HEADER = """
11+
gantt
12+
dateFormat YYYY-MM-DD
13+
title Python release cycle
14+
axisFormat %Y
15+
""".lstrip()
16+
17+
MERMAID_SECTION = """
18+
section Python {cycle}
19+
{release_status} :{mermaid_status} python{cycle}, {release_date},{eol}
20+
""" # noqa: E501
21+
22+
MERMAID_STATUS_MAPPING = {
23+
"features": "",
24+
"bugfix": "active,",
25+
"security": "done,",
26+
"end-of-life": "crit,",
27+
}
28+
29+
CSV_HEADER = (
30+
"Branch",
31+
"Schedule",
32+
"Status",
33+
"First release",
34+
"End-of-life",
35+
"Release manager",
36+
)
37+
38+
39+
def cycle(branch: str) -> str:
40+
"""Convert branch name to version number"""
41+
return "3.12" if branch == "main" else branch
42+
43+
44+
def pep(number: int) -> str:
45+
"""Format PEP number with Sphinx role"""
46+
return f":pep:`{number}`"
47+
48+
49+
def csv_date(date_str: str, now_str: str) -> str:
50+
"""Format a date for CSV"""
51+
if date_str > now_str:
52+
# Future, add italics
53+
return f"*{date_str}*"
54+
return date_str
55+
56+
57+
def mermaid_date(date_str: str) -> str:
58+
"""Format a date for Mermaid"""
59+
if len(date_str) == len("yyyy-mm"):
60+
# Mermaid needs a full yyyy-mm-dd, so let's approximate
61+
date_str = f"{date_str}-01"
62+
return date_str
63+
64+
65+
class Versions:
66+
"""For converting JSON to CSV and Mermaid"""
67+
68+
def __init__(self) -> None:
69+
with open("include/release-cycle.json") as f:
70+
self.versions = json.load(f)
71+
72+
def save_csv(self) -> None:
73+
"""Output CSV files"""
74+
now_str = str(dt.datetime.utcnow())
75+
76+
with (
77+
open("include/branches.csv", "w", newline="") as file_branches,
78+
open("include/end-of-life.csv", "w", newline="") as file_eol,
79+
):
80+
csv_branches = csv.writer(file_branches, quoting=csv.QUOTE_MINIMAL)
81+
csv_eol = csv.writer(file_eol, quoting=csv.QUOTE_MINIMAL)
82+
83+
csv_branches.writerow(CSV_HEADER)
84+
csv_eol.writerow(CSV_HEADER)
85+
86+
sorted_versions = sorted(
87+
self.versions,
88+
key=lambda d: int(cycle(d["cycle"]).replace(".", "")),
89+
reverse=True,
90+
)
91+
for version in sorted_versions:
92+
row = (
93+
version["cycle"],
94+
pep(version["pep"]),
95+
version["status"],
96+
csv_date(version["releaseDate"], now_str),
97+
csv_date(version["eol"], now_str),
98+
version["releaseManager"],
99+
)
100+
101+
if version["status"] == "end-of-life":
102+
csv_eol.writerow(row)
103+
else:
104+
csv_branches.writerow(row)
105+
106+
def save_mermaid(self) -> None:
107+
"""Output Mermaid file"""
108+
out = [MERMAID_HEADER]
109+
110+
for version in reversed(self.versions):
111+
v = MERMAID_SECTION.format(
112+
cycle=cycle(version["cycle"]),
113+
release_date=version["releaseDate"],
114+
eol=mermaid_date(version["eol"]),
115+
release_status=version["status"],
116+
mermaid_status=MERMAID_STATUS_MAPPING[version["status"]],
117+
)
118+
out.append(v)
119+
120+
with open("include/release-cycle.mmd", "w") as f:
121+
f.writelines(out)
122+
123+
124+
def main() -> None:
125+
versions = Versions()
126+
versions.save_csv()
127+
versions.save_mermaid()
128+
129+
130+
if __name__ == "__main__":
131+
main()

include/branches.csv

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
Branch,Schedule,Status,First release,End-of-life,Release manager
2-
main,:pep:`693`,features,*2023-10-02*,*2028-10*,Thomas Wouters
3-
3.11,:pep:`664`,bugfix,2022-10-24,*2027-10*,Pablo Galindo Salgado
4-
3.10,:pep:`619`,bugfix,2021-10-04,*2026-10*,Pablo Galindo Salgado
5-
3.9,:pep:`596`,security,2020-10-05,*2025-10*,Łukasz Langa
6-
3.8,:pep:`569`,security,2019-10-14,*2024-10*,Łukasz Langa
7-
3.7,:pep:`537`,security,2018-06-27,*2023-06-27*,Ned Deily
1+
Branch,Schedule,Status,First release,End-of-life,Release manager
2+
main,:pep:`693`,features,*2023-10-02*,*2028-10*,Thomas Wouters
3+
3.11,:pep:`664`,bugfix,2022-10-24,*2027-10*,Pablo Galindo Salgado
4+
3.10,:pep:`619`,bugfix,2021-10-04,*2026-10*,Pablo Galindo Salgado
5+
3.9,:pep:`596`,security,2020-10-05,*2025-10*,Łukasz Langa
6+
3.8,:pep:`569`,security,2019-10-14,*2024-10*,Łukasz Langa
7+
3.7,:pep:`537`,security,2018-06-27,*2023-06-27*,Ned Deily

include/end-of-life.csv

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
Branch,Schedule,Status,First release,End-of-life,Release manager
2-
3.6,:pep:`494`,end-of-life,2016-12-23,2021-12-23,Ned Deily
3-
3.5,:pep:`478`,end-of-life,2015-09-13,2020-09-30,Larry Hastings
4-
3.4,:pep:`429`,end-of-life,2014-03-16,2019-03-18,Larry Hastings
5-
3.3,:pep:`398`,end-of-life,2012-09-29,2017-09-29,"Georg Brandl, Ned Deily (3.3.7+)"
6-
3.2,:pep:`392`,end-of-life,2011-02-20,2016-02-20,Georg Brandl
7-
3.1,:pep:`375`,end-of-life,2009-06-27,2012-04-09,Benjamin Peterson
8-
3.0,:pep:`361`,end-of-life,2008-12-03,2009-06-27,Barry Warsaw
9-
2.7,:pep:`373`,end-of-life,2010-07-03,2020-01-01,Benjamin Peterson
10-
2.6,:pep:`361`,end-of-life,2008-10-01,2013-10-29,Barry Warsaw
1+
Branch,Schedule,Status,First release,End-of-life,Release manager
2+
3.6,:pep:`494`,end-of-life,2016-12-23,2021-12-23,Ned Deily
3+
3.5,:pep:`478`,end-of-life,2015-09-13,2020-09-30,Larry Hastings
4+
3.4,:pep:`429`,end-of-life,2014-03-16,2019-03-18,Larry Hastings
5+
3.3,:pep:`398`,end-of-life,2012-09-29,2017-09-29,"Georg Brandl, Ned Deily (3.3.7+)"
6+
3.2,:pep:`392`,end-of-life,2011-02-20,2016-02-20,Georg Brandl
7+
3.1,:pep:`375`,end-of-life,2009-06-27,2012-04-09,Benjamin Peterson
8+
3.0,:pep:`361`,end-of-life,2008-12-03,2009-06-27,Barry Warsaw
9+
2.7,:pep:`373`,end-of-life,2010-07-03,2020-01-01,Benjamin Peterson
10+
2.6,:pep:`361`,end-of-life,2008-10-01,2013-10-29,Barry Warsaw

0 commit comments

Comments
 (0)