Skip to content

Commit 09a565e

Browse files
committed
Add script to generate changelog from JSON files
1 parent b7fb982 commit 09a565e

1 file changed

Lines changed: 125 additions & 0 deletions

File tree

scripts/render-change

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#!/usr/bin/env python
2+
"""Generate a changelog file.
3+
4+
Usage
5+
=====
6+
7+
::
8+
9+
$ scripts/gen-change --format rst
10+
# Or:
11+
$ scripts/gen-change --format single-html -r 2.0.0
12+
13+
14+
"""
15+
import os
16+
import sys
17+
import json
18+
import argparse
19+
20+
21+
ROOTDIR = os.path.dirname(
22+
os.path.dirname(os.path.abspath(__file__)))
23+
CHANGEDIR = os.path.join(ROOTDIR, '.changes')
24+
SINGLE_HTML_TEMPLATE = """
25+
%s
26+
27+
.. list-table::
28+
:header-rows: 1
29+
30+
%s
31+
32+
"""
33+
34+
35+
def sorted_releases(changedir):
36+
def key(filename):
37+
filename = filename[:-len('.json')]
38+
parts = tuple(int(i) for i in filename.split('.'))
39+
return parts
40+
releases = sorted(os.listdir(changedir), key=key, reverse=True)
41+
return releases
42+
43+
44+
def _generate_single_release_rst(release_identifier, data, contents):
45+
contents.append(release_identifier)
46+
contents.append('=' * len(release_identifier))
47+
contents.append('')
48+
for change in data:
49+
line = '* %s:%s: %s' % (change['type'], change['category'],
50+
change['description'])
51+
contents.append(line)
52+
contents.append('')
53+
contents.append('')
54+
55+
56+
def generate_rst_changelog(args, changedir=CHANGEDIR):
57+
if not os.path.isdir(changedir):
58+
sys.stderr.write("Changedir does not exist: %s\n" % changedir)
59+
return
60+
contents = []
61+
for release_filename in sorted_releases(changedir):
62+
with open(os.path.join(changedir, release_filename)) as f:
63+
data = json.load(f)
64+
release_identifier = release_filename[:-len('.json')]
65+
_generate_single_release_rst(release_identifier, data, contents)
66+
sys.stdout.write('\n'.join(contents).encode("utf-8"))
67+
68+
69+
def generate_html_snippet_changelog(args):
70+
with open(os.path.join(CHANGEDIR, args.release_version + '.json')) as f:
71+
changes = json.load(f)
72+
73+
features = [ch for ch in changes if ch['type'] == 'feature']
74+
fixes = [ch for ch in changes if ch['type'] == 'bugfix']
75+
76+
feature_contents = _gen_contents_for(features)
77+
fixes_contents = _gen_contents_for(fixes)
78+
if feature_contents:
79+
title = 'New Features'
80+
title += '\n%s' % ('-' * len(title))
81+
rendered = SINGLE_HTML_TEMPLATE % (title, feature_contents)
82+
sys.stdout.write(rendered)
83+
if fixes_contents:
84+
title = 'Resolved Issues'
85+
title += '\n%s' % ('-' * len(title))
86+
rendered = SINGLE_HTML_TEMPLATE % (title, fixes_contents)
87+
sys.stdout.write(rendered)
88+
89+
90+
def _gen_contents_for(changes):
91+
if not changes:
92+
return ''
93+
lines = []
94+
lines.extend(_entry('Change', 'Description'))
95+
for change in changes:
96+
lines.extend(_entry(change['category'], change['description']))
97+
return '\n'.join(lines)
98+
99+
100+
def _entry(title, description):
101+
return [
102+
' * - %s' % title,
103+
' - %s' % description,
104+
]
105+
106+
107+
def main():
108+
parser = argparse.ArgumentParser()
109+
parser.add_argument('--format', default='rst',
110+
dest='output_format',
111+
choices=('rst', 'single-html'),
112+
help=('The output format to generate. By '
113+
'default this is rst (CHANGELOG.rst)'))
114+
parser.add_argument('-r', '--release-version',
115+
help=('The release version to generate. Only '
116+
'needed if --format is single-html.'))
117+
args = parser.parse_args()
118+
if args.output_format == 'rst':
119+
generate_rst_changelog(args)
120+
elif args.output_format == 'single-html':
121+
generate_html_snippet_changelog(args)
122+
123+
124+
if __name__ == '__main__':
125+
main()

0 commit comments

Comments
 (0)