Skip to content

Commit 689aba2

Browse files
committed
Create release notes
1 parent 1c677cb commit 689aba2

2 files changed

Lines changed: 70 additions & 0 deletions

File tree

CHANGELOG.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
Release 0.11.0 (unreleased)
22
====================================
33

4+
.. note::
5+
6+
This is the latest unreleased version and may change
7+
48
* Support python 3.14
59
* Drop python 3.7, 3.8 support (#801)
610
* Don't show animation when running in CI (#702)

script/create_release_notes.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#!/usr/bin/env python3
2+
"""
3+
create_release_notes.py
4+
5+
Extracts the latest section from CHANGELOG.rst.
6+
If --latest is provided, adds an admonition that it is unreleased.
7+
"""
8+
9+
import argparse
10+
import re
11+
from pathlib import Path
12+
13+
14+
def extract_latest_section(changelog_path: Path) -> str:
15+
"""
16+
Extract the latest release section from a CHANGELOG.rst file.
17+
"""
18+
content = changelog_path.read_text(encoding="utf-8")
19+
lines = content.splitlines()
20+
21+
# Find lines starting with version headings like: 'v1.2.3' or '.. version'
22+
# dfetch uses "vX.Y.Z" style headings in CHANGELOG.rst
23+
version_header_pattern = re.compile(r"^Release \d+\.\d+\.\d+")
24+
25+
start_idx = None
26+
end_idx = None
27+
28+
for idx, line in enumerate(lines):
29+
if version_header_pattern.match(line.strip()):
30+
start_idx = idx
31+
break
32+
33+
if start_idx is None:
34+
raise ValueError("No release section found in CHANGELOG.rst")
35+
36+
# Find the next version header to determine the end
37+
for idx in range(start_idx + 1, len(lines)):
38+
if version_header_pattern.match(lines[idx].strip()):
39+
end_idx = idx
40+
break
41+
42+
section_lines = lines[start_idx:end_idx]
43+
return "\n".join(section_lines).strip()
44+
45+
46+
def main():
47+
"""Main CLI entry."""
48+
parser = argparse.ArgumentParser(
49+
description="Create release notes from CHANGELOG.rst"
50+
)
51+
parser.add_argument(
52+
"--changelog", default="CHANGELOG.rst", help="Path to CHANGELOG.rst"
53+
)
54+
args = parser.parse_args()
55+
56+
changelog_path = Path(args.changelog)
57+
if not changelog_path.exists():
58+
print(f"Error: {changelog_path} not found.")
59+
return
60+
61+
release_notes = extract_latest_section(changelog_path)
62+
print(release_notes)
63+
64+
65+
if __name__ == "__main__":
66+
main()

0 commit comments

Comments
 (0)