Statistics
| Branch: | Tag: | Revision:

root / snf-webproject / distribute_setup.py @ e61aed5a

History | View | Annotate | Download (15.4 kB)

1 2ce0636e Kostas Papadimitriou
#!python
2 2ce0636e Kostas Papadimitriou
"""Bootstrap distribute installation
3 2ce0636e Kostas Papadimitriou

4 2ce0636e Kostas Papadimitriou
If you want to use setuptools in your package's setup.py, just include this
5 2ce0636e Kostas Papadimitriou
file in the same directory with it, and add this to the top of your setup.py::
6 2ce0636e Kostas Papadimitriou

7 2ce0636e Kostas Papadimitriou
    from distribute_setup import use_setuptools
8 2ce0636e Kostas Papadimitriou
    use_setuptools()
9 2ce0636e Kostas Papadimitriou

10 2ce0636e Kostas Papadimitriou
If you want to require a specific version of setuptools, set a download
11 2ce0636e Kostas Papadimitriou
mirror, or use an alternate download directory, you can do so by supplying
12 2ce0636e Kostas Papadimitriou
the appropriate options to ``use_setuptools()``.
13 2ce0636e Kostas Papadimitriou

14 2ce0636e Kostas Papadimitriou
This file can also be run as a script to install or upgrade setuptools.
15 2ce0636e Kostas Papadimitriou
"""
16 2ce0636e Kostas Papadimitriou
import os
17 2ce0636e Kostas Papadimitriou
import sys
18 2ce0636e Kostas Papadimitriou
import time
19 2ce0636e Kostas Papadimitriou
import fnmatch
20 2ce0636e Kostas Papadimitriou
import tempfile
21 2ce0636e Kostas Papadimitriou
import tarfile
22 2ce0636e Kostas Papadimitriou
from distutils import log
23 2ce0636e Kostas Papadimitriou
24 2ce0636e Kostas Papadimitriou
try:
25 2ce0636e Kostas Papadimitriou
    from site import USER_SITE
26 2ce0636e Kostas Papadimitriou
except ImportError:
27 2ce0636e Kostas Papadimitriou
    USER_SITE = None
28 2ce0636e Kostas Papadimitriou
29 2ce0636e Kostas Papadimitriou
try:
30 2ce0636e Kostas Papadimitriou
    import subprocess
31 2ce0636e Kostas Papadimitriou
32 2ce0636e Kostas Papadimitriou
    def _python_cmd(*args):
33 2ce0636e Kostas Papadimitriou
        args = (sys.executable,) + args
34 2ce0636e Kostas Papadimitriou
        return subprocess.call(args) == 0
35 2ce0636e Kostas Papadimitriou
36 2ce0636e Kostas Papadimitriou
except ImportError:
37 2ce0636e Kostas Papadimitriou
    # will be used for python 2.3
38 2ce0636e Kostas Papadimitriou
    def _python_cmd(*args):
39 2ce0636e Kostas Papadimitriou
        args = (sys.executable,) + args
40 2ce0636e Kostas Papadimitriou
        # quoting arguments if windows
41 2ce0636e Kostas Papadimitriou
        if sys.platform == 'win32':
42 2ce0636e Kostas Papadimitriou
            def quote(arg):
43 2ce0636e Kostas Papadimitriou
                if ' ' in arg:
44 2ce0636e Kostas Papadimitriou
                    return '"%s"' % arg
45 2ce0636e Kostas Papadimitriou
                return arg
46 2ce0636e Kostas Papadimitriou
            args = [quote(arg) for arg in args]
47 2ce0636e Kostas Papadimitriou
        return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
48 2ce0636e Kostas Papadimitriou
49 2ce0636e Kostas Papadimitriou
DEFAULT_VERSION = "0.6.10"
50 2ce0636e Kostas Papadimitriou
DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
51 2ce0636e Kostas Papadimitriou
SETUPTOOLS_FAKED_VERSION = "0.6c11"
52 2ce0636e Kostas Papadimitriou
53 2ce0636e Kostas Papadimitriou
SETUPTOOLS_PKG_INFO = """\
54 2ce0636e Kostas Papadimitriou
Metadata-Version: 1.0
55 2ce0636e Kostas Papadimitriou
Name: setuptools
56 2ce0636e Kostas Papadimitriou
Version: %s
57 2ce0636e Kostas Papadimitriou
Summary: xxxx
58 2ce0636e Kostas Papadimitriou
Home-page: xxx
59 2ce0636e Kostas Papadimitriou
Author: xxx
60 2ce0636e Kostas Papadimitriou
Author-email: xxx
61 2ce0636e Kostas Papadimitriou
License: xxx
62 2ce0636e Kostas Papadimitriou
Description: xxx
63 2ce0636e Kostas Papadimitriou
""" % SETUPTOOLS_FAKED_VERSION
64 2ce0636e Kostas Papadimitriou
65 2ce0636e Kostas Papadimitriou
66 2ce0636e Kostas Papadimitriou
def _install(tarball):
67 2ce0636e Kostas Papadimitriou
    # extracting the tarball
68 2ce0636e Kostas Papadimitriou
    tmpdir = tempfile.mkdtemp()
69 2ce0636e Kostas Papadimitriou
    log.warn('Extracting in %s', tmpdir)
70 2ce0636e Kostas Papadimitriou
    old_wd = os.getcwd()
71 2ce0636e Kostas Papadimitriou
    try:
72 2ce0636e Kostas Papadimitriou
        os.chdir(tmpdir)
73 2ce0636e Kostas Papadimitriou
        tar = tarfile.open(tarball)
74 2ce0636e Kostas Papadimitriou
        _extractall(tar)
75 2ce0636e Kostas Papadimitriou
        tar.close()
76 2ce0636e Kostas Papadimitriou
77 2ce0636e Kostas Papadimitriou
        # going in the directory
78 2ce0636e Kostas Papadimitriou
        subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
79 2ce0636e Kostas Papadimitriou
        os.chdir(subdir)
80 2ce0636e Kostas Papadimitriou
        log.warn('Now working in %s', subdir)
81 2ce0636e Kostas Papadimitriou
82 2ce0636e Kostas Papadimitriou
        # installing
83 2ce0636e Kostas Papadimitriou
        log.warn('Installing Distribute')
84 2ce0636e Kostas Papadimitriou
        if not _python_cmd('setup.py', 'install'):
85 2ce0636e Kostas Papadimitriou
            log.warn('Something went wrong during the installation.')
86 2ce0636e Kostas Papadimitriou
            log.warn('See the error message above.')
87 2ce0636e Kostas Papadimitriou
    finally:
88 2ce0636e Kostas Papadimitriou
        os.chdir(old_wd)
89 2ce0636e Kostas Papadimitriou
90 2ce0636e Kostas Papadimitriou
91 2ce0636e Kostas Papadimitriou
def _build_egg(egg, tarball, to_dir):
92 2ce0636e Kostas Papadimitriou
    # extracting the tarball
93 2ce0636e Kostas Papadimitriou
    tmpdir = tempfile.mkdtemp()
94 2ce0636e Kostas Papadimitriou
    log.warn('Extracting in %s', tmpdir)
95 2ce0636e Kostas Papadimitriou
    old_wd = os.getcwd()
96 2ce0636e Kostas Papadimitriou
    try:
97 2ce0636e Kostas Papadimitriou
        os.chdir(tmpdir)
98 2ce0636e Kostas Papadimitriou
        tar = tarfile.open(tarball)
99 2ce0636e Kostas Papadimitriou
        _extractall(tar)
100 2ce0636e Kostas Papadimitriou
        tar.close()
101 2ce0636e Kostas Papadimitriou
102 2ce0636e Kostas Papadimitriou
        # going in the directory
103 2ce0636e Kostas Papadimitriou
        subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
104 2ce0636e Kostas Papadimitriou
        os.chdir(subdir)
105 2ce0636e Kostas Papadimitriou
        log.warn('Now working in %s', subdir)
106 2ce0636e Kostas Papadimitriou
107 2ce0636e Kostas Papadimitriou
        # building an egg
108 2ce0636e Kostas Papadimitriou
        log.warn('Building a Distribute egg in %s', to_dir)
109 2ce0636e Kostas Papadimitriou
        _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
110 2ce0636e Kostas Papadimitriou
111 2ce0636e Kostas Papadimitriou
    finally:
112 2ce0636e Kostas Papadimitriou
        os.chdir(old_wd)
113 2ce0636e Kostas Papadimitriou
    # returning the result
114 2ce0636e Kostas Papadimitriou
    log.warn(egg)
115 2ce0636e Kostas Papadimitriou
    if not os.path.exists(egg):
116 2ce0636e Kostas Papadimitriou
        raise IOError('Could not build the egg.')
117 2ce0636e Kostas Papadimitriou
118 2ce0636e Kostas Papadimitriou
119 2ce0636e Kostas Papadimitriou
def _do_download(version, download_base, to_dir, download_delay):
120 2ce0636e Kostas Papadimitriou
    egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg'
121 2ce0636e Kostas Papadimitriou
                       % (version, sys.version_info[0], sys.version_info[1]))
122 2ce0636e Kostas Papadimitriou
    if not os.path.exists(egg):
123 2ce0636e Kostas Papadimitriou
        tarball = download_setuptools(version, download_base,
124 2ce0636e Kostas Papadimitriou
                                      to_dir, download_delay)
125 2ce0636e Kostas Papadimitriou
        _build_egg(egg, tarball, to_dir)
126 2ce0636e Kostas Papadimitriou
    sys.path.insert(0, egg)
127 2ce0636e Kostas Papadimitriou
    import setuptools
128 2ce0636e Kostas Papadimitriou
    setuptools.bootstrap_install_from = egg
129 2ce0636e Kostas Papadimitriou
130 2ce0636e Kostas Papadimitriou
131 2ce0636e Kostas Papadimitriou
def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
132 2ce0636e Kostas Papadimitriou
                   to_dir=os.curdir, download_delay=15, no_fake=True):
133 2ce0636e Kostas Papadimitriou
    # making sure we use the absolute path
134 2ce0636e Kostas Papadimitriou
    to_dir = os.path.abspath(to_dir)
135 2ce0636e Kostas Papadimitriou
    was_imported = 'pkg_resources' in sys.modules or \
136 2ce0636e Kostas Papadimitriou
        'setuptools' in sys.modules
137 2ce0636e Kostas Papadimitriou
    try:
138 2ce0636e Kostas Papadimitriou
        try:
139 2ce0636e Kostas Papadimitriou
            import pkg_resources
140 2ce0636e Kostas Papadimitriou
            if not hasattr(pkg_resources, '_distribute'):
141 2ce0636e Kostas Papadimitriou
                if not no_fake:
142 2ce0636e Kostas Papadimitriou
                    _fake_setuptools()
143 2ce0636e Kostas Papadimitriou
                raise ImportError
144 2ce0636e Kostas Papadimitriou
        except ImportError:
145 2ce0636e Kostas Papadimitriou
            return _do_download(version, download_base, to_dir, download_delay)
146 2ce0636e Kostas Papadimitriou
        try:
147 2ce0636e Kostas Papadimitriou
            pkg_resources.require("distribute>="+version)
148 2ce0636e Kostas Papadimitriou
            return
149 2ce0636e Kostas Papadimitriou
        except pkg_resources.VersionConflict:
150 2ce0636e Kostas Papadimitriou
            e = sys.exc_info()[1]
151 2ce0636e Kostas Papadimitriou
            if was_imported:
152 2ce0636e Kostas Papadimitriou
                sys.stderr.write(
153 2ce0636e Kostas Papadimitriou
                "The required version of distribute (>=%s) is not available,\n"
154 2ce0636e Kostas Papadimitriou
                "and can't be installed while this script is running. Please\n"
155 2ce0636e Kostas Papadimitriou
                "install a more recent version first, using\n"
156 2ce0636e Kostas Papadimitriou
                "'easy_install -U distribute'."
157 2ce0636e Kostas Papadimitriou
                "\n\n(Currently using %r)\n" % (version, e.args[0]))
158 2ce0636e Kostas Papadimitriou
                sys.exit(2)
159 2ce0636e Kostas Papadimitriou
            else:
160 2ce0636e Kostas Papadimitriou
                del pkg_resources, sys.modules['pkg_resources']    # reload ok
161 2ce0636e Kostas Papadimitriou
                return _do_download(version, download_base, to_dir,
162 2ce0636e Kostas Papadimitriou
                                    download_delay)
163 2ce0636e Kostas Papadimitriou
        except pkg_resources.DistributionNotFound:
164 2ce0636e Kostas Papadimitriou
            return _do_download(version, download_base, to_dir,
165 2ce0636e Kostas Papadimitriou
                                download_delay)
166 2ce0636e Kostas Papadimitriou
    finally:
167 2ce0636e Kostas Papadimitriou
        if not no_fake:
168 2ce0636e Kostas Papadimitriou
            _create_fake_setuptools_pkg_info(to_dir)
169 2ce0636e Kostas Papadimitriou
170 2ce0636e Kostas Papadimitriou
def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
171 2ce0636e Kostas Papadimitriou
                        to_dir=os.curdir, delay=15):
172 2ce0636e Kostas Papadimitriou
    """Download distribute from a specified location and return its filename
173 2ce0636e Kostas Papadimitriou

174 2ce0636e Kostas Papadimitriou
    `version` should be a valid distribute version number that is available
175 2ce0636e Kostas Papadimitriou
    as an egg for download under the `download_base` URL (which should end
176 2ce0636e Kostas Papadimitriou
    with a '/'). `to_dir` is the directory where the egg will be downloaded.
177 2ce0636e Kostas Papadimitriou
    `delay` is the number of seconds to pause before an actual download
178 2ce0636e Kostas Papadimitriou
    attempt.
179 2ce0636e Kostas Papadimitriou
    """
180 2ce0636e Kostas Papadimitriou
    # making sure we use the absolute path
181 2ce0636e Kostas Papadimitriou
    to_dir = os.path.abspath(to_dir)
182 2ce0636e Kostas Papadimitriou
    try:
183 2ce0636e Kostas Papadimitriou
        from urllib.request import urlopen
184 2ce0636e Kostas Papadimitriou
    except ImportError:
185 2ce0636e Kostas Papadimitriou
        from urllib2 import urlopen
186 2ce0636e Kostas Papadimitriou
    tgz_name = "distribute-%s.tar.gz" % version
187 2ce0636e Kostas Papadimitriou
    url = download_base + tgz_name
188 2ce0636e Kostas Papadimitriou
    saveto = os.path.join(to_dir, tgz_name)
189 2ce0636e Kostas Papadimitriou
    src = dst = None
190 2ce0636e Kostas Papadimitriou
    if not os.path.exists(saveto):  # Avoid repeated downloads
191 2ce0636e Kostas Papadimitriou
        try:
192 2ce0636e Kostas Papadimitriou
            log.warn("Downloading %s", url)
193 2ce0636e Kostas Papadimitriou
            src = urlopen(url)
194 2ce0636e Kostas Papadimitriou
            # Read/write all in one block, so we don't create a corrupt file
195 2ce0636e Kostas Papadimitriou
            # if the download is interrupted.
196 2ce0636e Kostas Papadimitriou
            data = src.read()
197 2ce0636e Kostas Papadimitriou
            dst = open(saveto, "wb")
198 2ce0636e Kostas Papadimitriou
            dst.write(data)
199 2ce0636e Kostas Papadimitriou
        finally:
200 2ce0636e Kostas Papadimitriou
            if src:
201 2ce0636e Kostas Papadimitriou
                src.close()
202 2ce0636e Kostas Papadimitriou
            if dst:
203 2ce0636e Kostas Papadimitriou
                dst.close()
204 2ce0636e Kostas Papadimitriou
    return os.path.realpath(saveto)
205 2ce0636e Kostas Papadimitriou
206 2ce0636e Kostas Papadimitriou
def _no_sandbox(function):
207 2ce0636e Kostas Papadimitriou
    def __no_sandbox(*args, **kw):
208 2ce0636e Kostas Papadimitriou
        try:
209 2ce0636e Kostas Papadimitriou
            from setuptools.sandbox import DirectorySandbox
210 2ce0636e Kostas Papadimitriou
            if not hasattr(DirectorySandbox, '_old'):
211 2ce0636e Kostas Papadimitriou
                def violation(*args):
212 2ce0636e Kostas Papadimitriou
                    pass
213 2ce0636e Kostas Papadimitriou
                DirectorySandbox._old = DirectorySandbox._violation
214 2ce0636e Kostas Papadimitriou
                DirectorySandbox._violation = violation
215 2ce0636e Kostas Papadimitriou
                patched = True
216 2ce0636e Kostas Papadimitriou
            else:
217 2ce0636e Kostas Papadimitriou
                patched = False
218 2ce0636e Kostas Papadimitriou
        except ImportError:
219 2ce0636e Kostas Papadimitriou
            patched = False
220 2ce0636e Kostas Papadimitriou
221 2ce0636e Kostas Papadimitriou
        try:
222 2ce0636e Kostas Papadimitriou
            return function(*args, **kw)
223 2ce0636e Kostas Papadimitriou
        finally:
224 2ce0636e Kostas Papadimitriou
            if patched:
225 2ce0636e Kostas Papadimitriou
                DirectorySandbox._violation = DirectorySandbox._old
226 2ce0636e Kostas Papadimitriou
                del DirectorySandbox._old
227 2ce0636e Kostas Papadimitriou
228 2ce0636e Kostas Papadimitriou
    return __no_sandbox
229 2ce0636e Kostas Papadimitriou
230 2ce0636e Kostas Papadimitriou
def _patch_file(path, content):
231 2ce0636e Kostas Papadimitriou
    """Will backup the file then patch it"""
232 2ce0636e Kostas Papadimitriou
    existing_content = open(path).read()
233 2ce0636e Kostas Papadimitriou
    if existing_content == content:
234 2ce0636e Kostas Papadimitriou
        # already patched
235 2ce0636e Kostas Papadimitriou
        log.warn('Already patched.')
236 2ce0636e Kostas Papadimitriou
        return False
237 2ce0636e Kostas Papadimitriou
    log.warn('Patching...')
238 2ce0636e Kostas Papadimitriou
    _rename_path(path)
239 2ce0636e Kostas Papadimitriou
    f = open(path, 'w')
240 2ce0636e Kostas Papadimitriou
    try:
241 2ce0636e Kostas Papadimitriou
        f.write(content)
242 2ce0636e Kostas Papadimitriou
    finally:
243 2ce0636e Kostas Papadimitriou
        f.close()
244 2ce0636e Kostas Papadimitriou
    return True
245 2ce0636e Kostas Papadimitriou
246 2ce0636e Kostas Papadimitriou
_patch_file = _no_sandbox(_patch_file)
247 2ce0636e Kostas Papadimitriou
248 2ce0636e Kostas Papadimitriou
def _same_content(path, content):
249 2ce0636e Kostas Papadimitriou
    return open(path).read() == content
250 2ce0636e Kostas Papadimitriou
251 2ce0636e Kostas Papadimitriou
def _rename_path(path):
252 2ce0636e Kostas Papadimitriou
    new_name = path + '.OLD.%s' % time.time()
253 2ce0636e Kostas Papadimitriou
    log.warn('Renaming %s into %s', path, new_name)
254 2ce0636e Kostas Papadimitriou
    os.rename(path, new_name)
255 2ce0636e Kostas Papadimitriou
    return new_name
256 2ce0636e Kostas Papadimitriou
257 2ce0636e Kostas Papadimitriou
def _remove_flat_installation(placeholder):
258 2ce0636e Kostas Papadimitriou
    if not os.path.isdir(placeholder):
259 2ce0636e Kostas Papadimitriou
        log.warn('Unkown installation at %s', placeholder)
260 2ce0636e Kostas Papadimitriou
        return False
261 2ce0636e Kostas Papadimitriou
    found = False
262 2ce0636e Kostas Papadimitriou
    for file in os.listdir(placeholder):
263 2ce0636e Kostas Papadimitriou
        if fnmatch.fnmatch(file, 'setuptools*.egg-info'):
264 2ce0636e Kostas Papadimitriou
            found = True
265 2ce0636e Kostas Papadimitriou
            break
266 2ce0636e Kostas Papadimitriou
    if not found:
267 2ce0636e Kostas Papadimitriou
        log.warn('Could not locate setuptools*.egg-info')
268 2ce0636e Kostas Papadimitriou
        return
269 2ce0636e Kostas Papadimitriou
270 2ce0636e Kostas Papadimitriou
    log.warn('Removing elements out of the way...')
271 2ce0636e Kostas Papadimitriou
    pkg_info = os.path.join(placeholder, file)
272 2ce0636e Kostas Papadimitriou
    if os.path.isdir(pkg_info):
273 2ce0636e Kostas Papadimitriou
        patched = _patch_egg_dir(pkg_info)
274 2ce0636e Kostas Papadimitriou
    else:
275 2ce0636e Kostas Papadimitriou
        patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO)
276 2ce0636e Kostas Papadimitriou
277 2ce0636e Kostas Papadimitriou
    if not patched:
278 2ce0636e Kostas Papadimitriou
        log.warn('%s already patched.', pkg_info)
279 2ce0636e Kostas Papadimitriou
        return False
280 2ce0636e Kostas Papadimitriou
    # now let's move the files out of the way
281 2ce0636e Kostas Papadimitriou
    for element in ('setuptools', 'pkg_resources.py', 'site.py'):
282 2ce0636e Kostas Papadimitriou
        element = os.path.join(placeholder, element)
283 2ce0636e Kostas Papadimitriou
        if os.path.exists(element):
284 2ce0636e Kostas Papadimitriou
            _rename_path(element)
285 2ce0636e Kostas Papadimitriou
        else:
286 2ce0636e Kostas Papadimitriou
            log.warn('Could not find the %s element of the '
287 2ce0636e Kostas Papadimitriou
                     'Setuptools distribution', element)
288 2ce0636e Kostas Papadimitriou
    return True
289 2ce0636e Kostas Papadimitriou
290 2ce0636e Kostas Papadimitriou
_remove_flat_installation = _no_sandbox(_remove_flat_installation)
291 2ce0636e Kostas Papadimitriou
292 2ce0636e Kostas Papadimitriou
def _after_install(dist):
293 2ce0636e Kostas Papadimitriou
    log.warn('After install bootstrap.')
294 2ce0636e Kostas Papadimitriou
    placeholder = dist.get_command_obj('install').install_purelib
295 2ce0636e Kostas Papadimitriou
    _create_fake_setuptools_pkg_info(placeholder)
296 2ce0636e Kostas Papadimitriou
297 2ce0636e Kostas Papadimitriou
def _create_fake_setuptools_pkg_info(placeholder):
298 2ce0636e Kostas Papadimitriou
    if not placeholder or not os.path.exists(placeholder):
299 2ce0636e Kostas Papadimitriou
        log.warn('Could not find the install location')
300 2ce0636e Kostas Papadimitriou
        return
301 2ce0636e Kostas Papadimitriou
    pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1])
302 2ce0636e Kostas Papadimitriou
    setuptools_file = 'setuptools-%s-py%s.egg-info' % \
303 2ce0636e Kostas Papadimitriou
            (SETUPTOOLS_FAKED_VERSION, pyver)
304 2ce0636e Kostas Papadimitriou
    pkg_info = os.path.join(placeholder, setuptools_file)
305 2ce0636e Kostas Papadimitriou
    if os.path.exists(pkg_info):
306 2ce0636e Kostas Papadimitriou
        log.warn('%s already exists', pkg_info)
307 2ce0636e Kostas Papadimitriou
        return
308 2ce0636e Kostas Papadimitriou
309 2ce0636e Kostas Papadimitriou
    log.warn('Creating %s', pkg_info)
310 2ce0636e Kostas Papadimitriou
    f = open(pkg_info, 'w')
311 2ce0636e Kostas Papadimitriou
    try:
312 2ce0636e Kostas Papadimitriou
        f.write(SETUPTOOLS_PKG_INFO)
313 2ce0636e Kostas Papadimitriou
    finally:
314 2ce0636e Kostas Papadimitriou
        f.close()
315 2ce0636e Kostas Papadimitriou
316 2ce0636e Kostas Papadimitriou
    pth_file = os.path.join(placeholder, 'setuptools.pth')
317 2ce0636e Kostas Papadimitriou
    log.warn('Creating %s', pth_file)
318 2ce0636e Kostas Papadimitriou
    f = open(pth_file, 'w')
319 2ce0636e Kostas Papadimitriou
    try:
320 2ce0636e Kostas Papadimitriou
        f.write(os.path.join(os.curdir, setuptools_file))
321 2ce0636e Kostas Papadimitriou
    finally:
322 2ce0636e Kostas Papadimitriou
        f.close()
323 2ce0636e Kostas Papadimitriou
324 2ce0636e Kostas Papadimitriou
_create_fake_setuptools_pkg_info = _no_sandbox(_create_fake_setuptools_pkg_info)
325 2ce0636e Kostas Papadimitriou
326 2ce0636e Kostas Papadimitriou
def _patch_egg_dir(path):
327 2ce0636e Kostas Papadimitriou
    # let's check if it's already patched
328 2ce0636e Kostas Papadimitriou
    pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
329 2ce0636e Kostas Papadimitriou
    if os.path.exists(pkg_info):
330 2ce0636e Kostas Papadimitriou
        if _same_content(pkg_info, SETUPTOOLS_PKG_INFO):
331 2ce0636e Kostas Papadimitriou
            log.warn('%s already patched.', pkg_info)
332 2ce0636e Kostas Papadimitriou
            return False
333 2ce0636e Kostas Papadimitriou
    _rename_path(path)
334 2ce0636e Kostas Papadimitriou
    os.mkdir(path)
335 2ce0636e Kostas Papadimitriou
    os.mkdir(os.path.join(path, 'EGG-INFO'))
336 2ce0636e Kostas Papadimitriou
    pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
337 2ce0636e Kostas Papadimitriou
    f = open(pkg_info, 'w')
338 2ce0636e Kostas Papadimitriou
    try:
339 2ce0636e Kostas Papadimitriou
        f.write(SETUPTOOLS_PKG_INFO)
340 2ce0636e Kostas Papadimitriou
    finally:
341 2ce0636e Kostas Papadimitriou
        f.close()
342 2ce0636e Kostas Papadimitriou
    return True
343 2ce0636e Kostas Papadimitriou
344 2ce0636e Kostas Papadimitriou
_patch_egg_dir = _no_sandbox(_patch_egg_dir)
345 2ce0636e Kostas Papadimitriou
346 2ce0636e Kostas Papadimitriou
def _before_install():
347 2ce0636e Kostas Papadimitriou
    log.warn('Before install bootstrap.')
348 2ce0636e Kostas Papadimitriou
    _fake_setuptools()
349 2ce0636e Kostas Papadimitriou
350 2ce0636e Kostas Papadimitriou
351 2ce0636e Kostas Papadimitriou
def _under_prefix(location):
352 2ce0636e Kostas Papadimitriou
    if 'install' not in sys.argv:
353 2ce0636e Kostas Papadimitriou
        return True
354 2ce0636e Kostas Papadimitriou
    args = sys.argv[sys.argv.index('install')+1:]
355 2ce0636e Kostas Papadimitriou
    for index, arg in enumerate(args):
356 2ce0636e Kostas Papadimitriou
        for option in ('--root', '--prefix'):
357 2ce0636e Kostas Papadimitriou
            if arg.startswith('%s=' % option):
358 2ce0636e Kostas Papadimitriou
                top_dir = arg.split('root=')[-1]
359 2ce0636e Kostas Papadimitriou
                return location.startswith(top_dir)
360 2ce0636e Kostas Papadimitriou
            elif arg == option:
361 2ce0636e Kostas Papadimitriou
                if len(args) > index:
362 2ce0636e Kostas Papadimitriou
                    top_dir = args[index+1]
363 2ce0636e Kostas Papadimitriou
                    return location.startswith(top_dir)
364 2ce0636e Kostas Papadimitriou
        if arg == '--user' and USER_SITE is not None:
365 2ce0636e Kostas Papadimitriou
            return location.startswith(USER_SITE)
366 2ce0636e Kostas Papadimitriou
    return True
367 2ce0636e Kostas Papadimitriou
368 2ce0636e Kostas Papadimitriou
369 2ce0636e Kostas Papadimitriou
def _fake_setuptools():
370 2ce0636e Kostas Papadimitriou
    log.warn('Scanning installed packages')
371 2ce0636e Kostas Papadimitriou
    try:
372 2ce0636e Kostas Papadimitriou
        import pkg_resources
373 2ce0636e Kostas Papadimitriou
    except ImportError:
374 2ce0636e Kostas Papadimitriou
        # we're cool
375 2ce0636e Kostas Papadimitriou
        log.warn('Setuptools or Distribute does not seem to be installed.')
376 2ce0636e Kostas Papadimitriou
        return
377 2ce0636e Kostas Papadimitriou
    ws = pkg_resources.working_set
378 2ce0636e Kostas Papadimitriou
    try:
379 2ce0636e Kostas Papadimitriou
        setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools',
380 2ce0636e Kostas Papadimitriou
                                  replacement=False))
381 2ce0636e Kostas Papadimitriou
    except TypeError:
382 2ce0636e Kostas Papadimitriou
        # old distribute API
383 2ce0636e Kostas Papadimitriou
        setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools'))
384 2ce0636e Kostas Papadimitriou
385 2ce0636e Kostas Papadimitriou
    if setuptools_dist is None:
386 2ce0636e Kostas Papadimitriou
        log.warn('No setuptools distribution found')
387 2ce0636e Kostas Papadimitriou
        return
388 2ce0636e Kostas Papadimitriou
    # detecting if it was already faked
389 2ce0636e Kostas Papadimitriou
    setuptools_location = setuptools_dist.location
390 2ce0636e Kostas Papadimitriou
    log.warn('Setuptools installation detected at %s', setuptools_location)
391 2ce0636e Kostas Papadimitriou
392 2ce0636e Kostas Papadimitriou
    # if --root or --preix was provided, and if
393 2ce0636e Kostas Papadimitriou
    # setuptools is not located in them, we don't patch it
394 2ce0636e Kostas Papadimitriou
    if not _under_prefix(setuptools_location):
395 2ce0636e Kostas Papadimitriou
        log.warn('Not patching, --root or --prefix is installing Distribute'
396 2ce0636e Kostas Papadimitriou
                 ' in another location')
397 2ce0636e Kostas Papadimitriou
        return
398 2ce0636e Kostas Papadimitriou
399 2ce0636e Kostas Papadimitriou
    # let's see if its an egg
400 2ce0636e Kostas Papadimitriou
    if not setuptools_location.endswith('.egg'):
401 2ce0636e Kostas Papadimitriou
        log.warn('Non-egg installation')
402 2ce0636e Kostas Papadimitriou
        res = _remove_flat_installation(setuptools_location)
403 2ce0636e Kostas Papadimitriou
        if not res:
404 2ce0636e Kostas Papadimitriou
            return
405 2ce0636e Kostas Papadimitriou
    else:
406 2ce0636e Kostas Papadimitriou
        log.warn('Egg installation')
407 2ce0636e Kostas Papadimitriou
        pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO')
408 2ce0636e Kostas Papadimitriou
        if (os.path.exists(pkg_info) and
409 2ce0636e Kostas Papadimitriou
            _same_content(pkg_info, SETUPTOOLS_PKG_INFO)):
410 2ce0636e Kostas Papadimitriou
            log.warn('Already patched.')
411 2ce0636e Kostas Papadimitriou
            return
412 2ce0636e Kostas Papadimitriou
        log.warn('Patching...')
413 2ce0636e Kostas Papadimitriou
        # let's create a fake egg replacing setuptools one
414 2ce0636e Kostas Papadimitriou
        res = _patch_egg_dir(setuptools_location)
415 2ce0636e Kostas Papadimitriou
        if not res:
416 2ce0636e Kostas Papadimitriou
            return
417 2ce0636e Kostas Papadimitriou
    log.warn('Patched done.')
418 2ce0636e Kostas Papadimitriou
    _relaunch()
419 2ce0636e Kostas Papadimitriou
420 2ce0636e Kostas Papadimitriou
421 2ce0636e Kostas Papadimitriou
def _relaunch():
422 2ce0636e Kostas Papadimitriou
    log.warn('Relaunching...')
423 2ce0636e Kostas Papadimitriou
    # we have to relaunch the process
424 2ce0636e Kostas Papadimitriou
    # pip marker to avoid a relaunch bug
425 2ce0636e Kostas Papadimitriou
    if sys.argv[:3] == ['-c', 'install', '--single-version-externally-managed']:
426 2ce0636e Kostas Papadimitriou
        sys.argv[0] = 'setup.py'
427 2ce0636e Kostas Papadimitriou
    args = [sys.executable] + sys.argv
428 2ce0636e Kostas Papadimitriou
    sys.exit(subprocess.call(args))
429 2ce0636e Kostas Papadimitriou
430 2ce0636e Kostas Papadimitriou
431 2ce0636e Kostas Papadimitriou
def _extractall(self, path=".", members=None):
432 2ce0636e Kostas Papadimitriou
    """Extract all members from the archive to the current working
433 2ce0636e Kostas Papadimitriou
       directory and set owner, modification time and permissions on
434 2ce0636e Kostas Papadimitriou
       directories afterwards. `path' specifies a different directory
435 2ce0636e Kostas Papadimitriou
       to extract to. `members' is optional and must be a subset of the
436 2ce0636e Kostas Papadimitriou
       list returned by getmembers().
437 2ce0636e Kostas Papadimitriou
    """
438 2ce0636e Kostas Papadimitriou
    import copy
439 2ce0636e Kostas Papadimitriou
    import operator
440 2ce0636e Kostas Papadimitriou
    from tarfile import ExtractError
441 2ce0636e Kostas Papadimitriou
    directories = []
442 2ce0636e Kostas Papadimitriou
443 2ce0636e Kostas Papadimitriou
    if members is None:
444 2ce0636e Kostas Papadimitriou
        members = self
445 2ce0636e Kostas Papadimitriou
446 2ce0636e Kostas Papadimitriou
    for tarinfo in members:
447 2ce0636e Kostas Papadimitriou
        if tarinfo.isdir():
448 2ce0636e Kostas Papadimitriou
            # Extract directories with a safe mode.
449 2ce0636e Kostas Papadimitriou
            directories.append(tarinfo)
450 2ce0636e Kostas Papadimitriou
            tarinfo = copy.copy(tarinfo)
451 2ce0636e Kostas Papadimitriou
            tarinfo.mode = 448 # decimal for oct 0700
452 2ce0636e Kostas Papadimitriou
        self.extract(tarinfo, path)
453 2ce0636e Kostas Papadimitriou
454 2ce0636e Kostas Papadimitriou
    # Reverse sort directories.
455 2ce0636e Kostas Papadimitriou
    if sys.version_info < (2, 4):
456 2ce0636e Kostas Papadimitriou
        def sorter(dir1, dir2):
457 2ce0636e Kostas Papadimitriou
            return cmp(dir1.name, dir2.name)
458 2ce0636e Kostas Papadimitriou
        directories.sort(sorter)
459 2ce0636e Kostas Papadimitriou
        directories.reverse()
460 2ce0636e Kostas Papadimitriou
    else:
461 2ce0636e Kostas Papadimitriou
        directories.sort(key=operator.attrgetter('name'), reverse=True)
462 2ce0636e Kostas Papadimitriou
463 2ce0636e Kostas Papadimitriou
    # Set correct owner, mtime and filemode on directories.
464 2ce0636e Kostas Papadimitriou
    for tarinfo in directories:
465 2ce0636e Kostas Papadimitriou
        dirpath = os.path.join(path, tarinfo.name)
466 2ce0636e Kostas Papadimitriou
        try:
467 2ce0636e Kostas Papadimitriou
            self.chown(tarinfo, dirpath)
468 2ce0636e Kostas Papadimitriou
            self.utime(tarinfo, dirpath)
469 2ce0636e Kostas Papadimitriou
            self.chmod(tarinfo, dirpath)
470 2ce0636e Kostas Papadimitriou
        except ExtractError:
471 2ce0636e Kostas Papadimitriou
            e = sys.exc_info()[1]
472 2ce0636e Kostas Papadimitriou
            if self.errorlevel > 1:
473 2ce0636e Kostas Papadimitriou
                raise
474 2ce0636e Kostas Papadimitriou
            else:
475 2ce0636e Kostas Papadimitriou
                self._dbg(1, "tarfile: %s" % e)
476 2ce0636e Kostas Papadimitriou
477 2ce0636e Kostas Papadimitriou
478 2ce0636e Kostas Papadimitriou
def main(argv, version=DEFAULT_VERSION):
479 2ce0636e Kostas Papadimitriou
    """Install or upgrade setuptools and EasyInstall"""
480 2ce0636e Kostas Papadimitriou
    tarball = download_setuptools()
481 2ce0636e Kostas Papadimitriou
    _install(tarball)
482 2ce0636e Kostas Papadimitriou
483 2ce0636e Kostas Papadimitriou
484 2ce0636e Kostas Papadimitriou
if __name__ == '__main__':
485 2ce0636e Kostas Papadimitriou
    main(sys.argv[1:])