Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate release cycle chart and CSV #988

Merged
merged 21 commits into from
Dec 5, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
17 changes: 16 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ help:
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
@echo " check to run a check for frequent markup errors"
@echo " versions to update release cycle after changing release-cycle.json"

.PHONY: clean
clean: clean-venv
Expand Down Expand Up @@ -66,7 +67,7 @@ ensure-venv:
fi

.PHONY: html
html: ensure-venv
html: ensure-venv versions
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
Expand Down Expand Up @@ -186,3 +187,17 @@ check: ensure-venv
serve:
@echo "The 'serve' target was removed, use 'htmlview' instead" \
"(see https://github.com/python/cpython/issues/80510)"

# TODO make.bat
include/branches.csv: include/release-cycle.json
$(PYTHON) generate-release-cycle.py

include/end-of-life.csv: include/release-cycle.json
$(PYTHON) generate-release-cycle.py

include/release-cycle.mmd: include/release-cycle.json
$(PYTHON) generate-release-cycle.py
merwok marked this conversation as resolved.
Show resolved Hide resolved

.PHONY: versions
versions: include/branches.csv include/end-of-life.csv include/release-cycle.mmd
@echo Release cycle data generated.
65 changes: 65 additions & 0 deletions _static/devguide_overrides.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,68 @@
width: 111px;
height: 110px;
}

/* Release cycle chart */
#python-release-cycle .mermaid .active0,
#python-release-cycle .mermaid .active1,
#python-release-cycle .mermaid .active2,
#python-release-cycle .mermaid .active3 {
fill: #00dd00;
stroke: darkgreen;
}

#python-release-cycle .mermaid .done0,
#python-release-cycle .mermaid .done1,
#python-release-cycle .mermaid .done2,
#python-release-cycle .mermaid .done3 {
fill: orange;
stroke: darkorange;
}

#python-release-cycle .mermaid .task0,
#python-release-cycle .mermaid .task1,
#python-release-cycle .mermaid .task2,
#python-release-cycle .mermaid .task3 {
fill: #007acc;
stroke: #004455;
}

#python-release-cycle .mermaid .section0,
#python-release-cycle .mermaid .section2 {
fill: darkgrey;
}

/* Set master colours */
:root {
--mermaid-section1-3: white;
--mermaid-text-color: black;
}

@media (prefers-color-scheme: dark) {
body[data-theme=auto] {
--mermaid-section1-3: black;
--mermaid-text-color: #ffffffcc;
}
}
body[data-theme=dark] {
--mermaid-section1-3: black;
--mermaid-text-color: #ffffffcc;
}

#python-release-cycle .mermaid .section1,
#python-release-cycle .mermaid .section3 {
fill: var(--mermaid-section1-3);
}

#python-release-cycle .mermaid .grid .tick text,
#python-release-cycle .mermaid .sectionTitle0,
#python-release-cycle .mermaid .sectionTitle1,
#python-release-cycle .mermaid .sectionTitle2,
#python-release-cycle .mermaid .sectionTitle3,
#python-release-cycle .mermaid .taskTextOutside0,
#python-release-cycle .mermaid .taskTextOutside1,
#python-release-cycle .mermaid .taskTextOutside2,
#python-release-cycle .mermaid .taskTextOutside3,
#python-release-cycle .mermaid .titleText {
fill: var(--mermaid-text-color);
}
1 change: 1 addition & 0 deletions conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
'sphinx.ext.intersphinx',
'sphinx.ext.todo',
'sphinx_copybutton',
'sphinxcontrib.mermaid',
'sphinxext.rediraffe',
]

Expand Down
131 changes: 131 additions & 0 deletions generate-release-cycle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
"""
Read in a JSON and generate two CSVs and a Mermaid file
"""
from __future__ import annotations

import csv
import datetime as dt
import json

MERMAID_HEADER = """
gantt
dateFormat YYYY-MM-DD
title Python release cycle
axisFormat %Y
""".lstrip()

MERMAID_SECTION = """
section Python {cycle}
{release_status} :{mermaid_status} python{cycle}, {release_date},{eol}
""" # noqa: E501

MERMAID_STATUS_MAPPING = {
"features": "",
"bugfix": "active,",
"security": "done,",
"end-of-life": "crit,",
}

CSV_HEADER = (
"Branch",
"Schedule",
"Status",
"First release",
"End-of-life",
merwok marked this conversation as resolved.
Show resolved Hide resolved
"Release manager",
)


def cycle(branch: str) -> str:
"""Convert branch name to version number"""
return "3.12" if branch == "main" else branch
hugovk marked this conversation as resolved.
Show resolved Hide resolved


def pep(number: int) -> str:
"""Format PEP number with Sphinx role"""
return f":pep:`{number}`"


def csv_date(date_str: str, now_str: str) -> str:
"""Format a date for CSV"""
if date_str > now_str:
# Future, add italics
return f"*{date_str}*"
return date_str


def mermaid_date(date_str: str) -> str:
"""Format a date for Mermaid"""
if len(date_str) == len("yyyy-mm"):
# Mermaid needs a full yyyy-mm-dd, so let's approximate
date_str = f"{date_str}-01"
return date_str


class Versions:
"""For converting JSON to CSV and Mermaid"""

def __init__(self) -> None:
with open("include/release-cycle.json") as f:
self.versions = json.load(f)
hugovk marked this conversation as resolved.
Show resolved Hide resolved

def save_csv(self) -> None:
"""Output CSV files"""
now_str = str(dt.datetime.utcnow())

with (
open("include/branches.csv", "w", newline="") as file_branches,
open("include/end-of-life.csv", "w", newline="") as file_eol,
hugovk marked this conversation as resolved.
Show resolved Hide resolved
):
csv_branches = csv.writer(file_branches, quoting=csv.QUOTE_MINIMAL)
csv_eol = csv.writer(file_eol, quoting=csv.QUOTE_MINIMAL)

csv_branches.writerow(CSV_HEADER)
csv_eol.writerow(CSV_HEADER)

sorted_versions = sorted(
self.versions,
key=lambda d: int(cycle(d["cycle"]).replace(".", "")),
reverse=True,
)
for version in sorted_versions:
row = (
version["cycle"],
pep(version["pep"]),
version["status"],
csv_date(version["releaseDate"], now_str),
csv_date(version["eol"], now_str),
version["releaseManager"],
)

if version["status"] == "end-of-life":
csv_eol.writerow(row)
else:
csv_branches.writerow(row)
hugovk marked this conversation as resolved.
Show resolved Hide resolved

def save_mermaid(self) -> None:
"""Output Mermaid file"""
out = [MERMAID_HEADER]

for version in reversed(self.versions):
v = MERMAID_SECTION.format(
cycle=cycle(version["cycle"]),
release_date=version["releaseDate"],
eol=mermaid_date(version["eol"]),
release_status=version["status"],
mermaid_status=MERMAID_STATUS_MAPPING[version["status"]],
)
out.append(v)

with open("include/release-cycle.mmd", "w") as f:
hugovk marked this conversation as resolved.
Show resolved Hide resolved
f.writelines(out)


def main() -> None:
versions = Versions()
versions.save_csv()
versions.save_mermaid()
hugovk marked this conversation as resolved.
Show resolved Hide resolved


if __name__ == "__main__":
main()
14 changes: 7 additions & 7 deletions include/branches.csv
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Branch,Schedule,Status,First release,End-of-life,Release manager
main,:pep:`693`,features,*2023-10-02*,*2028-10*,Thomas Wouters
3.11,:pep:`664`,bugfix,2022-10-24,*2027-10*,Pablo Galindo Salgado
3.10,:pep:`619`,bugfix,2021-10-04,*2026-10*,Pablo Galindo Salgado
3.9,:pep:`596`,security,2020-10-05,*2025-10*,Łukasz Langa
3.8,:pep:`569`,security,2019-10-14,*2024-10*,Łukasz Langa
3.7,:pep:`537`,security,2018-06-27,*2023-06-27*,Ned Deily
Branch,Schedule,Status,First release,End-of-life,Release manager
hugovk marked this conversation as resolved.
Show resolved Hide resolved
main,:pep:`693`,features,*2023-10-02*,*2028-10*,Thomas Wouters
3.11,:pep:`664`,bugfix,2022-10-24,*2027-10*,Pablo Galindo Salgado
3.10,:pep:`619`,bugfix,2021-10-04,*2026-10*,Pablo Galindo Salgado
3.9,:pep:`596`,security,2020-10-05,*2025-10*,Łukasz Langa
3.8,:pep:`569`,security,2019-10-14,*2024-10*,Łukasz Langa
3.7,:pep:`537`,security,2018-06-27,*2023-06-27*,Ned Deily
20 changes: 10 additions & 10 deletions include/end-of-life.csv
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
Branch,Schedule,Status,First release,End-of-life,Release manager
3.6,:pep:`494`,end-of-life,2016-12-23,2021-12-23,Ned Deily
3.5,:pep:`478`,end-of-life,2015-09-13,2020-09-30,Larry Hastings
3.4,:pep:`429`,end-of-life,2014-03-16,2019-03-18,Larry Hastings
3.3,:pep:`398`,end-of-life,2012-09-29,2017-09-29,"Georg Brandl, Ned Deily (3.3.7+)"
3.2,:pep:`392`,end-of-life,2011-02-20,2016-02-20,Georg Brandl
3.1,:pep:`375`,end-of-life,2009-06-27,2012-04-09,Benjamin Peterson
3.0,:pep:`361`,end-of-life,2008-12-03,2009-06-27,Barry Warsaw
2.7,:pep:`373`,end-of-life,2010-07-03,2020-01-01,Benjamin Peterson
2.6,:pep:`361`,end-of-life,2008-10-01,2013-10-29,Barry Warsaw
Branch,Schedule,Status,First release,End-of-life,Release manager
3.6,:pep:`494`,end-of-life,2016-12-23,2021-12-23,Ned Deily
3.5,:pep:`478`,end-of-life,2015-09-13,2020-09-30,Larry Hastings
3.4,:pep:`429`,end-of-life,2014-03-16,2019-03-18,Larry Hastings
3.3,:pep:`398`,end-of-life,2012-09-29,2017-09-29,"Georg Brandl, Ned Deily (3.3.7+)"
3.2,:pep:`392`,end-of-life,2011-02-20,2016-02-20,Georg Brandl
3.1,:pep:`375`,end-of-life,2009-06-27,2012-04-09,Benjamin Peterson
3.0,:pep:`361`,end-of-life,2008-12-03,2009-06-27,Barry Warsaw
2.7,:pep:`373`,end-of-life,2010-07-03,2020-01-01,Benjamin Peterson
2.6,:pep:`361`,end-of-life,2008-10-01,2013-10-29,Barry Warsaw
Loading