Coverage for gpaw/utilities/newrelease.py: 8%
167 statements
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-20 00:19 +0000
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-20 00:19 +0000
1"""Generate new release of ASE.
3This script does not attempt to import ASE - then it would depend on
4which ASE is installed and how - but assumes that it is run from the
5ASE root directory."""
7import subprocess
8import re
9import argparse
10from time import strftime
13def runcmd(cmd, output=False, error_ok=False):
14 print('Executing:', cmd)
15 try:
16 if output:
17 txt = subprocess.check_output(cmd, shell=True)
18 return txt.decode('utf8')
19 else:
20 return subprocess.check_call(cmd, shell=True)
21 except subprocess.CalledProcessError as err:
22 if error_ok:
23 print(f'Failed: {err}')
24 print('Continuing...')
25 else:
26 raise
29bash = runcmd
32def py(cmd, output=False):
33 return runcmd(f'python3 {cmd}')
36def py2(cmd, output=False):
37 return runcmd(f'python2 {cmd}')
40def git(cmd, error_ok=False):
41 cmd = f'git {cmd}'
42 return runcmd(cmd, output=True, error_ok=error_ok)
45versionfile = 'gpaw/__init__.py'
48def get_version():
49 with open(versionfile) as fd:
50 return re.search(r"__version__ = '(\S+)'", fd.read()).group(1)
53def main():
54 p = argparse.ArgumentParser(description='Generate new release of GPAW.',
55 epilog='Run from the root directory of GPAW.')
56 p.add_argument('version', nargs='?',
57 help='new version number')
58 p.add_argument('--clean', action='store_true',
59 help='delete release branch and tag')
60 p.add_argument('--sign', action='store_true')
61 p.add_argument('--wheel', action='store_true')
62 args = p.parse_args()
64 try:
65 current_version = get_version()
66 except Exception as err:
67 p.error('Cannot get version: {}. Are you in the root directory?'
68 .format(err))
70 print(f'Current version: {current_version}')
72 if not args.version:
73 p.print_help()
74 raise SystemExit
76 version = args.version
78 branchname = f'gpaw-{version}'
79 current_version = get_version()
81 if args.clean:
82 print(f'Cleaning {version}')
83 git('checkout master')
84 git(f'tag -d {version}', error_ok=True)
85 git(f'branch -D {branchname}', error_ok=True)
86 git('branch -D {}'.format('web-page'), error_ok=True)
87 return
89 print(f'New release: {version}')
91 txt = git('status')
92 branch = re.match(r'On branch (\S+)', txt).group(1)
93 print(f'Currently on branch {repr(branch)}')
94 if branch != 'master':
95 git('checkout master')
97 git(f'checkout -b {branchname}')
99 majormiddle, minor = version.rsplit('.', 1)
100 minor = int(minor)
101 nextminor = minor + 1
102 next_devel_version = f'{majormiddle}.{nextminor}b1'
104 def update_version(version):
105 print(f'Editing {versionfile}: version {version}')
106 new_versionline = f"__version__ = '{version}'\n"
107 lines = []
108 ok = False
109 with open(versionfile) as fd:
110 for line in fd:
111 if line.startswith('__version__'):
112 ok = True
113 line = new_versionline
114 lines.append(line)
115 assert ok
116 with open(versionfile, 'w') as fd:
117 for line in lines:
118 fd.write(line)
120 update_version(version)
122 releasenotes = 'doc/releasenotes.rst'
123 lines = []
125 searchtxt = re.escape("""\
126Git master branch
127=================
129:git:`master <>`.
130""")
132 replacetxt = """\
133Git master branch
134=================
136:git:`master <>`.
138* No changes yet
141{header}
142{underline}
144{date}: :git:`{version} <../{version}>`
145"""
147 date = strftime('%d %B %Y').lstrip('0')
148 header = f'Version {version}'
149 underline = '=' * len(header)
150 replacetxt = replacetxt.format(header=header, version=version,
151 underline=underline, date=date)
153 print(f'Editing {releasenotes}')
154 with open(releasenotes) as fd:
155 txt = fd.read()
156 txt, n = re.subn(searchtxt, replacetxt, txt, re.MULTILINE)
157 assert n == 1
159 with open(releasenotes, 'w') as fd:
160 fd.write(txt)
162 searchtxt = """\
163News
164====
165"""
167 replacetxt = """\
168News
169====
171* :ref:`GPAW version {version} <releasenotes>` released ({date}).
172"""
174 replacetxt = replacetxt.format(version=version, date=date)
176 frontpage = 'doc/index.rst'
177 lines = []
178 print(f'Editing {frontpage}')
179 with open(frontpage) as fd:
180 txt = fd.read()
181 txt, n = re.subn(searchtxt, replacetxt, txt)
182 assert n == 1
183 with open(frontpage, 'w') as fd:
184 fd.write(txt)
186 installdoc = 'doc/install.rst'
187 print(f'Editing {installdoc}')
189 with open(installdoc) as fd:
190 txt = fd.read()
192 txt, nsub = re.subn(r'gpaw-\d+\.\d+.\d+',
193 f'gpaw-{version}', txt)
194 assert nsub > 0
195 txt, nsub = re.subn(r'git clone -b \d+\.\d+.\d+',
196 f'git clone -b {version}', txt)
197 assert nsub == 1
199 with open(installdoc, 'w') as fd:
200 fd.write(txt)
202 sphinxconf = 'doc/conf.py'
203 print(f'Editing {sphinxconf}')
204 comment = '# This line auto-edited by newrelease script'
205 line1 = f"dev_version = '{next_devel_version}' {comment}\n"
206 line2 = f"stable_version = '{version}' {comment}\n"
207 lines = []
208 with open(sphinxconf) as fd:
209 for line in fd:
210 if re.match('dev_version = ', line):
211 line = line1
212 if re.match('stable_version = ', line):
213 line = line2
214 lines.append(line)
215 with open(sphinxconf, 'w') as fd:
216 fd.write(''.join(lines))
218 git('add {}'.format(' '.join([versionfile, sphinxconf, installdoc,
219 frontpage, releasenotes])))
220 git(f'commit -m "GPAW version {version}"')
221 git('tag {0} {1} -m "gpaw-{1}"'
222 .format('-s' if args.sign else '',
223 version))
225 py('setup.py sdist > setup_sdist.log')
226 if args.wheel:
227 py2('setup.py bdist_wheel > setup_bdist_wheel2.log')
228 py('setup.py bdist_wheel > setup_bdist_wheel3.log')
229 if args.sign:
230 bash('gpg --armor --yes --detach-sign dist/gpaw-{}.tar.gz'
231 .format(version))
232 git('checkout -b web-page')
233 git('branch --set-upstream-to=origin/web-page')
234 git(f'checkout {branchname}')
235 update_version(next_devel_version)
236 git(f'add {versionfile}')
237 git('branch --set-upstream-to=master')
238 git(f'commit -m "bump version number to {next_devel_version}"')
240 print()
241 print('Automatic steps done.')
242 print()
243 print('Now is a good time to:')
244 print(' * check the diff')
245 print(' * run the tests')
246 print(' * verify the web-page build')
247 print()
248 print('Remaining steps')
249 print('===============')
250 print(f'git show {version} # Inspect!')
251 print('git checkout master')
252 print(f'git merge {branchname}')
253 print('twine upload '
254 'dist/gpaw-{v}.tar.gz '
255 'dist/gpaw-{v}-py2-none-any.whl '
256 'dist/gpaw-{v}-py3-none-any.whl '
257 'dist/gpaw-{v}.tar.gz.asc'.format(v=version))
258 print('git push --tags origin master # Assuming your remote is "origin"')
259 print('git checkout web-page')
260 print('git push --force origin web-page')
263if __name__ == '__main__':
264 main()