Skip to content

Commit 10ba536

Browse files
committed
Backport gh-1284: Add tool for generating GitHub-friendly release notes
DOC: Fix references in changelog MNT: Add tool for generating GitHub-friendly release notes MNT: Avoid isort version with broken extras
1 parent 70795b0 commit 10ba536

File tree

3 files changed

+100
-5
lines changed

3 files changed

+100
-5
lines changed

Changelog

+3-3
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,15 @@ tested up to Python 3.12 and NumPy 1.26.
3636
New features
3737
------------
3838
* Add generic :class:`~nibabel.pointset.Pointset` and regularly spaced
39-
:class:`~nibabel.pointset.NDGrid` data structures in preparation for coordinate
39+
:class:`~nibabel.pointset.Grid` data structures in preparation for coordinate
4040
transformation and resampling (pr/1251) (CM, reviewed by Oscar Esteban)
4141

4242
Enhancements
4343
------------
4444
* Add :meth:`~nibabel.arrayproxy.ArrayProxy.copy` method to
4545
:class:`~nibabel.arrayproxy.ArrayProxy` (pr/1255) (CM, reviewed by Paul McCarthy)
4646
* Permit :meth:`~nibabel.xmlutils.XmlSerializable.to_xml` to pass keyword
47-
arguments to :meth:`~xml.etree.ElementTree.ElementTree.tostring` (pr/1258)
47+
arguments to :meth:`~xml.etree.ElementTree.tostring` (pr/1258)
4848
(CM)
4949
* Allow user expansion (e.g., ``~/...``) in strings passed to functions that
5050
accept paths (pr/1260) (Reinder Vos de Wael, reviewed by CM)
@@ -54,7 +54,7 @@ Enhancements
5454
``affine=None`` argument (pr/1253) (Blake Dewey, reviewed by CM)
5555
* Warn on invalid MINC2 spacing declarations, treat as missing (pr/1237)
5656
(Peter Suter, reviewed by CM)
57-
* Refactor :func:`~nibabel.nicom.utils.find_private_element` for improved
57+
* Refactor :func:`~nibabel.nicom.utils.find_private_section` for improved
5858
readability and maintainability (pr/1228) (MB, reviewed by CM)
5959

6060
Bug fixes

tools/markdown_release_notes.py

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#!/usr/bin/env python
2+
import re
3+
import sys
4+
from pathlib import Path
5+
6+
CHANGELOG = Path(__file__).parent.parent / 'Changelog'
7+
8+
# Match release lines like "5.2.0 (Monday 11 December 2023)"
9+
RELEASE_REGEX = re.compile(r"""((?:\d+)\.(?:\d+)\.(?:\d+)) \(\w+ \d{1,2} \w+ \d{4}\)$""")
10+
11+
12+
def main():
13+
version = sys.argv[1]
14+
output = sys.argv[2]
15+
if output == '-':
16+
output = sys.stdout
17+
else:
18+
output = open(output, 'w')
19+
20+
release_notes = []
21+
in_release_notes = False
22+
23+
with open(CHANGELOG) as f:
24+
for line in f:
25+
match = RELEASE_REGEX.match(line)
26+
if match:
27+
if in_release_notes:
28+
break
29+
in_release_notes = match.group(1) == version
30+
next(f) # Skip the underline
31+
continue
32+
33+
if in_release_notes:
34+
release_notes.append(line)
35+
36+
# Drop empty lines at start and end
37+
while release_notes and not release_notes[0].strip():
38+
release_notes.pop(0)
39+
while release_notes and not release_notes[-1].strip():
40+
release_notes.pop()
41+
42+
# Join lines
43+
release_notes = ''.join(release_notes)
44+
45+
# Remove line breaks when they are followed by a space
46+
release_notes = re.sub(r'\n +', ' ', release_notes)
47+
48+
# Replace pr/<number> with #<number> for GitHub
49+
release_notes = re.sub(r'\(pr/(\d+)\)', r'(#\1)', release_notes)
50+
51+
# Replace :mod:`package.X` with [package.X](...)
52+
release_notes = re.sub(
53+
r':mod:`nibabel\.(.*)`',
54+
r'[nibabel.\1](https://nipy.org/nibabel/reference/nibabel.\1.html)',
55+
release_notes,
56+
)
57+
# Replace :class/func/attr:`package.module.X` with [package.module.X](...)
58+
release_notes = re.sub(
59+
r':(?:class|func|attr):`(nibabel\.\w*)(\.[\w.]*)?\.(\w+)`',
60+
r'[\1\2.\3](https://nipy.org/nibabel/reference/\1.html#\1\2.\3)',
61+
release_notes,
62+
)
63+
release_notes = re.sub(
64+
r':(?:class|func|attr):`~(nibabel\.\w*)(\.[\w.]*)?\.(\w+)`',
65+
r'[\3](https://nipy.org/nibabel/reference/\1.html#\1\2.\3)',
66+
release_notes,
67+
)
68+
# Replace :meth:`package.module.class.X` with [package.module.class.X](...)
69+
release_notes = re.sub(
70+
r':meth:`(nibabel\.[\w.]*)\.(\w+)\.(\w+)`',
71+
r'[\1.\2.\3](https://nipy.org/nibabel/reference/\1.html#\1.\2.\3)',
72+
release_notes,
73+
)
74+
release_notes = re.sub(
75+
r':meth:`~(nibabel\.[\w.]*)\.(\w+)\.(\w+)`',
76+
r'[\3](https://nipy.org/nibabel/reference/\1.html#\1.\2.\3)',
77+
release_notes,
78+
)
79+
80+
def python_doc(match):
81+
module = match.group(1)
82+
name = match.group(2)
83+
return f'[{name}](https://docs.python.org/3/library/{module.lower()}.html#{module}.{name})'
84+
85+
release_notes = re.sub(r':meth:`~([\w.]+)\.(\w+)`', python_doc, release_notes)
86+
87+
output.write('## Release notes\n\n')
88+
output.write(release_notes)
89+
90+
output.close()
91+
92+
93+
if __name__ == '__main__':
94+
main()

tox.ini

+3-2
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ labels = check
141141
deps =
142142
flake8
143143
blue
144-
isort[colors]
144+
# Broken extras, remove when fix is released
145+
isort[colors]!=5.13.1
145146
skip_install = true
146147
commands =
147148
blue --check --diff --color nibabel
@@ -153,7 +154,7 @@ description = Auto-apply style guide to the extent possible
153154
labels = pre-release
154155
deps =
155156
blue
156-
isort[colors]
157+
isort
157158
skip_install = true
158159
commands =
159160
blue nibabel

0 commit comments

Comments
 (0)