TracUtil: ez_setup.py

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