diff options
Diffstat (limited to 'ez_setup.py')
-rwxr-xr-x | ez_setup.py | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/ez_setup.py b/ez_setup.py new file mode 100755 index 0000000..89cf056 --- /dev/null +++ b/ez_setup.py | |||
@@ -0,0 +1,272 @@ | |||
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.6c8" | ||
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 | } | ||
52 | |||
53 | import sys, os | ||
54 | |||
55 | def _validate_md5(egg_name, data): | ||
56 | if egg_name in md5_data: | ||
57 | from md5 import md5 | ||
58 | digest = md5(data).hexdigest() | ||
59 | if digest != md5_data[egg_name]: | ||
60 | print >>sys.stderr, ( | ||
61 | "md5 validation of %s failed! (Possible download problem?)" | ||
62 | % egg_name | ||
63 | ) | ||
64 | sys.exit(2) | ||
65 | return data | ||
66 | |||
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 | else: | ||
104 | del pkg_resources, sys.modules['pkg_resources'] # reload ok | ||
105 | return do_download() | ||
106 | except pkg_resources.DistributionNotFound: | ||
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 | from md5 import md5 | ||
237 | |||
238 | for name in filenames: | ||
239 | base = os.path.basename(name) | ||
240 | f = open(name,'rb') | ||
241 | md5_data[base] = md5(f.read()).hexdigest() | ||
242 | f.close() | ||
243 | |||
244 | data = [" %r: %r,\n" % it for it in md5_data.items()] | ||
245 | data.sort() | ||
246 | repl = "".join(data) | ||
247 | |||
248 | import inspect | ||
249 | srcfile = inspect.getsourcefile(sys.modules[__name__]) | ||
250 | f = open(srcfile, 'rb'); src = f.read(); f.close() | ||
251 | |||
252 | match = re.search("\nmd5_data = {\n([^}]+)}", src) | ||
253 | if not match: | ||
254 | print >>sys.stderr, "Internal error!" | ||
255 | sys.exit(2) | ||
256 | |||
257 | src = src[:match.start(1)] + repl + src[match.end(1):] | ||
258 | f = open(srcfile,'w') | ||
259 | f.write(src) | ||
260 | f.close() | ||
261 | |||
262 | |||
263 | if __name__=='__main__': | ||
264 | if len(sys.argv)>2 and sys.argv[1]=='--md5update': | ||
265 | update_md5(sys.argv[2:]) | ||
266 | else: | ||
267 | main(sys.argv[1:]) | ||
268 | |||
269 | |||
270 | |||
271 | |||
272 | |||