1 #!/usr/bin/env python 2 # 3 # Copyright 2015 Google Inc. 4 # 5 # Licensed under the Apache License, Version 2.0 (the "License"); 6 # you may not use this file except in compliance with the License. 7 # You may obtain a copy of the License at 8 # 9 # http://www.apache.org/licenses/LICENSE-2.0 10 # 11 # Unless required by applicable law or agreed to in writing, software 12 # distributed under the License is distributed on an "AS IS" BASIS, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 17 """Bootstrap setuptools installation 18 19 If you want to use setuptools in your package's setup.py, just include this 20 file in the same directory with it, and add this to the top of your setup.py:: 21 22 from ez_setup import use_setuptools 23 use_setuptools() 24 25 If you want to require a specific version of setuptools, set a download 26 mirror, or use an alternate download directory, you can do so by supplying 27 the appropriate options to ``use_setuptools()``. 28 29 This file can also be run as a script to install or upgrade setuptools. 30 """ 31 import sys 32 DEFAULT_VERSION = "0.6c11" 33 DEFAULT_URL = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3] 34 35 md5_data = { 36 'setuptools-0.6c10-py2.3.egg': 'ce1e2ab5d3a0256456d9fc13800a7090', 37 'setuptools-0.6c10-py2.4.egg': '57d6d9d6e9b80772c59a53a8433a5dd4', 38 'setuptools-0.6c10-py2.5.egg': 'de46ac8b1c97c895572e5e8596aeb8c7', 39 'setuptools-0.6c10-py2.6.egg': '58ea40aef06da02ce641495523a0b7f5', 40 'setuptools-0.6c11-py2.3.egg': '2baeac6e13d414a9d28e7ba5b5a596de', 41 'setuptools-0.6c11-py2.4.egg': 'bd639f9b0eac4c42497034dec2ec0c2b', 42 'setuptools-0.6c11-py2.5.egg': '64c94f3bf7a72a13ec83e0b24f2749b2', 43 'setuptools-0.6c11-py2.6.egg': 'bfa92100bd772d5a213eedd356d64086', 44 'setuptools-0.6c8-py2.3.egg': '50759d29b349db8cfd807ba8303f1902', 45 'setuptools-0.6c8-py2.4.egg': 'cba38d74f7d483c06e9daa6070cce6de', 46 'setuptools-0.6c8-py2.5.egg': '1721747ee329dc150590a58b3e1ac95b', 47 'setuptools-0.6c9-py2.3.egg': 'a83c4020414807b496e4cfbe08507c03', 48 'setuptools-0.6c9-py2.4.egg': '260a2be2e5388d66bdaee06abec6342a', 49 'setuptools-0.6c9-py2.5.egg': 'fe67c3e5a17b12c0e7c541b7ea43a8e6', 50 'setuptools-0.6c9-py2.6.egg': 'ca37b1ff16fa2ede6e19383e7b59245a', 51 } 52 53 import sys, os 54 try: from hashlib import md5 55 except ImportError: from md5 import md5 56 57 def _validate_md5(egg_name, data): 58 if egg_name in md5_data: 59 digest = md5(data).hexdigest() 60 if digest != md5_data[egg_name]: 61 print >>sys.stderr, ( 62 "md5 validation of %s failed! (Possible download problem?)" 63 % egg_name 64 ) 65 sys.exit(2) 66 return data 67 68 def use_setuptools( 69 version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, 70 download_delay=15 71 ): 72 """Automatically find/download setuptools and make it available on sys.path 73 74 `version` should be a valid setuptools version number that is available 75 as an egg for download under the `download_base` URL (which should end with 76 a '/'). `to_dir` is the directory where setuptools will be downloaded, if 77 it is not already available. If `download_delay` is specified, it should 78 be the number of seconds that will be paused before initiating a download, 79 should one be required. If an older version of setuptools is installed, 80 this routine will print a message to ``sys.stderr`` and raise SystemExit in 81 an attempt to abort the calling script. 82 """ 83 was_imported = 'pkg_resources' in sys.modules or 'setuptools' in sys.modules 84 def do_download(): 85 egg = download_setuptools(version, download_base, to_dir, download_delay) 86 sys.path.insert(0, egg) 87 import setuptools; setuptools.bootstrap_install_from = egg 88 try: 89 import pkg_resources 90 except ImportError: 91 return do_download() 92 try: 93 pkg_resources.require("setuptools>="+version); return 94 except pkg_resources.VersionConflict, e: 95 if was_imported: 96 print >>sys.stderr, ( 97 "The required version of setuptools (>=%s) is not available, and\n" 98 "can't be installed while this script is running. Please install\n" 99 " a more recent version first, using 'easy_install -U setuptools'." 100 "\n\n(Currently using %r)" 101 ) % (version, e.args[0]) 102 sys.exit(2) 103 except pkg_resources.DistributionNotFound: 104 pass 105 106 del pkg_resources, sys.modules['pkg_resources'] # reload ok 107 return do_download() 108 109 def download_setuptools( 110 version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, 111 delay = 15 112 ): 113 """Download setuptools from a specified location and return its filename 114 115 `version` should be a valid setuptools version number that is available 116 as an egg for download under the `download_base` URL (which should end 117 with a '/'). `to_dir` is the directory where the egg will be downloaded. 118 `delay` is the number of seconds to pause before an actual download attempt. 119 """ 120 import urllib2, shutil 121 egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3]) 122 url = download_base + egg_name 123 saveto = os.path.join(to_dir, egg_name) 124 src = dst = None 125 if not os.path.exists(saveto): # Avoid repeated downloads 126 try: 127 from distutils import log 128 if delay: 129 log.warn(""" 130 --------------------------------------------------------------------------- 131 This script requires setuptools version %s to run (even to display 132 help). I will attempt to download it for you (from 133 %s), but 134 you may need to enable firewall access for this script first. 135 I will start the download in %d seconds. 136 137 (Note: if this machine does not have network access, please obtain the file 138 139 %s 140 141 and place it in this directory before rerunning this script.) 142 ---------------------------------------------------------------------------""", 143 version, download_base, delay, url 144 ); from time import sleep; sleep(delay) 145 log.warn("Downloading %s", url) 146 src = urllib2.urlopen(url) 147 # Read/write all in one block, so we don't create a corrupt file 148 # if the download is interrupted. 149 data = _validate_md5(egg_name, src.read()) 150 dst = open(saveto,"wb"); dst.write(data) 151 finally: 152 if src: src.close() 153 if dst: dst.close() 154 return os.path.realpath(saveto) 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 def main(argv, version=DEFAULT_VERSION): 192 """Install or upgrade setuptools and EasyInstall""" 193 try: 194 import setuptools 195 except ImportError: 196 egg = None 197 try: 198 egg = download_setuptools(version, delay=0) 199 sys.path.insert(0,egg) 200 from setuptools.command.easy_install import main 201 return main(list(argv)+[egg]) # we're done here 202 finally: 203 if egg and os.path.exists(egg): 204 os.unlink(egg) 205 else: 206 if setuptools.__version__ == '0.0.1': 207 print >>sys.stderr, ( 208 "You have an obsolete version of setuptools installed. Please\n" 209 "remove it from your system entirely before rerunning this script." 210 ) 211 sys.exit(2) 212 213 req = "setuptools>="+version 214 import pkg_resources 215 try: 216 pkg_resources.require(req) 217 except pkg_resources.VersionConflict: 218 try: 219 from setuptools.command.easy_install import main 220 except ImportError: 221 from easy_install import main 222 main(list(argv)+[download_setuptools(delay=0)]) 223 sys.exit(0) # try to force an exit 224 else: 225 if argv: 226 from setuptools.command.easy_install import main 227 main(argv) 228 else: 229 print "Setuptools version",version,"or greater has been installed." 230 print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)' 231 232 def update_md5(filenames): 233 """Update our built-in md5 registry""" 234 235 import re 236 237 for name in filenames: 238 base = os.path.basename(name) 239 f = open(name,'rb') 240 md5_data[base] = md5(f.read()).hexdigest() 241 f.close() 242 243 data = [" %r: %r,\n" % it for it in md5_data.items()] 244 data.sort() 245 repl = "".join(data) 246 247 import inspect 248 srcfile = inspect.getsourcefile(sys.modules[__name__]) 249 f = open(srcfile, 'rb'); src = f.read(); f.close() 250 251 match = re.search("\nmd5_data = {\n([^}]+)}", src) 252 if not match: 253 print >>sys.stderr, "Internal error!" 254 sys.exit(2) 255 256 src = src[:match.start(1)] + repl + src[match.end(1):] 257 f = open(srcfile,'w') 258 f.write(src) 259 f.close() 260 261 262 if __name__=='__main__': 263 if len(sys.argv)>2 and sys.argv[1]=='--md5update': 264 update_md5(sys.argv[2:]) 265 else: 266 main(sys.argv[1:]) 267