@@ -12,6 +12,7 @@ interface for those not familiar with the python
12
12
ecosystem.
13
13
14
14
"""
15
+
15
16
import os
16
17
import sys
17
18
import subprocess
@@ -31,10 +32,13 @@ PINNED_RUNTIME_DEPS = [
31
32
# require extra build time dependencies. We are pinning it to
32
33
# a version that does not need those.
33
34
('colorama' , '0.4.5' ),
35
+ # 2.0.0 of urllib3 started requiring hatchling as well
36
+ ('urllib3' , '1.26.20' ),
34
37
]
35
38
BUILDTIME_DEPS = [
39
+ ('setuptools' , '75.4.0' ), # start of >= 3.9
36
40
('setuptools-scm' , '3.3.3' ),
37
- ('wheel' , '0.33.6 ' ),
41
+ ('wheel' , '0.45.1 ' ), # 0.46.0+ requires packaging
38
42
]
39
43
PIP_DOWNLOAD_ARGS = '--no-build-isolation --no-binary :all:'
40
44
@@ -54,14 +58,14 @@ def cd(dirname):
54
58
55
59
56
60
def run (cmd ):
57
- sys .stdout .write ("Running cmd: %s\n " % cmd )
58
- p = subprocess .Popen (cmd , shell = True , stdout = subprocess .PIPE ,
59
- stderr = subprocess .PIPE )
61
+ sys .stdout .write (f"Running cmd: { cmd } \n " )
62
+ p = subprocess .Popen (
63
+ cmd , shell = True , stdout = subprocess .PIPE , stderr = subprocess .PIPE
64
+ )
60
65
stdout , stderr = p .communicate ()
61
66
rc = p .wait ()
62
67
if p .returncode != 0 :
63
- raise BadRCError ("Bad rc (%s) for cmd '%s': %s" % (
64
- rc , cmd , stderr + stdout ))
68
+ raise BadRCError (f"Bad rc ({ rc } ) for cmd '{ cmd } ': { stderr + stdout } " )
65
69
return stdout
66
70
67
71
@@ -79,17 +83,33 @@ def create_scratch_dir():
79
83
def download_package_tarballs (dirname , packages ):
80
84
with cd (dirname ):
81
85
for package , package_version in packages :
82
- run ('%s -m pip download %s==%s %s' % (
83
- sys .executable , package , package_version , PIP_DOWNLOAD_ARGS
84
- ))
86
+ run (
87
+ f'{ sys .executable } -m pip download { package } =={ package_version } '
88
+ f' { PIP_DOWNLOAD_ARGS } '
89
+ )
90
+
91
+
92
+ def download_package_wheels (dirname , packages ):
93
+ with cd (dirname ):
94
+ for package , package_version in packages :
95
+ run (
96
+ f'{ sys .executable } -m pip download { package } =={ package_version } '
97
+ f' --only-binary :all:'
98
+ )
99
+
100
+
101
+ def validate_that_wheels_are_universal (dirname ):
102
+ with cd (dirname ):
103
+ for wheel_path in os .listdir ():
104
+ if not wheel_path .endswith ('py3-none-any.whl' ):
105
+ raise ValueError (f'Found a non universal wheel: { wheel_path } ' )
85
106
86
107
87
108
def download_cli_deps (scratch_dir , packages ):
88
109
# pip download will always download a more recent version of a package
89
110
# even if one exists locally. The list of packages supplied in `packages`
90
111
# forces the use of a specific runtime dependency.
91
- awscli_dir = os .path .dirname (
92
- os .path .dirname (os .path .abspath (__file__ )))
112
+ awscli_dir = os .path .dirname (os .path .dirname (os .path .abspath (__file__ )))
93
113
pinned_packages = " " .join (
94
114
f"{ name } =={ version } " for (name , version ) in packages
95
115
)
@@ -104,20 +124,21 @@ def _remove_cli_zip(scratch_dir):
104
124
105
125
106
126
def add_cli_sdist (scratch_dir ):
107
- awscli_dir = os .path .dirname (
108
- os .path .dirname (os .path .abspath (__file__ )))
127
+ awscli_dir = os .path .dirname (os .path .dirname (os .path .abspath (__file__ )))
109
128
if os .path .exists (os .path .join (awscli_dir , 'dist' )):
110
129
shutil .rmtree (os .path .join (awscli_dir , 'dist' ))
111
130
with cd (awscli_dir ):
112
- run ('%s setup.py sdist' % sys . executable )
131
+ run (f' { sys . executable } setup.py sdist' )
113
132
filename = os .listdir ('dist' )[0 ]
114
- shutil .move (os .path .join ('dist' , filename ),
115
- os .path .join (scratch_dir , filename ))
133
+ shutil .move (
134
+ os .path .join ('dist' , filename ), os .path .join (scratch_dir , filename )
135
+ )
116
136
117
137
118
138
def create_bootstrap_script (scratch_dir ):
119
139
install_script = os .path .join (
120
- os .path .dirname (os .path .abspath (__file__ )), 'install' )
140
+ os .path .dirname (os .path .abspath (__file__ )), 'install'
141
+ )
121
142
shutil .copy (install_script , os .path .join (scratch_dir , 'install' ))
122
143
123
144
@@ -139,11 +160,11 @@ def zip_dir(scratch_dir):
139
160
def verify_preconditions ():
140
161
# The pip version looks like:
141
162
# 'pip 1.4.1 from ....'
142
- pip_version = run (
143
- '%s -m pip --version' % sys .executable ).strip ().split ()[1 ]
163
+ pip_version = run (f'{ sys .executable } -m pip --version' ).strip ().split ()[1 ]
144
164
# Virtualenv version just has the version string: '1.14.5\n'
145
165
virtualenv_version = run (
146
- '%s -m virtualenv --version' % sys .executable ).strip ()
166
+ f'{ sys .executable } -m virtualenv --version'
167
+ ).strip ()
147
168
_min_version_required ('9.0.1' , pip_version , 'pip' )
148
169
_min_version_required ('15.1.0' , virtualenv_version , 'virtualenv' )
149
170
@@ -156,15 +177,17 @@ def _min_version_required(min_version, actual_version, name):
156
177
for min_version_part , actual_version_part in zip (min_split , actual_split ):
157
178
if int (actual_version_part ) >= int (min_version_part ):
158
179
return
159
- raise ValueError ("%s requires at least version %s, but version %s was "
160
- "found." % (name , min_version , actual_version ))
180
+ raise ValueError (
181
+ f'{ name } requires at least version { min_version } , '
182
+ f'but version { actual_version } was found.'
183
+ )
161
184
162
185
163
186
def main ():
164
187
verify_preconditions ()
165
188
scratch_dir = create_scratch_dir ()
166
189
package_dir = os .path .join (scratch_dir , 'packages' )
167
- print ("Bundle dir at: %s" % scratch_dir )
190
+ print (f "Bundle dir at: { scratch_dir } " )
168
191
download_package_tarballs (
169
192
package_dir ,
170
193
packages = EXTRA_RUNTIME_DEPS ,
@@ -174,17 +197,19 @@ def main():
174
197
# manually install them. We isolate them to a particular directory so we
175
198
# can run the install before the things they're dependent on. We have to do
176
199
# this because pip won't actually find them since it doesn't handle build
177
- # dependencies.
200
+ # dependencies. We use wheels for this, to avoid bootstrapping setuptools
201
+ # in 3.12+ where it's no longer included by default.
178
202
setup_dir = os .path .join (package_dir , 'setup' )
179
- download_package_tarballs (
203
+ download_package_wheels (
180
204
setup_dir ,
181
205
packages = BUILDTIME_DEPS ,
182
206
)
207
+ validate_that_wheels_are_universal (setup_dir )
183
208
download_cli_deps (package_dir , packages = PINNED_RUNTIME_DEPS )
184
209
add_cli_sdist (package_dir )
185
210
create_bootstrap_script (scratch_dir )
186
211
zip_filename = zip_dir (scratch_dir )
187
- print ("Zipped bundle installer is at: %s" % zip_filename )
212
+ print (f "Zipped bundle installer is at: { zip_filename } " )
188
213
189
214
190
215
if __name__ == '__main__' :
0 commit comments