12
12
from zipfile import ZipFile , ZipInfo , ZIP_DEFLATED
13
13
14
14
15
- ZIG_VERSION_INFO_URL = ' https://ziglang.org/download/index.json'
15
+ ZIG_VERSION_INFO_URL = " https://ziglang.org/download/index.json"
16
16
ZIG_PYTHON_PLATFORMS = {
17
- ' x86_64-windows' : ' win_amd64' ,
18
- ' x86-windows' : ' win32' ,
19
- ' x86_64-macos' : ' macosx_12_0_x86_64' ,
20
- ' aarch64-macos' : ' macosx_12_0_arm64' ,
21
- ' i386-linux' : ' manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686' ,
17
+ " x86_64-windows" : " win_amd64" ,
18
+ " x86-windows" : " win32" ,
19
+ " x86_64-macos" : " macosx_12_0_x86_64" ,
20
+ " aarch64-macos" : " macosx_12_0_arm64" ,
21
+ " i386-linux" : " manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686" ,
22
22
# renamed i386 to x86 since v0.11.0, i386 was last supported in v0.10.1
23
- 'x86-linux' : 'manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686' ,
24
- 'x86_64-linux' : 'manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64' ,
25
- 'aarch64-linux' :
26
- 'manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64' ,
27
- 'armv7a-linux' : 'manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l' ,
28
- 'powerpc64le-linux' : 'manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le' ,
23
+ "x86-linux" : "manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686" ,
24
+ "x86_64-linux" : "manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64" ,
25
+ "aarch64-linux" : "manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64" ,
26
+ "armv7a-linux" : "manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l" ,
27
+ "powerpc64le-linux" : "manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le" ,
29
28
}
30
29
31
30
@@ -42,7 +41,7 @@ def writestr(self, zinfo_or_arcname, data, *args, **kwargs):
42
41
zinfo .external_attr = 0o0664 << 16
43
42
44
43
zinfo .compress_type = ZIP_DEFLATED
45
- zinfo .date_time = (1980 ,1 , 1 , 0 , 0 , 0 )
44
+ zinfo .date_time = (1980 , 1 , 1 , 0 , 0 , 0 )
46
45
zinfo .create_system = 3
47
46
super ().writestr (zinfo , data , * args , ** kwargs )
48
47
@@ -61,34 +60,42 @@ def make_message(headers, payload=None):
61
60
62
61
63
62
def write_wheel_file (filename , contents ):
64
- with ReproducibleWheelFile (filename , 'w' ) as wheel :
63
+ with ReproducibleWheelFile (filename , "w" ) as wheel :
65
64
for member_info , member_source in contents .items ():
66
65
wheel .writestr (member_info , bytes (member_source ))
67
66
return filename
68
67
69
68
70
69
def write_wheel (out_dir , * , name , version , tag , metadata , description , contents ):
71
- wheel_name = f' { name } -{ version } -{ tag } .whl'
72
- dist_info = f' { name } -{ version } .dist-info'
70
+ wheel_name = f" { name } -{ version } -{ tag } .whl"
71
+ dist_info = f" { name } -{ version } .dist-info"
73
72
filtered_metadata = []
74
73
for header , value in metadata :
75
74
filtered_metadata .append ((header , value ))
76
75
77
- return write_wheel_file (os .path .join (out_dir , wheel_name ), {
78
- ** contents ,
79
- f'{ dist_info } /METADATA' : make_message ([
80
- ('Metadata-Version' , '2.4' ),
81
- ('Name' , name ),
82
- ('Version' , version ),
83
- * filtered_metadata ,
84
- ], description ),
85
- f'{ dist_info } /WHEEL' : make_message ([
86
- ('Wheel-Version' , '1.0' ),
87
- ('Generator' , 'ziglang make_wheels.py' ),
88
- ('Root-Is-Purelib' , 'false' ),
89
- ('Tag' , tag ),
90
- ]),
91
- })
76
+ return write_wheel_file (
77
+ os .path .join (out_dir , wheel_name ),
78
+ {
79
+ ** contents ,
80
+ f"{ dist_info } /METADATA" : make_message (
81
+ [
82
+ ("Metadata-Version" , "2.4" ),
83
+ ("Name" , name ),
84
+ ("Version" , version ),
85
+ * filtered_metadata ,
86
+ ],
87
+ description ,
88
+ ),
89
+ f"{ dist_info } /WHEEL" : make_message (
90
+ [
91
+ ("Wheel-Version" , "1.0" ),
92
+ ("Generator" , "ziglang make_wheels.py" ),
93
+ ("Root-Is-Purelib" , "false" ),
94
+ ("Tag" , tag ),
95
+ ]
96
+ ),
97
+ },
98
+ )
92
99
93
100
94
101
def iter_archive_contents (archive ):
@@ -109,37 +116,37 @@ def iter_archive_contents(archive):
109
116
110
117
def write_ziglang_wheel (out_dir , * , version , platform , archive ):
111
118
contents = {}
112
- contents [' ziglang/__init__.py' ] = b''
119
+ contents [" ziglang/__init__.py" ] = b""
113
120
114
121
license_files = {}
115
122
116
123
# The paths to these licenses MUST match both the actual files
117
124
# in the Zig source tarballs and the License-File entries listed
118
125
# below in the metadata.
119
126
license_paths = [
120
- ' LICENSE' ,
121
- ' lib/libc/glibc/LICENSES' ,
122
- ' lib/libc/mingw/COPYING' ,
123
- ' lib/libc/musl/COPYRIGHT' ,
124
- ' lib/libc/wasi/LICENSE' ,
125
- ' lib/libc/wasi/LICENSE-APACHE' ,
126
- ' lib/libc/wasi/LICENSE-APACHE-LLVM' ,
127
- ' lib/libc/wasi/LICENSE-MIT' ,
128
- ' lib/libcxx/LICENSE.TXT' ,
129
- ' lib/libcxxabi/LICENSE.TXT' ,
130
- ' lib/libunwind/LICENSE.TXT'
127
+ " LICENSE" ,
128
+ " lib/libc/glibc/LICENSES" ,
129
+ " lib/libc/mingw/COPYING" ,
130
+ " lib/libc/musl/COPYRIGHT" ,
131
+ " lib/libc/wasi/LICENSE" ,
132
+ " lib/libc/wasi/LICENSE-APACHE" ,
133
+ " lib/libc/wasi/LICENSE-APACHE-LLVM" ,
134
+ " lib/libc/wasi/LICENSE-MIT" ,
135
+ " lib/libcxx/LICENSE.TXT" ,
136
+ " lib/libcxxabi/LICENSE.TXT" ,
137
+ " lib/libunwind/LICENSE.TXT" ,
131
138
]
132
139
133
140
found_license_files = set ()
134
141
135
142
for entry_name , entry_mode , entry_data in iter_archive_contents (archive ):
136
- entry_name = '/' .join (entry_name .split ('/' )[1 :])
143
+ entry_name = "/" .join (entry_name .split ("/" )[1 :])
137
144
if not entry_name :
138
145
continue
139
- if entry_name .startswith (' doc/' ):
146
+ if entry_name .startswith (" doc/" ):
140
147
continue
141
148
142
- zip_info = ZipInfo (f' ziglang/{ entry_name } ' )
149
+ zip_info = ZipInfo (f" ziglang/{ entry_name } " )
143
150
zip_info .external_attr = (entry_mode & 0xFFFF ) << 16
144
151
contents [zip_info ] = entry_data
145
152
@@ -149,15 +156,19 @@ def write_ziglang_wheel(out_dir, *, version, platform, archive):
149
156
license_files [entry_name ] = entry_data # adding to license files
150
157
found_license_files .add (entry_name ) # tracking found licenses
151
158
152
- if entry_name .startswith ('zig' ):
153
- contents ['ziglang/__main__.py' ] = f'''\
159
+ if entry_name .startswith ("zig" ):
160
+ contents ["ziglang/__main__.py" ] = (
161
+ f"""\
154
162
import os, sys
155
163
argv = [os.path.join(os.path.dirname(__file__), "{ entry_name } "), *sys.argv[1:]]
156
164
if os.name == 'posix':
157
165
os.execv(argv[0], argv)
158
166
else:
159
167
import subprocess; sys.exit(subprocess.call(argv))
160
- ''' .encode ('ascii' )
168
+ """ .encode (
169
+ "ascii"
170
+ )
171
+ )
161
172
162
173
# Check if any license files are missing and warn. This
163
174
# is useful to detect changes in the Zig archive structure
@@ -167,46 +178,47 @@ def write_ziglang_wheel(out_dir, *, version, platform, archive):
167
178
print (f"Warning: The following license files were not found in the Zig archive: { ', ' .join (sorted (missing_licenses ))} " )
168
179
print ("This may indicate a change in Zig's license file structure or an error in the list of license files and/or paths." )
169
180
170
- with open (' README.pypi.md' ) as f :
181
+ with open (" README.pypi.md" ) as f :
171
182
description = f .read ()
172
183
173
- dist_info = f' ziglang-{ version } .dist-info'
184
+ dist_info = f" ziglang-{ version } .dist-info"
174
185
for license_path , license_data in license_files .items ():
175
- contents [f' { dist_info } /licenses/{ license_path } ' ] = license_data
186
+ contents [f" { dist_info } /licenses/{ license_path } " ] = license_data
176
187
177
- return write_wheel (out_dir ,
178
- name = 'ziglang' ,
188
+ return write_wheel (
189
+ out_dir ,
190
+ name = "ziglang" ,
179
191
version = version ,
180
- tag = f' py3-none-{ platform } ' ,
192
+ tag = f" py3-none-{ platform } " ,
181
193
metadata = [
182
- (' Summary' , ' Zig is a general-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.' ),
183
- (' Description-Content-Type' , "'text/markdown'; charset=UTF-8; variant=GFM" ),
194
+ (" Summary" , " Zig is a general-purpose programming language and toolchain for maintaining robust, optimal, and reusable software." ),
195
+ (" Description-Content-Type" , "'text/markdown'; charset=UTF-8; variant=GFM" ),
184
196
# The license expression and the file paths MUST remain in sync
185
197
# with the paths in the official Zig tarballs and with the ones
186
198
# defined above in the contents.
187
- (' License-Expression' , ' MIT' ),
188
- (' License-File' , ' LICENSE' ),
189
- (' License-File' , ' lib/libc/glibc/LICENSES' ),
190
- (' License-File' , ' lib/libc/mingw/COPYING' ),
191
- (' License-File' , ' lib/libc/musl/COPYRIGHT' ),
192
- (' License-File' , ' lib/libc/wasi/LICENSE' ),
193
- (' License-File' , ' lib/libc/wasi/LICENSE-APACHE' ),
194
- (' License-File' , ' lib/libc/wasi/LICENSE-APACHE-LLVM' ),
195
- (' License-File' , ' lib/libc/wasi/LICENSE-MIT' ),
196
- (' License-File' , ' lib/libcxx/LICENSE.TXT' ),
197
- (' License-File' , ' lib/libcxxabi/LICENSE.TXT' ),
198
- (' License-File' , ' lib/libunwind/LICENSE.TXT' ),
199
- (' Classifier' , ' Development Status :: 4 - Beta' ),
200
- (' Classifier' , ' Intended Audience :: Developers' ),
201
- (' Classifier' , ' Topic :: Software Development :: Compilers' ),
202
- (' Classifier' , ' Topic :: Software Development :: Code Generators' ),
203
- (' Classifier' , ' Topic :: Software Development :: Build Tools' ),
204
- (' Classifier' , ' Programming Language :: Other' ),
205
- (' Classifier' , ' Programming Language :: Other Scripting Engines' ),
206
- (' Project-URL' , ' Homepage, https://ziglang.org' ),
207
- (' Project-URL' , ' Source Code, https://github.com/ziglang/zig-pypi' ),
208
- (' Project-URL' , ' Bug Tracker, https://github.com/ziglang/zig-pypi/issues' ),
209
- (' Requires-Python' , ' ~=3.5' ),
199
+ (" License-Expression" , " MIT" ),
200
+ (" License-File" , " LICENSE" ),
201
+ (" License-File" , " lib/libc/glibc/LICENSES" ),
202
+ (" License-File" , " lib/libc/mingw/COPYING" ),
203
+ (" License-File" , " lib/libc/musl/COPYRIGHT" ),
204
+ (" License-File" , " lib/libc/wasi/LICENSE" ),
205
+ (" License-File" , " lib/libc/wasi/LICENSE-APACHE" ),
206
+ (" License-File" , " lib/libc/wasi/LICENSE-APACHE-LLVM" ),
207
+ (" License-File" , " lib/libc/wasi/LICENSE-MIT" ),
208
+ (" License-File" , " lib/libcxx/LICENSE.TXT" ),
209
+ (" License-File" , " lib/libcxxabi/LICENSE.TXT" ),
210
+ (" License-File" , " lib/libunwind/LICENSE.TXT" ),
211
+ (" Classifier" , " Development Status :: 4 - Beta" ),
212
+ (" Classifier" , " Intended Audience :: Developers" ),
213
+ (" Classifier" , " Topic :: Software Development :: Compilers" ),
214
+ (" Classifier" , " Topic :: Software Development :: Code Generators" ),
215
+ (" Classifier" , " Topic :: Software Development :: Build Tools" ),
216
+ (" Classifier" , " Programming Language :: Other" ),
217
+ (" Classifier" , " Programming Language :: Other Scripting Engines" ),
218
+ (" Project-URL" , " Homepage, https://ziglang.org" ),
219
+ (" Project-URL" , " Source Code, https://github.com/ziglang/zig-pypi" ),
220
+ (" Project-URL" , " Bug Tracker, https://github.com/ziglang/zig-pypi/issues" ),
221
+ (" Requires-Python" , " ~=3.5" ),
210
222
],
211
223
description = description ,
212
224
contents = contents ,
@@ -218,69 +230,60 @@ def fetch_zig_version_info():
218
230
return json .loads (request .read ())
219
231
220
232
221
- def fetch_and_write_ziglang_wheels (
222
- outdir = 'dist/' , zig_version = 'master' , wheel_version_suffix = '' , platforms = tuple ()
223
- ):
233
+ def fetch_and_write_ziglang_wheels (outdir = "dist/" , zig_version = "master" , wheel_version_suffix = "" , platforms = tuple ()):
224
234
Path (outdir ).mkdir (exist_ok = True )
225
235
if not platforms :
226
236
platforms = list (ZIG_PYTHON_PLATFORMS )
227
237
zig_versions_info = fetch_zig_version_info ()
228
238
229
- if zig_version == ' latest' :
230
- zig_version = [version for version in zig_versions_info if version != ' master' ][0 ]
239
+ if zig_version == " latest" :
240
+ zig_version = [version for version in zig_versions_info if version != " master" ][0 ]
231
241
232
242
try :
233
243
zig_version_info = zig_versions_info [zig_version ]
234
244
except KeyError :
235
245
print (f"Invalid version, valid values: { list (zig_versions_info )} " )
236
246
raise
237
247
238
- effective_zig_version = zig_version_info .get (' version' , zig_version )
248
+ effective_zig_version = zig_version_info .get (" version" , zig_version )
239
249
240
250
for zig_platform in platforms :
241
251
python_platform = ZIG_PYTHON_PLATFORMS [zig_platform ]
242
252
if zig_platform not in zig_version_info :
243
- print (f"{ zig_platform } not present for "
244
- f"version { zig_version } / { effective_zig_version } " )
253
+ print (f"{ zig_platform } not present for " f"version { zig_version } / { effective_zig_version } " )
245
254
continue
246
255
zig_download = zig_version_info [zig_platform ]
247
- zig_url = zig_download [' tarball' ]
248
- expected_hash = zig_download [' shasum' ]
256
+ zig_url = zig_download [" tarball" ]
257
+ expected_hash = zig_download [" shasum" ]
249
258
250
259
with urllib .request .urlopen (zig_url ) as request :
251
260
zig_archive = request .read ()
252
261
zig_archive_hash = hashlib .sha256 (zig_archive ).hexdigest ()
253
262
if zig_archive_hash != expected_hash :
254
263
print (zig_download , "SHA256 hash mismatch!" )
255
264
raise AssertionError
256
- print (f' { hashlib .sha256 (zig_archive ).hexdigest ()} { zig_url } ' )
265
+ print (f" { hashlib .sha256 (zig_archive ).hexdigest ()} { zig_url } " )
257
266
258
- wheel_version = effective_zig_version .split ('+' )[0 ].replace ('-' , '.' )
259
- wheel_path = write_ziglang_wheel (outdir ,
260
- version = wheel_version + wheel_version_suffix ,
261
- platform = python_platform ,
262
- archive = zig_archive )
263
- with open (wheel_path , 'rb' ) as wheel :
264
- print (f' { hashlib .sha256 (wheel .read ()).hexdigest ()} { wheel_path } ' )
267
+ wheel_version = effective_zig_version .split ("+" )[0 ].replace ("-" , "." )
268
+ wheel_path = write_ziglang_wheel (outdir , version = wheel_version + wheel_version_suffix , platform = python_platform , archive = zig_archive )
269
+ with open (wheel_path , "rb" ) as wheel :
270
+ print (f" { hashlib .sha256 (wheel .read ()).hexdigest ()} { wheel_path } " )
265
271
266
272
267
273
def get_argparser ():
268
274
parser = argparse .ArgumentParser (prog = __file__ , description = "Repackage official Zig downloads as Python wheels" )
269
- parser .add_argument ('--version' , default = 'latest' ,
270
- help = "version to package, use `latest` for latest release, `master` for nightly build" )
271
- parser .add_argument ('--suffix' , default = '' , help = "wheel version suffix" )
272
- parser .add_argument ('--outdir' , default = 'dist/' , help = "target directory" )
273
- parser .add_argument ('--platform' , action = 'append' , choices = list (ZIG_PYTHON_PLATFORMS .keys ()), default = [],
274
- help = "platform to build for, can be repeated" )
275
+ parser .add_argument ("--version" , default = "latest" , help = "version to package, use `latest` for latest release, `master` for nightly build" )
276
+ parser .add_argument ("--suffix" , default = "" , help = "wheel version suffix" )
277
+ parser .add_argument ("--outdir" , default = "dist/" , help = "target directory" )
278
+ parser .add_argument ("--platform" , action = "append" , choices = list (ZIG_PYTHON_PLATFORMS .keys ()), default = [], help = "platform to build for, can be repeated" )
275
279
return parser
276
280
277
281
278
282
def main ():
279
283
args = get_argparser ().parse_args ()
280
284
logging .getLogger ("wheel" ).setLevel (logging .WARNING )
281
- fetch_and_write_ziglang_wheels (outdir = args .outdir , zig_version = args .version ,
282
- wheel_version_suffix = args .suffix , platforms = args .platform )
285
+ fetch_and_write_ziglang_wheels (outdir = args .outdir , zig_version = args .version , wheel_version_suffix = args .suffix , platforms = args .platform )
283
286
284
287
285
- if __name__ == ' __main__' :
288
+ if __name__ == " __main__" :
286
289
main ()
0 commit comments