get_previous_releases.py raw
1 #!/usr/bin/env python3
2 #
3 # Copyright (c) 2018-present The Limenka developers
4 # Distributed under the MIT software license, see the accompanying
5 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 #
7 # Download or build previous releases.
8 # Needs curl and tar to download a release, or the build dependencies when
9 # building a release.
10
11 import argparse
12 import contextlib
13 from fnmatch import fnmatch
14 import os
15 from pathlib import Path
16 import re
17 import shutil
18 import subprocess
19 import sys
20 import time
21 import hashlib
22
23 SHA256_SUMS = {
24 "0e2819135366f150d9906e294b61dff58fd1996ebd26c2f8e979d6c0b7a79580": {"tag": "v0.14.3", "tarball": "limenka-0.14.3-aarch64-linux-gnu.tar.gz"},
25 "d86fc90824a85c38b25c8488115178d5785dbc975f5ff674f9f5716bc8ad6e65": {"tag": "v0.14.3", "tarball": "limenka-0.14.3-arm-linux-gnueabihf.tar.gz"},
26 "1b0a7408c050e3d09a8be8e21e183ef7ee570385dc41216698cc3ab392a484e7": {"tag": "v0.14.3", "tarball": "limenka-0.14.3-osx64.tar.gz"},
27 "706e0472dbc933ed2757650d54cbcd780fd3829ebf8f609b32780c7eedebdbc9": {"tag": "v0.14.3", "tarball": "limenka-0.14.3-x86_64-linux-gnu.tar.gz"},
28 #
29 "d40f18b4e43c6e6370ef7db9131f584fbb137276ec2e3dba67a4b267f81cb644": {"tag": "v0.15.2", "tarball": "limenka-0.15.2-aarch64-linux-gnu.tar.gz"},
30 "54fb877a148a6ad189a1e1ab1ff8b11181e58ff2aaf430da55b3fd46ae549a6b": {"tag": "v0.15.2", "tarball": "limenka-0.15.2-arm-linux-gnueabihf.tar.gz"},
31 "87e9340ff3d382d543b2b69112376077f0c8b4f7450d372e83b68f5a1e22b2df": {"tag": "v0.15.2", "tarball": "limenka-0.15.2-osx64.tar.gz"},
32 "566be44190fd76daa01f13d428939dadfb8e3daacefc8fa17f433cad28f73bd5": {"tag": "v0.15.2", "tarball": "limenka-0.15.2-x86_64-linux-gnu.tar.gz"},
33 #
34 "0768c6c15caffbaca6524824c9563b42c24f70633c681c2744649158aa3fd484": {"tag": "v0.16.3", "tarball": "limenka-0.16.3-aarch64-linux-gnu.tar.gz"},
35 "fb2818069854a6ad20ea03b28b55dbd35d8b1f7d453e90b83eace5d0098a2a87": {"tag": "v0.16.3", "tarball": "limenka-0.16.3-arm-linux-gnueabihf.tar.gz"},
36 "78c3bff3b619a19aed575961ea43cc9e142959218835cf51aede7f0b764fc25d": {"tag": "v0.16.3", "tarball": "limenka-0.16.3-osx64.tar.gz"},
37 "5d422a9d544742bc0df12427383f9c2517433ce7b58cf672b9a9b17c2ef51e4f": {"tag": "v0.16.3", "tarball": "limenka-0.16.3-x86_64-linux-gnu.tar.gz"},
38 #
39 "5a6b35d1a348a402f2d2d6ab5aed653a1a1f13bc63aaaf51605e3501b0733b7a": {"tag": "v0.17.2", "tarball": "limenka-0.17.2-aarch64-linux-gnu.tar.gz"},
40 "d1913a5d19c8e8da4a67d1bd5205d03c8614dfd2e02bba2fe3087476643a729e": {"tag": "v0.17.2", "tarball": "limenka-0.17.2-arm-linux-gnueabihf.tar.gz"},
41 "a783ba20706dbfd5b47fbedf42165fce70fbbc7d78003305d964f6b3da14887f": {"tag": "v0.17.2", "tarball": "limenka-0.17.2-osx64.tar.gz"},
42 "943f9362b9f11130177839116f48f809d83478b4c28591d486ee9a7e35179da6": {"tag": "v0.17.2", "tarball": "limenka-0.17.2-x86_64-linux-gnu.tar.gz"},
43 #
44 "88f343af72803b851c7da13874cc5525026b0b55e63e1b5e1298390c4688adc6": {"tag": "v0.18.1", "tarball": "limenka-0.18.1-aarch64-linux-gnu.tar.gz"},
45 "cc7d483e4b20c5dabd4dcaf304965214cf4934bcc029ca99cbc9af00d3771a1f": {"tag": "v0.18.1", "tarball": "limenka-0.18.1-arm-linux-gnueabihf.tar.gz"},
46 "b7bbcee7a7540f711b171d6981f939ca8482005fde22689bc016596d80548bb1": {"tag": "v0.18.1", "tarball": "limenka-0.18.1-osx64.tar.gz"},
47 "425ee5ec631ae8da71ebc1c3f5c0269c627cf459379b9b030f047107a28e3ef8": {"tag": "v0.18.1", "tarball": "limenka-0.18.1-riscv64-linux-gnu.tar.gz"},
48 "600d1db5e751fa85903e935a01a74f5cc57e1e7473c15fd3e17ed21e202cfe5a": {"tag": "v0.18.1", "tarball": "limenka-0.18.1-x86_64-linux-gnu.tar.gz"},
49 #
50 "3a80431717842672df682bdb619e66523b59541483297772a7969413be3502ff": {"tag": "v0.19.1", "tarball": "limenka-0.19.1-aarch64-linux-gnu.tar.gz"},
51 "657f28213823d240dd3324d14829702f9ad6f0710f8bdd1c379cb3c447197f48": {"tag": "v0.19.1", "tarball": "limenka-0.19.1-arm-linux-gnueabihf.tar.gz"},
52 "1ae1b87de26487075cd2fd22e0d4ead87d969bd55c44f2f1d873ecdc6147ebb3": {"tag": "v0.19.1", "tarball": "limenka-0.19.1-osx64.tar.gz"},
53 "aa7a9563b48aa79252c8e7b6a41c07a5441bd9f14c5e4562cc72720ea6cb0ee5": {"tag": "v0.19.1", "tarball": "limenka-0.19.1-riscv64-linux-gnu.tar.gz"},
54 "5fcac9416e486d4960e1a946145566350ca670f9aaba99de6542080851122e4c": {"tag": "v0.19.1", "tarball": "limenka-0.19.1-x86_64-linux-gnu.tar.gz"},
55 #
56 "60c93e3462c303eb080be7cf623f1a7684b37fd47a018ad3848bc23e13c84e1c": {"tag": "v0.20.1", "tarball": "limenka-0.20.1-aarch64-linux-gnu.tar.gz"},
57 "55b577e0fb306fb429d4be6c9316607753e8543e5946b542d75d876a2f08654c": {"tag": "v0.20.1", "tarball": "limenka-0.20.1-arm-linux-gnueabihf.tar.gz"},
58 "b9024dde373ea7dad707363e07ec7e265383204127539ae0c234bff3a61da0d1": {"tag": "v0.20.1", "tarball": "limenka-0.20.1-osx64.tar.gz"},
59 "fa71cb52ee5e0459cbf5248cdec72df27995840c796f58b304607a1ed4c165af": {"tag": "v0.20.1", "tarball": "limenka-0.20.1-riscv64-linux-gnu.tar.gz"},
60 "376194f06596ecfa40331167c39bc70c355f960280bd2a645fdbf18f66527397": {"tag": "v0.20.1", "tarball": "limenka-0.20.1-x86_64-linux-gnu.tar.gz"},
61
62 "43416854330914992bbba2d0e9adf2a6fff4130be9af8ae2ef1186e743d9a3fe": {"tag": "v0.21.0", "tarball": "limenka-0.21.0-aarch64-linux-gnu.tar.gz"},
63 "f028af308eda45a3c4c90f9332f96b075bf21e3495c945ebce48597151808176": {"tag": "v0.21.0", "tarball": "limenka-0.21.0-arm-linux-gnueabihf.tar.gz"},
64 "695fb624fa6423f5da4f443b60763dd1d77488bfe5ef63760904a7b54e91298d": {"tag": "v0.21.0", "tarball": "limenka-0.21.0-osx64.tar.gz"},
65 "f8b2adfeae021a672effbc7bd40d5c48d6b94e53b2dd660f787340bf1a52e4e9": {"tag": "v0.21.0", "tarball": "limenka-0.21.0-riscv64-linux-gnu.tar.gz"},
66 "da7766775e3f9c98d7a9145429f2be8297c2672fe5b118fd3dc2411fb48e0032": {"tag": "v0.21.0", "tarball": "limenka-0.21.0-x86_64-linux-gnu.tar.gz"},
67
68 "ac718fed08570a81b3587587872ad85a25173afa5f9fbbd0c03ba4d1714cfa3e": {"tag": "v22.0", "tarball": "limenka-22.0-aarch64-linux-gnu.tar.gz"},
69 "b8713c6c5f03f5258b54e9f436e2ed6d85449aa24c2c9972f91963d413e86311": {"tag": "v22.0", "tarball": "limenka-22.0-arm-linux-gnueabihf.tar.gz"},
70 "2744d199c3343b2d94faffdfb2c94d75a630ba27301a70e47b0ad30a7e0155e9": {"tag": "v22.0", "tarball": "limenka-22.0-osx64.tar.gz"},
71 "2cca5f99007d060aca9d8c7cbd035dfe2f040dd8200b210ce32cdf858479f70d": {"tag": "v22.0", "tarball": "limenka-22.0-powerpc64-linux-gnu.tar.gz"},
72 "91b1e012975c5a363b5b5fcc81b5b7495e86ff703ec8262d4b9afcfec633c30d": {"tag": "v22.0", "tarball": "limenka-22.0-powerpc64le-linux-gnu.tar.gz"},
73 "9cc3a62c469fe57e11485fdd32c916f10ce7a2899299855a2e479256ff49ff3c": {"tag": "v22.0", "tarball": "limenka-22.0-riscv64-linux-gnu.tar.gz"},
74 "59ebd25dd82a51638b7a6bb914586201e67db67b919b2a1ff08925a7936d1b16": {"tag": "v22.0", "tarball": "limenka-22.0-x86_64-linux-gnu.tar.gz"},
75
76 "06f4c78271a77752ba5990d60d81b1751507f77efda1e5981b4e92fd4d9969fb": {"tag": "v23.0", "tarball": "limenka-23.0-aarch64-linux-gnu.tar.gz"},
77 "952c574366aff76f6d6ad1c9ee45a361d64fa04155e973e926dfe7e26f9703a3": {"tag": "v23.0", "tarball": "limenka-23.0-arm-linux-gnueabihf.tar.gz"},
78 "7c8bc63731aa872b7b334a8a7d96e33536ad77d49029bad179b09dca32cd77ac": {"tag": "v23.0", "tarball": "limenka-23.0-arm64-apple-darwin.tar.gz"},
79 "2caa5898399e415f61d9af80a366a3008e5856efa15aaff74b88acf429674c99": {"tag": "v23.0", "tarball": "limenka-23.0-powerpc64-linux-gnu.tar.gz"},
80 "217dd0469d0f4962d22818c368358575f6a0abcba8804807bb75325eb2f28b19": {"tag": "v23.0", "tarball": "limenka-23.0-powerpc64le-linux-gnu.tar.gz"},
81 "078f96b1e92895009c798ab827fb3fde5f6719eee886bd0c0e93acab18ea4865": {"tag": "v23.0", "tarball": "limenka-23.0-riscv64-linux-gnu.tar.gz"},
82 "c816780583009a9dad426dc0c183c89be9da98906e1e2c7ebae91041c1aaaaf3": {"tag": "v23.0", "tarball": "limenka-23.0-x86_64-apple-darwin.tar.gz"},
83 "2cca490c1f2842884a3c5b0606f179f9f937177da4eadd628e3f7fd7e25d26d0": {"tag": "v23.0", "tarball": "limenka-23.0-x86_64-linux-gnu.tar.gz"},
84
85 "0b48b9e69b30037b41a1e6b78fb7cbcc48c7ad627908c99686e81f3802454609": {"tag": "v24.0.1", "tarball": "limenka-24.0.1-aarch64-linux-gnu.tar.gz"},
86 "37d7660f0277301744e96426bbb001d2206b8d4505385dfdeedf50c09aaaef60": {"tag": "v24.0.1", "tarball": "limenka-24.0.1-arm-linux-gnueabihf.tar.gz"},
87 "90ed59e86bfda1256f4b4cad8cc1dd77ee0efec2492bcb5af61402709288b62c": {"tag": "v24.0.1", "tarball": "limenka-24.0.1-arm64-apple-darwin.tar.gz"},
88 "7590645e8676f8b5fda62dc20174474c4ac8fd0defc83a19ed908ebf2e94dc11": {"tag": "v24.0.1", "tarball": "limenka-24.0.1-powerpc64-linux-gnu.tar.gz"},
89 "79e89a101f23ff87816675b98769cd1ee91059f95c5277f38f48f21a9f7f8509": {"tag": "v24.0.1", "tarball": "limenka-24.0.1-powerpc64le-linux-gnu.tar.gz"},
90 "6b163cef7de4beb07b8cb3347095e0d76a584019b1891135cd1268a1f05b9d88": {"tag": "v24.0.1", "tarball": "limenka-24.0.1-riscv64-linux-gnu.tar.gz"},
91 "e2f751512f3c0f00eb68ba946d9c829e6cf99422a61e8f5e0a7c109c318674d0": {"tag": "v24.0.1", "tarball": "limenka-24.0.1-x86_64-apple-darwin.tar.gz"},
92 "49df6e444515d457ea0b885d66f521f2a26ca92ccf73d5296082e633544253bf": {"tag": "v24.0.1", "tarball": "limenka-24.0.1-x86_64-linux-gnu.tar.gz"},
93
94 "3a7bdd959a0b426624f63f394f25e5b7769a5a2f96f8126dcc2ea53f3fa5212b": {"tag": "v25.0", "tarball": "limenka-25.0-aarch64-linux-gnu.tar.gz"},
95 "e537c8630b05e63242d979c3004f851fd73c2a10b5b4fdbb161788427c7b3c0f": {"tag": "v25.0", "tarball": "limenka-25.0-arm-linux-gnueabihf.tar.gz"},
96 "3b35075d6c1209743611c705a13575be2668bc069bc6301ce78a2e1e53ebe7cc": {"tag": "v25.0", "tarball": "limenka-25.0-arm64-apple-darwin.tar.gz"},
97 "0c8e135a6fd297270d3b65196042d761453493a022b5ff7fb847fc911e938214": {"tag": "v25.0", "tarball": "limenka-25.0-powerpc64-linux-gnu.tar.gz"},
98 "fa8af160782f5adfcea570f72b947073c1663b3e9c3cd0f82b216b609fe47573": {"tag": "v25.0", "tarball": "limenka-25.0-powerpc64le-linux-gnu.tar.gz"},
99 "fe6e347a66043946920c72c9c4afca301968101e6b82fb90a63d7885ebcceb32": {"tag": "v25.0", "tarball": "limenka-25.0-riscv64-linux-gnu.tar.gz"},
100 "5708fc639cdfc27347cccfd50db9b73b53647b36fb5f3a4a93537cbe8828c27f": {"tag": "v25.0", "tarball": "limenka-25.0-x86_64-apple-darwin.tar.gz"},
101 "33930d432593e49d58a9bff4c30078823e9af5d98594d2935862788ce8a20aec": {"tag": "v25.0", "tarball": "limenka-25.0-x86_64-linux-gnu.tar.gz"},
102
103 "7fa582d99a25c354d23e371a5848bd9e6a79702870f9cbbf1292b86e647d0f4e": {"tag": "v28.0", "tarball": "limenka-28.0-aarch64-linux-gnu.tar.gz"},
104 "e004b7910bedd6dd18b6c52b4eef398d55971da666487a82cd48708d2879727e": {"tag": "v28.0", "tarball": "limenka-28.0-arm-linux-gnueabihf.tar.gz"},
105 "c8108f30dfcc7ddffab33f5647d745414ef9d3298bfe67d243fe9b9cb4df4c12": {"tag": "v28.0", "tarball": "limenka-28.0-arm64-apple-darwin.tar.gz"},
106 "756df50d8f0c2a3d4111389a7be5f4849e0f5014dd5bfcbc37a8c3aaaa54907b": {"tag": "v28.0", "tarball": "limenka-28.0-powerpc64-linux-gnu.tar.gz"},
107 "6ee1a520b638132a16725020146abea045db418ce91c02493f02f541cd53062a": {"tag": "v28.0", "tarball": "limenka-28.0-riscv64-linux-gnu.tar.gz"},
108 "77e931bbaaf47771a10c376230bf53223f5380864bad3568efc7f4d02e40a0f7": {"tag": "v28.0", "tarball": "limenka-28.0-x86_64-apple-darwin.tar.gz"},
109 "7fe294b02b25b51acb8e8e0a0eb5af6bbafa7cd0c5b0e5fcbb61263104a82fbc": {"tag": "v28.0", "tarball": "limenka-28.0-x86_64-linux-gnu.tar.gz"},
110 }
111
112
113 @contextlib.contextmanager
114 def pushd(new_dir) -> None:
115 previous_dir = os.getcwd()
116 os.chdir(new_dir)
117 try:
118 yield
119 finally:
120 os.chdir(previous_dir)
121
122
123 def download_binary(tag, args) -> int:
124 if Path(tag).is_dir():
125 if not args.remove_dir:
126 print('Using cached {}'.format(tag))
127 return 0
128 shutil.rmtree(tag)
129 Path(tag).mkdir()
130 bin_path = 'bin/limenka-{}'.format(tag[1:])
131 match = re.compile('v(.*)(rc[0-9]+)$').search(tag)
132 if match:
133 bin_path = 'bin/limenka-{}/test.{}'.format(
134 match.group(1), match.group(2))
135 platform = args.platform
136 if tag < "v23" and platform in ["x86_64-apple-darwin", "arm64-apple-darwin"]:
137 platform = "osx64"
138 tarball = 'limenka-{tag}-{platform}.tar.gz'.format(
139 tag=tag[1:], platform=platform)
140 tarballUrl = 'https://limenkacore.org/{bin_path}/{tarball}'.format(
141 bin_path=bin_path, tarball=tarball)
142
143 print('Fetching: {tarballUrl}'.format(tarballUrl=tarballUrl))
144
145 ret = subprocess.run(['curl', '--fail', '--remote-name', tarballUrl]).returncode
146 if ret:
147 print("Retrying download after failure ...", file=sys.stderr)
148 time.sleep(12)
149 ret = subprocess.run(['curl', '--fail', '--remote-name', tarballUrl]).returncode
150 if ret:
151 print("\nDownload failed a second time", file=sys.stderr)
152 return ret
153
154 hasher = hashlib.sha256()
155 with open(tarball, "rb") as afile:
156 hasher.update(afile.read())
157 tarballHash = hasher.hexdigest()
158
159 if tarballHash not in SHA256_SUMS or SHA256_SUMS[tarballHash]['tarball'] != tarball:
160 if tarball in [v['tarball'] for v in SHA256_SUMS.values()]:
161 print("Checksum did not match")
162 return 1
163
164 print("Checksum for given version doesn't exist")
165 return 1
166 print("Checksum matched")
167
168 # Extract tarball
169 ret = subprocess.run(['tar', '-zxf', tarball, '-C', tag,
170 '--strip-components=1',
171 'limenka-{tag}'.format(tag=tag[1:])]).returncode
172 if ret != 0:
173 print(f"Failed to extract the {tag} tarball")
174 return ret
175
176 Path(tarball).unlink()
177
178 if tag >= "v23" and platform == "arm64-apple-darwin":
179 # Starting with v23 there are arm64 binaries for ARM (e.g. M1, M2) macs, but they have to be signed to run
180 binary_path = f'{os.getcwd()}/{tag}/bin/'
181
182 for arm_binary in os.listdir(binary_path):
183 # Is it already signed?
184 ret = subprocess.run(
185 ['codesign', '-v', binary_path + arm_binary],
186 stderr=subprocess.DEVNULL, # Suppress expected stderr output
187 ).returncode
188 if ret == 1:
189 # Have to self-sign the binary
190 ret = subprocess.run(
191 ['codesign', '-s', '-', binary_path + arm_binary]
192 ).returncode
193 if ret != 0:
194 print(f"Failed to self-sign {tag} {arm_binary} arm64 binary")
195 return 1
196
197 # Confirm success
198 ret = subprocess.run(
199 ['codesign', '-v', binary_path + arm_binary]
200 ).returncode
201 if ret != 0:
202 print(f"Failed to verify the self-signed {tag} {arm_binary} arm64 binary")
203 return 1
204
205 return 0
206
207
208 def build_release(tag, args) -> int:
209 githubUrl = "https://github.com/limenka/limenka"
210 if args.remove_dir:
211 if Path(tag).is_dir():
212 shutil.rmtree(tag)
213 if not Path(tag).is_dir():
214 # fetch new tags
215 subprocess.run(
216 ["git", "fetch", githubUrl, "--tags"])
217 output = subprocess.check_output(['git', 'tag', '-l', tag])
218 if not output:
219 print('Tag {} not found'.format(tag))
220 return 1
221 ret = subprocess.run([
222 'git', 'clone', f'--branch={tag}', '--depth=1', githubUrl, tag
223 ]).returncode
224 if ret:
225 return ret
226 with pushd(tag):
227 host = args.host
228 if args.depends:
229 with pushd('depends'):
230 ret = subprocess.run(['make', 'NO_QT=1']).returncode
231 if ret:
232 return ret
233 host = os.environ.get(
234 'HOST', subprocess.check_output(['./config.guess']))
235 config_flags = '--prefix={pwd}/depends/{host} '.format(
236 pwd=os.getcwd(),
237 host=host) + args.config_flags
238 cmds = [
239 './autogen.sh',
240 './configure {}'.format(config_flags),
241 'make',
242 ]
243 for cmd in cmds:
244 ret = subprocess.run(cmd.split()).returncode
245 if ret:
246 return ret
247 # Move binaries, so they're in the same place as in the
248 # release download
249 Path('bin').mkdir(exist_ok=True)
250 files = ['limenkad', 'limenka-cli', 'limenka-tx']
251 for f in files:
252 Path('src/'+f).rename('bin/'+f)
253 return 0
254
255
256 def check_host(args) -> int:
257 args.host = os.environ.get('HOST', subprocess.check_output(
258 './depends/config.guess').decode())
259 if args.download_binary:
260 platforms = {
261 'aarch64-*-linux*': 'aarch64-linux-gnu',
262 'powerpc64le-*-linux-*': 'powerpc64le-linux-gnu',
263 'riscv64-*-linux*': 'riscv64-linux-gnu',
264 'x86_64-*-linux*': 'x86_64-linux-gnu',
265 'x86_64-apple-darwin*': 'x86_64-apple-darwin',
266 'aarch64-apple-darwin*': 'arm64-apple-darwin',
267 }
268 args.platform = ''
269 for pattern, target in platforms.items():
270 if fnmatch(args.host, pattern):
271 args.platform = target
272 if not args.platform:
273 print('Not sure which binary to download for {}'.format(args.host))
274 return 1
275 return 0
276
277
278 def main(args) -> int:
279 Path(args.target_dir).mkdir(exist_ok=True, parents=True)
280 print("Releases directory: {}".format(args.target_dir))
281 ret = check_host(args)
282 if ret:
283 return ret
284 if args.download_binary:
285 with pushd(args.target_dir):
286 for tag in args.tags:
287 ret = download_binary(tag, args)
288 if ret:
289 return ret
290 return 0
291 args.config_flags = os.environ.get('CONFIG_FLAGS', '')
292 args.config_flags += ' --without-gui --disable-tests --disable-bench'
293 with pushd(args.target_dir):
294 for tag in args.tags:
295 ret = build_release(tag, args)
296 if ret:
297 return ret
298 return 0
299
300
301 if __name__ == '__main__':
302 parser = argparse.ArgumentParser(
303 formatter_class=argparse.ArgumentDefaultsHelpFormatter)
304 parser.add_argument('-r', '--remove-dir', action='store_true',
305 help='remove existing directory.')
306 parser.add_argument('-d', '--depends', action='store_true',
307 help='use depends.')
308 parser.add_argument('-b', '--download-binary', action='store_true',
309 help='download release binary.')
310 parser.add_argument('-t', '--target-dir', action='store',
311 help='target directory.', default='releases')
312 all_tags = sorted([*set([v['tag'] for v in SHA256_SUMS.values()])])
313 parser.add_argument('tags', nargs='*', default=all_tags,
314 help='release tags. e.g.: v0.18.1 v0.20.0rc2 '
315 '(if not specified, the full list needed for '
316 'backwards compatibility tests will be used)'
317 )
318 args = parser.parse_args()
319 sys.exit(main(args))
320