Skip to content

Commit 249986b

Browse files
committed
MNT: Update release notes translator
1 parent 48dcb47 commit 249986b

File tree

1 file changed

+51
-5
lines changed

1 file changed

+51
-5
lines changed

tools/markdown_release_notes.py

+51-5
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,53 @@
11
#!/usr/bin/env python
22
import re
33
import sys
4+
from collections import defaultdict
5+
from functools import cache
6+
from operator import call
47
from pathlib import Path
58

9+
from sphinx.ext.intersphinx import fetch_inventory
10+
611
CHANGELOG = Path(__file__).parent.parent / 'Changelog'
712

813
# Match release lines like "5.2.0 (Monday 11 December 2023)"
914
RELEASE_REGEX = re.compile(r"""((?:\d+)\.(?:\d+)\.(?:\d+)) \(\w+ \d{1,2} \w+ \d{4}\)$""")
1015

1116

17+
class MockConfig:
18+
intersphinx_timeout: int | None = None
19+
tls_verify = False
20+
tls_cacerts: str | dict[str, str] | None = None
21+
user_agent: str = ''
22+
23+
24+
@call
25+
class MockApp:
26+
srcdir = ''
27+
config = MockConfig()
28+
29+
30+
fetch_inv = cache(fetch_inventory)
31+
32+
33+
def get_intersphinx(obj):
34+
module = obj.split('.', 1)[0]
35+
36+
registry = defaultdict(lambda: 'https://docs.python.org/3')
37+
registry.update(
38+
numpy='https://numpy.org/doc/stable',
39+
)
40+
41+
base_url = registry[module]
42+
43+
inventory = fetch_inv(MockApp, '', f'{base_url}/objects.inv')
44+
# Check py: first, then whatever
45+
for objclass in sorted(inventory, key=lambda x: not x.startswith('py:')):
46+
if obj in inventory[objclass]:
47+
return f'{base_url}/{inventory[objclass][obj][2]}'
48+
raise ValueError("Couldn't lookup {obj}")
49+
50+
1251
def main():
1352
version = sys.argv[1]
1453
output = sys.argv[2]
@@ -46,7 +85,7 @@ def main():
4685
release_notes = re.sub(r'\n +', ' ', release_notes)
4786

4887
# Replace pr/<number> with #<number> for GitHub
49-
release_notes = re.sub(r'\(pr/(\d+)\)', r'(#\1)', release_notes)
88+
release_notes = re.sub(r'pr/(\d+)', r'#\1', release_notes)
5089

5190
# Replace :mod:`package.X` with [package.X](...)
5291
release_notes = re.sub(
@@ -76,6 +115,14 @@ def main():
76115
r'[\3](https://nipy.org/nibabel/reference/\1.html#\1.\2.\3)',
77116
release_notes,
78117
)
118+
# Replace :<any>:`<ref>` with intersphinx lookup
119+
for ref in re.findall(r'(:[^:]*:`~?\w[\w.]+\w`)', release_notes):
120+
objclass, tilde, module, obj = re.match(r':([^:]*):`(~?)([\w.]+)\.(\w+)`', ref).groups()
121+
url = get_intersphinx(f'{module}.{obj}')
122+
mdlink = f'[{"" if tilde else module}{obj}]({url})'
123+
release_notes = release_notes.replace(ref, mdlink)
124+
# Replace RST links with Markdown links
125+
release_notes = re.sub(r'`([^<`]*) <([^>]*)>`_+', r'[\1](\2)', release_notes)
79126

80127
def python_doc(match):
81128
module = match.group(1)
@@ -84,10 +131,9 @@ def python_doc(match):
84131

85132
release_notes = re.sub(r':meth:`~([\w.]+)\.(\w+)`', python_doc, release_notes)
86133

87-
output.write('## Release notes\n\n')
88-
output.write(release_notes)
89-
90-
output.close()
134+
with output:
135+
output.write('## Release notes\n\n')
136+
output.write(release_notes)
91137

92138

93139
if __name__ == '__main__':

0 commit comments

Comments
 (0)