Test suite runs and passes!
[zzz-floof.git] / ez_setup.py
1 #!python
2 """Bootstrap setuptools installation
3
4 If you want to use setuptools in your package's setup.py, just include this
5 file 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
10 If you want to require a specific version of setuptools, set a download
11 mirror, or use an alternate download directory, you can do so by supplying
12 the appropriate options to ``use_setuptools()``.
13
14 This file can also be run as a script to install or upgrade setuptools.
15 """
16 import sys
17 DEFAULT_VERSION = "0.6c9"
18 DEFAULT_URL = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3]
19
20 md5_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 'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20',
43 'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab',
44 'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53',
45 'setuptools-0.6c7-py2.3.egg': '209fdf9adc3a615e5115b725658e13e2',
46 'setuptools-0.6c7-py2.4.egg': '5a8f954807d46a0fb67cf1f26c55a82e',
47 'setuptools-0.6c7-py2.5.egg': '45d2ad28f9750e7434111fde831e8372',
48 'setuptools-0.6c8-py2.3.egg': '50759d29b349db8cfd807ba8303f1902',
49 'setuptools-0.6c8-py2.4.egg': 'cba38d74f7d483c06e9daa6070cce6de',
50 'setuptools-0.6c8-py2.5.egg': '1721747ee329dc150590a58b3e1ac95b',
51 'setuptools-0.6c9-py2.3.egg': 'a83c4020414807b496e4cfbe08507c03',
52 'setuptools-0.6c9-py2.4.egg': '260a2be2e5388d66bdaee06abec6342a',
53 'setuptools-0.6c9-py2.5.egg': 'fe67c3e5a17b12c0e7c541b7ea43a8e6',
54 'setuptools-0.6c9-py2.6.egg': 'ca37b1ff16fa2ede6e19383e7b59245a',
55 }
56
57 import sys, os
58 try: from hashlib import md5
59 except ImportError: from md5 import md5
60
61 def _validate_md5(egg_name, data):
62 if egg_name in md5_data:
63 digest = md5(data).hexdigest()
64 if digest != md5_data[egg_name]:
65 print >>sys.stderr, (
66 "md5 validation of %s failed! (Possible download problem?)"
67 % egg_name
68 )
69 sys.exit(2)
70 return data
71
72 def use_setuptools(
73 version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
74 download_delay=15
75 ):
76 """Automatically find/download setuptools and make it available on sys.path
77
78 `version` should be a valid setuptools version number that is available
79 as an egg for download under the `download_base` URL (which should end with
80 a '/'). `to_dir` is the directory where setuptools will be downloaded, if
81 it is not already available. If `download_delay` is specified, it should
82 be the number of seconds that will be paused before initiating a download,
83 should one be required. If an older version of setuptools is installed,
84 this routine will print a message to ``sys.stderr`` and raise SystemExit in
85 an attempt to abort the calling script.
86 """
87 was_imported = 'pkg_resources' in sys.modules or 'setuptools' in sys.modules
88 def do_download():
89 egg = download_setuptools(version, download_base, to_dir, download_delay)
90 sys.path.insert(0, egg)
91 import setuptools; setuptools.bootstrap_install_from = egg
92 try:
93 import pkg_resources
94 except ImportError:
95 return do_download()
96 try:
97 pkg_resources.require("setuptools>="+version); return
98 except pkg_resources.VersionConflict, e:
99 if was_imported:
100 print >>sys.stderr, (
101 "The required version of setuptools (>=%s) is not available, and\n"
102 "can't be installed while this script is running. Please install\n"
103 " a more recent version first, using 'easy_install -U setuptools'."
104 "\n\n(Currently using %r)"
105 ) % (version, e.args[0])
106 sys.exit(2)
107 else:
108 del pkg_resources, sys.modules['pkg_resources'] # reload ok
109 return do_download()
110 except pkg_resources.DistributionNotFound:
111 return do_download()
112
113 def download_setuptools(
114 version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
115 delay = 15
116 ):
117 """Download setuptools from a specified location and return its filename
118
119 `version` should be a valid setuptools version number that is available
120 as an egg for download under the `download_base` URL (which should end
121 with a '/'). `to_dir` is the directory where the egg will be downloaded.
122 `delay` is the number of seconds to pause before an actual download attempt.
123 """
124 import urllib2, shutil
125 egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3])
126 url = download_base + egg_name
127 saveto = os.path.join(to_dir, egg_name)
128 src = dst = None
129 if not os.path.exists(saveto): # Avoid repeated downloads
130 try:
131 from distutils import log
132 if delay:
133 log.warn("""
134 ---------------------------------------------------------------------------
135 This script requires setuptools version %s to run (even to display
136 help). I will attempt to download it for you (from
137 %s), but
138 you may need to enable firewall access for this script first.
139 I will start the download in %d seconds.
140
141 (Note: if this machine does not have network access, please obtain the file
142
143 %s
144
145 and place it in this directory before rerunning this script.)
146 ---------------------------------------------------------------------------""",
147 version, download_base, delay, url
148 ); from time import sleep; sleep(delay)
149 log.warn("Downloading %s", url)
150 src = urllib2.urlopen(url)
151 # Read/write all in one block, so we don't create a corrupt file
152 # if the download is interrupted.
153 data = _validate_md5(egg_name, src.read())
154 dst = open(saveto,"wb"); dst.write(data)
155 finally:
156 if src: src.close()
157 if dst: dst.close()
158 return os.path.realpath(saveto)
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
192
193
194
195 def main(argv, version=DEFAULT_VERSION):
196 """Install or upgrade setuptools and EasyInstall"""
197 try:
198 import setuptools
199 except ImportError:
200 egg = None
201 try:
202 egg = download_setuptools(version, delay=0)
203 sys.path.insert(0,egg)
204 from setuptools.command.easy_install import main
205 return main(list(argv)+[egg]) # we're done here
206 finally:
207 if egg and os.path.exists(egg):
208 os.unlink(egg)
209 else:
210 if setuptools.__version__ == '0.0.1':
211 print >>sys.stderr, (
212 "You have an obsolete version of setuptools installed. Please\n"
213 "remove it from your system entirely before rerunning this script."
214 )
215 sys.exit(2)
216
217 req = "setuptools>="+version
218 import pkg_resources
219 try:
220 pkg_resources.require(req)
221 except pkg_resources.VersionConflict:
222 try:
223 from setuptools.command.easy_install import main
224 except ImportError:
225 from easy_install import main
226 main(list(argv)+[download_setuptools(delay=0)])
227 sys.exit(0) # try to force an exit
228 else:
229 if argv:
230 from setuptools.command.easy_install import main
231 main(argv)
232 else:
233 print "Setuptools version",version,"or greater has been installed."
234 print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)'
235
236 def update_md5(filenames):
237 """Update our built-in md5 registry"""
238
239 import re
240
241 for name in filenames:
242 base = os.path.basename(name)
243 f = open(name,'rb')
244 md5_data[base] = md5(f.read()).hexdigest()
245 f.close()
246
247 data = [" %r: %r,\n" % it for it in md5_data.items()]
248 data.sort()
249 repl = "".join(data)
250
251 import inspect
252 srcfile = inspect.getsourcefile(sys.modules[__name__])
253 f = open(srcfile, 'rb'); src = f.read(); f.close()
254
255 match = re.search("\nmd5_data = {\n([^}]+)}", src)
256 if not match:
257 print >>sys.stderr, "Internal error!"
258 sys.exit(2)
259
260 src = src[:match.start(1)] + repl + src[match.end(1):]
261 f = open(srcfile,'w')
262 f.write(src)
263 f.close()
264
265
266 if __name__=='__main__':
267 if len(sys.argv)>2 and sys.argv[1]=='--md5update':
268 update_md5(sys.argv[2:])
269 else:
270 main(sys.argv[1:])
271
272
273
274
275
276