From d4a4b59ee39dcf2e8dddafebfecccaaf709ec8bb Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Mon, 22 Apr 2024 14:43:48 +0300 Subject: [PATCH 1/4] Sphinx extension to add dates to release notes Co-authored-by: Jason R. Coombs --- docs/conf.py | 1 + docs/dater.py | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 docs/dater.py diff --git a/docs/conf.py b/docs/conf.py index 392cf317e5f..f12b30e65fb 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -28,6 +28,7 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ + "dater", "sphinx.ext.autodoc", "sphinx.ext.extlinks", "sphinx.ext.intersphinx", diff --git a/docs/dater.py b/docs/dater.py new file mode 100644 index 00000000000..d9e583547bd --- /dev/null +++ b/docs/dater.py @@ -0,0 +1,52 @@ +""" +Sphinx extension to add timestamps to release notes based on Git versions. + +Based on https://github.com/jaraco/rst.linker, with thanks to Jason R. Coombs. +""" + +from __future__ import annotations + +import datetime as dt +import os +import re +import subprocess +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from sphinx.application import Sphinx + +DOC_NAME_REGEX = re.compile(r"releasenotes/\d+\.\d+\.\d+") +VERSION_TITLE_REGEX = re.compile(r"^(\d+\.\d+\.\d+)\n-+\n") + + +def get_date_for(git_version: str) -> dt.datetime | None: + cmd = ["git", "log", "-1", "--format=%ai", git_version] + try: + with open(os.devnull, "w", encoding="utf-8") as devnull: + out = subprocess.check_output( + cmd, stderr=devnull, text=True, encoding="utf-8" + ) + ts = out.strip() + return dt.datetime.fromisoformat(ts) + except subprocess.CalledProcessError: + return None + + +def add_date(app: Sphinx, doc_name: str, source: list[str]) -> None: + if DOC_NAME_REGEX.match(doc_name) and (m := VERSION_TITLE_REGEX.match(source[0])): + old_title = m.group(1) + + if tag_datetime := get_date_for(old_title): + new_title = f"{old_title} ({tag_datetime:%Y-%m-%d})" + else: + new_title = f"{old_title} (unreleased)" + + new_underline = "-" * len(new_title) + + result = source[0].replace(m.group(0), f"{new_title}\n{new_underline}\n", 1) + source[0] = result + + +def setup(app: Sphinx) -> dict[str, bool]: + app.connect("source-read", add_date) + return {"parallel_read_safe": True} From 35003343386f3d2d40f179e0c18f96e0b58ce102 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Mon, 22 Apr 2024 14:58:44 +0300 Subject: [PATCH 2/4] Fetch tags on Read the Docs --- .readthedocs.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.readthedocs.yml b/.readthedocs.yml index 0c8f935d58c..b83ba05b128 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -6,6 +6,10 @@ build: os: ubuntu-22.04 tools: python: "3" + jobs: + post_checkout: + - git remote add upstream https://github.com/python-pillow/Pillow.git # For forks + - git fetch upstream --tags python: install: From ccf1efb3efb371818455289b8c04aa21f18d4c4d Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Wed, 24 Apr 2024 23:06:06 +1000 Subject: [PATCH 3/4] Use subprocess.DEVNULL --- docs/dater.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/docs/dater.py b/docs/dater.py index d9e583547bd..04855956beb 100644 --- a/docs/dater.py +++ b/docs/dater.py @@ -7,7 +7,6 @@ from __future__ import annotations import datetime as dt -import os import re import subprocess from typing import TYPE_CHECKING @@ -22,11 +21,10 @@ def get_date_for(git_version: str) -> dt.datetime | None: cmd = ["git", "log", "-1", "--format=%ai", git_version] try: - with open(os.devnull, "w", encoding="utf-8") as devnull: - out = subprocess.check_output( - cmd, stderr=devnull, text=True, encoding="utf-8" - ) - ts = out.strip() + out = subprocess.check_output( + cmd, stderr=subprocess.DEVNULL, text=True, encoding="utf-8" + ) + ts = out.strip() return dt.datetime.fromisoformat(ts) except subprocess.CalledProcessError: return None From bc35bf0c9e2b3c0a5702a21daa02d5982932f8d7 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Thu, 25 Apr 2024 13:10:45 +1000 Subject: [PATCH 4/4] Use split instead of datetime --- docs/dater.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/docs/dater.py b/docs/dater.py index 04855956beb..f9fb0c1da6e 100644 --- a/docs/dater.py +++ b/docs/dater.py @@ -6,7 +6,6 @@ from __future__ import annotations -import datetime as dt import re import subprocess from typing import TYPE_CHECKING @@ -18,24 +17,23 @@ VERSION_TITLE_REGEX = re.compile(r"^(\d+\.\d+\.\d+)\n-+\n") -def get_date_for(git_version: str) -> dt.datetime | None: +def get_date_for(git_version: str) -> str | None: cmd = ["git", "log", "-1", "--format=%ai", git_version] try: out = subprocess.check_output( cmd, stderr=subprocess.DEVNULL, text=True, encoding="utf-8" ) - ts = out.strip() - return dt.datetime.fromisoformat(ts) except subprocess.CalledProcessError: return None + return out.split()[0] def add_date(app: Sphinx, doc_name: str, source: list[str]) -> None: if DOC_NAME_REGEX.match(doc_name) and (m := VERSION_TITLE_REGEX.match(source[0])): old_title = m.group(1) - if tag_datetime := get_date_for(old_title): - new_title = f"{old_title} ({tag_datetime:%Y-%m-%d})" + if tag_date := get_date_for(old_title): + new_title = f"{old_title} ({tag_date})" else: new_title = f"{old_title} (unreleased)"