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.6c9"
18DEFAULT_URL     = "http://pypi.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    '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
57import sys, os
58try: from hashlib import md5
59except ImportError: from md5 import md5
60
61def _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
72def 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
113def 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---------------------------------------------------------------------------
135This script requires setuptools version %s to run (even to display
136help).  I will attempt to download it for you (from
137%s), but
138you may need to enable firewall access for this script first.
139I 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
145and 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
195def 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
236def 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
266if __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
277