Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(99)

Side by Side Diff: bootstrap/bootstrap.py

Issue 2520493003: Vendor virtualenv, update to 15.1.0. (Closed)
Patch Set: Fix cache directory usage, now hermetic w/ deps-dir. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « .gitignore ('k') | bootstrap/update_vendoring.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright 2016 The LUCI Authors. All rights reserved. 2 # Copyright 2016 The LUCI Authors. All rights reserved.
3 # Use of this source code is governed under the Apache License, Version 2.0 3 # Use of this source code is governed under the Apache License, Version 2.0
4 # that can be found in the LICENSE file. 4 # that can be found in the LICENSE file.
5 5
6 import argparse 6 import argparse
7 import contextlib 7 import contextlib
8 import glob 8 import glob
9 import logging 9 import logging
10 import os 10 import os
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 return entries 67 return entries
68 68
69 69
70 def sha_for(deps_entry): 70 def sha_for(deps_entry):
71 if 'rev' in deps_entry: 71 if 'rev' in deps_entry:
72 return deps_entry['rev'] 72 return deps_entry['rev']
73 else: 73 else:
74 return deps_entry['gs'].split('.')[0] 74 return deps_entry['gs'].split('.')[0]
75 75
76 76
77 def get_links(deps): 77 def install(deps, cache_root):
78 import pip.wheel # pylint: disable=E0611
79 plat_tag = platform_tag()
80
81 links = []
82
83 for name, dep in deps.iteritems():
84 version, source_sha = dep['version'] , sha_for(dep)
85 prefix = 'wheels/{}-{}-{}_{}'.format(name, version, dep['build'],
86 source_sha)
87 generic_link = None
88 binary_link = None
89 local_link = None
90
91 for entry in ls(prefix):
92 fname = entry['name'].split('/')[-1]
93 md5hash = entry['md5Hash']
94 wheel_info = pip.wheel.Wheel.wheel_file_re.match(fname)
95 if not wheel_info:
96 LOGGER.warn('Skipping invalid wheel: %r', fname)
97 continue
98
99 if pip.wheel.Wheel(fname).supported():
100 if entry['local']:
101 link = LOCAL_OBJECT_URL.format(entry['name'])
102 local_link = link
103 continue
104 else:
105 link = OBJECT_URL.format(entry['name'], md5hash)
106 if fname.endswith('none-any.whl'):
107 if generic_link:
108 LOGGER.error(
109 'Found more than one generic matching wheel for %r: %r',
110 prefix, dep)
111 continue
112 generic_link = link
113 elif plat_tag in fname:
114 if binary_link:
115 LOGGER.error(
116 'Found more than one binary matching wheel for %r: %r',
117 prefix, dep)
118 continue
119 binary_link = link
120
121 if not binary_link and not generic_link and not local_link:
122 raise NoWheelException(name, version, dep['build'], source_sha)
123
124 links.append(local_link or binary_link or generic_link)
125
126 return links
127
128
129 @contextlib.contextmanager
130 def html_index(links):
131 tf = tempfile.mktemp('.html')
132 try:
133 with open(tf, 'w') as f:
134 print >> f, '<html><body>'
135 for link in links:
136 print >> f, '<a href="%s">wat</a>' % link
137 print >> f, '</body></html>'
138 yield tf
139 finally:
140 os.unlink(tf)
141
142
143 def install(deps):
144 bin_dir = 'Scripts' if sys.platform.startswith('win') else 'bin' 78 bin_dir = 'Scripts' if sys.platform.startswith('win') else 'bin'
145 pip = os.path.join(sys.prefix, bin_dir, 'pip') 79 pip = os.path.join(sys.prefix, bin_dir, 'pip')
146 80
147 links = get_links(deps) 81 requirements = []
148 with html_index(links) as ipath: 82 # TODO(iannucci): Do this as a requirements.txt
149 requirements = [] 83 for name, deps_entry in deps.iteritems():
150 # TODO(iannucci): Do this as a requirements.txt 84 if not deps_entry.get('implicit'):
151 for name, deps_entry in deps.iteritems(): 85 requirements.append('%s==%s' % (name, deps_entry['version']))
152 if not deps_entry.get('implicit'): 86
153 requirements.append('%s==%s' % (name, deps_entry['version'])) 87 if not cache_root:
154 subprocess.check_call( 88 cache_root = os.path.join(ROOT, '.bootstrap_cache')
155 [pip, 'install', '--no-index', '--download-cache', 89 wheel_cache_dir = os.path.join(cache_root, 'wheels')
156 os.path.join(ROOT, '.wheelcache'), '-f', ipath] + requirements) 90 download_cache_dir = os.path.join(cache_root, 'download_cache')
91
92 for path in (wheel_cache_dir, download_cache_dir):
93 if not os.path.exists(path):
94 os.makedirs(path)
95
96 env = os.environ.copy()
97 env['PIP_CACHE_DIR'] = download_cache_dir
98
99 # Download the package into our cache directory.
100 subprocess.check_call([
101 pip, 'download',
102 '--find-links', 'file://' + wheel_cache_dir,
103 '--dest', wheel_cache_dir,
104 ] + requirements,
105 env=env)
106
107 # Install the downloaded packages.
108 subprocess.check_call([
109 pip, 'install',
110 '--find-links', 'file://' + wheel_cache_dir,
111 '--no-index',
112 ] + requirements,
113 env=env)
157 114
158 115
159 def activate_env(env, deps, quiet=False): 116 def activate_env(env, deps, quiet=False, cache_root=None):
160 if hasattr(sys, 'real_prefix'): 117 if hasattr(sys, 'real_prefix'):
161 LOGGER.error('Already activated environment!') 118 LOGGER.error('Already activated environment!')
162 return 119 return
163 120
164 if not quiet: 121 if not quiet:
165 print 'Activating environment: %r' % env 122 print 'Activating environment: %r' % env
166 assert isinstance(deps, dict) 123 assert isinstance(deps, dict)
167 124
168 manifest_path = os.path.join(env, 'manifest.pyl') 125 manifest_path = os.path.join(env, 'manifest.pyl')
169 cur_deps = read_deps(manifest_path) 126 cur_deps = read_deps(manifest_path)
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 # Ensure hermeticity during activation. 170 # Ensure hermeticity during activation.
214 os.environ.pop('PYTHONPATH', None) 171 os.environ.pop('PYTHONPATH', None)
215 bin_dir = 'Scripts' if sys.platform.startswith('win') else 'bin' 172 bin_dir = 'Scripts' if sys.platform.startswith('win') else 'bin'
216 activate_this = os.path.join(env, bin_dir, 'activate_this.py') 173 activate_this = os.path.join(env, bin_dir, 'activate_this.py')
217 execfile(activate_this, dict(__file__=activate_this)) 174 execfile(activate_this, dict(__file__=activate_this))
218 175
219 if cur_deps is None: 176 if cur_deps is None:
220 if not quiet: 177 if not quiet:
221 print ' Installing deps' 178 print ' Installing deps'
222 print_deps(deps, indent=2, with_implicit=False) 179 print_deps(deps, indent=2, with_implicit=False)
223 install(deps) 180 install(deps, cache_root)
224 virtualenv.make_environment_relocatable(env) 181 virtualenv.make_environment_relocatable(env)
225 with open(manifest_path, 'wb') as f: 182 with open(manifest_path, 'wb') as f:
226 f.write(repr(deps) + '\n') 183 f.write(repr(deps) + '\n')
227 184
228 # Create bin\python.bat on Windows to unify path where Python is found. 185 # Create bin\python.bat on Windows to unify path where Python is found.
229 if sys.platform.startswith('win'): 186 if sys.platform.startswith('win'):
230 bin_path = os.path.join(env, 'bin') 187 bin_path = os.path.join(env, 'bin')
231 if not os.path.isdir(bin_path): 188 if not os.path.isdir(bin_path):
232 os.makedirs(bin_path) 189 os.makedirs(bin_path)
233 python_bat_path = os.path.join(bin_path, 'python.bat') 190 python_bat_path = os.path.join(bin_path, 'python.bat')
234 if not os.path.isfile(python_bat_path): 191 if not os.path.isfile(python_bat_path):
235 with open(python_bat_path, 'w') as python_bat_file: 192 with open(python_bat_path, 'w') as python_bat_file:
236 python_bat_file.write(PYTHON_BAT_WIN) 193 python_bat_file.write(PYTHON_BAT_WIN)
237 194
238 if not quiet: 195 if not quiet:
239 print 'Done creating environment' 196 print 'Done creating environment'
240 197
241 198
242 def main(args): 199 def main(args):
243 parser = argparse.ArgumentParser() 200 parser = argparse.ArgumentParser()
244 parser.add_argument('--deps-file', '--deps_file', action='append', 201 parser.add_argument('--deps-file', '--deps_file', action='append',
245 help='Path to deps.pyl file (may be used multiple times)') 202 help='Path to deps.pyl file (may be used multiple times)')
203 parser.add_argument('--cache-root',
204 help='Store download/wheel caches in this directory.')
246 parser.add_argument('-q', '--quiet', action='store_true', default=False, 205 parser.add_argument('-q', '--quiet', action='store_true', default=False,
247 help='Supress all output') 206 help='Supress all output')
248 parser.add_argument('env_path', 207 parser.add_argument('env_path',
249 help='Path to place environment (default: %(default)s)', 208 help='Path to place environment (default: %(default)s)',
250 default='ENV') 209 default='ENV')
251 opts = parser.parse_args(args) 210 opts = parser.parse_args(args)
252 211
253 deps = merge_deps(opts.deps_file) 212 deps = merge_deps(opts.deps_file)
254 activate_env(opts.env_path, deps, opts.quiet) 213 activate_env(opts.env_path, deps, opts.quiet, cache_root=opts.cache_root)
255 214
256 215
257 if __name__ == '__main__': 216 if __name__ == '__main__':
258 logging.basicConfig() 217 logging.basicConfig()
259 LOGGER.setLevel(logging.DEBUG) 218 LOGGER.setLevel(logging.DEBUG)
260 sys.exit(main(sys.argv[1:])) 219 sys.exit(main(sys.argv[1:]))
OLDNEW
« no previous file with comments | « .gitignore ('k') | bootstrap/update_vendoring.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698