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