1#!python 2"""Bootstrap setuptools installation 3 4If you want to use setuptools in your package's setup.py, just include this 5file in the same directory with it, and add this to the top of your setup.py:: 6 7 from ez_setup import use_setuptools 8 use_setuptools() 9 10If you want to require a specific version of setuptools, set a download 11mirror, or use an alternate download directory, you can do so by supplying 12the appropriate options to ``use_setuptools()``. 13 14This file can also be run as a script to install or upgrade setuptools. 15""" 16import sys 17DEFAULT_VERSION = "0.6c5" 18DEFAULT_URL = "http://cheeseshop.python.org/packages/%s/s/setuptools/" % sys.version[:3] 19 20md5_data = { 21 'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca', 22 'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb', 23 'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b', 24 'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a', 25 'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618', 26 'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac', 27 'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5', 28 'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4', 29 'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c', 30 'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b', 31 'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27', 32 'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277', 33 'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa', 34 'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e', 35 'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e', 36 'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f', 37 'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2', 38 'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc', 39 'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167', 40 'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64', 41 'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d', 42} 43 44import sys, os 45 46def _validate_md5(egg_name, data): 47 if egg_name in md5_data: 48 from md5 import md5 49 digest = md5(data).hexdigest() 50 if digest != md5_data[egg_name]: 51 print >>sys.stderr, ( 52 "md5 validation of %s failed! (Possible download problem?)" 53 % egg_name 54 ) 55 sys.exit(2) 56 return data 57 58 59def use_setuptools( 60 version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, 61 download_delay=15 62): 63 """Automatically find/download setuptools and make it available on sys.path 64 65 `version` should be a valid setuptools version number that is available 66 as an egg for download under the `download_base` URL (which should end with 67 a '/'). `to_dir` is the directory where setuptools will be downloaded, if 68 it is not already available. If `download_delay` is specified, it should 69 be the number of seconds that will be paused before initiating a download, 70 should one be required. If an older version of setuptools is installed, 71 this routine will print a message to ``sys.stderr`` and raise SystemExit in 72 an attempt to abort the calling script. 73 """ 74 try: 75 import setuptools 76 if setuptools.__version__ == '0.0.1': 77 print >>sys.stderr, ( 78 "You have an obsolete version of setuptools installed. Please\n" 79 "remove it from your system entirely before rerunning this script." 80 ) 81 sys.exit(2) 82 except ImportError: 83 egg = download_setuptools(version, download_base, to_dir, download_delay) 84 sys.path.insert(0, egg) 85 import setuptools; setuptools.bootstrap_install_from = egg 86 87 import pkg_resources 88 try: 89 pkg_resources.require("setuptools>="+version) 90 91 except pkg_resources.VersionConflict, e: 92 # XXX could we install in a subprocess here? 93 print >>sys.stderr, ( 94 "The required version of setuptools (>=%s) is not available, and\n" 95 "can't be installed while this script is running. Please install\n" 96 " a more recent version first.\n\n(Currently using %r)" 97 ) % (version, e.args[0]) 98 sys.exit(2) 99 100def download_setuptools( 101 version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, 102 delay = 15 103): 104 """Download setuptools from a specified location and return its filename 105 106 `version` should be a valid setuptools version number that is available 107 as an egg for download under the `download_base` URL (which should end 108 with a '/'). `to_dir` is the directory where the egg will be downloaded. 109 `delay` is the number of seconds to pause before an actual download attempt. 110 """ 111 import urllib2, shutil 112 egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3]) 113 url = download_base + egg_name 114 saveto = os.path.join(to_dir, egg_name) 115 src = dst = None 116 if not os.path.exists(saveto): # Avoid repeated downloads 117 try: 118 from distutils import log 119 if delay: 120 log.warn(""" 121--------------------------------------------------------------------------- 122This script requires setuptools version %s to run (even to display 123help). I will attempt to download it for you (from 124%s), but 125you may need to enable firewall access for this script first. 126I will start the download in %d seconds. 127 128(Note: if this machine does not have network access, please obtain the file 129 130 %s 131 132and place it in this directory before rerunning this script.) 133---------------------------------------------------------------------------""", 134 version, download_base, delay, url 135 ); from time import sleep; sleep(delay) 136 log.warn("Downloading %s", url) 137 src = urllib2.urlopen(url) 138 # Read/write all in one block, so we don't create a corrupt file 139 # if the download is interrupted. 140 data = _validate_md5(egg_name, src.read()) 141 dst = open(saveto,"wb"); dst.write(data) 142 finally: 143 if src: src.close() 144 if dst: dst.close() 145 return os.path.realpath(saveto) 146 147def main(argv, version=DEFAULT_VERSION): 148 """Install or upgrade setuptools and EasyInstall""" 149 150 try: 151 import setuptools 152 except ImportError: 153 egg = None 154 try: 155 egg = download_setuptools(version, delay=0) 156 sys.path.insert(0,egg) 157 from setuptools.command.easy_install import main 158 return main(list(argv)+[egg]) # we're done here 159 finally: 160 if egg and os.path.exists(egg): 161 os.unlink(egg) 162 else: 163 if setuptools.__version__ == '0.0.1': 164 # tell the user to uninstall obsolete version 165 use_setuptools(version) 166 167 req = "setuptools>="+version 168 import pkg_resources 169 try: 170 pkg_resources.require(req) 171 except pkg_resources.VersionConflict: 172 try: 173 from setuptools.command.easy_install import main 174 except ImportError: 175 from easy_install import main 176 main(list(argv)+[download_setuptools(delay=0)]) 177 sys.exit(0) # try to force an exit 178 else: 179 if argv: 180 from setuptools.command.easy_install import main 181 main(argv) 182 else: 183 print "Setuptools version",version,"or greater has been installed." 184 print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)' 185 186 187 188def update_md5(filenames): 189 """Update our built-in md5 registry""" 190 191 import re 192 from md5 import md5 193 194 for name in filenames: 195 base = os.path.basename(name) 196 f = open(name,'rb') 197 md5_data[base] = md5(f.read()).hexdigest() 198 f.close() 199 200 data = [" %r: %r,\n" % it for it in md5_data.items()] 201 data.sort() 202 repl = "".join(data) 203 204 import inspect 205 srcfile = inspect.getsourcefile(sys.modules[__name__]) 206 f = open(srcfile, 'rb'); src = f.read(); f.close() 207 208 match = re.search("\nmd5_data = {\n([^}]+)}", src) 209 if not match: 210 print >>sys.stderr, "Internal error!" 211 sys.exit(2) 212 213 src = src[:match.start(1)] + repl + src[match.end(1):] 214 f = open(srcfile,'w') 215 f.write(src) 216 f.close() 217 218 219if __name__=='__main__': 220 if len(sys.argv)>2 and sys.argv[1]=='--md5update': 221 update_md5(sys.argv[2:]) 222 else: 223 main(sys.argv[1:]) 224 225 226 227 228 229