Statistics
| Branch: | Tag: | Revision:

root / distribute_setup.py @ 6149f03e

History | View | Annotate | Download (15.4 kB)

1 68caea79 Vangelis Koukis
#!python
2 68caea79 Vangelis Koukis
"""Bootstrap distribute installation
3 68caea79 Vangelis Koukis

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

7 68caea79 Vangelis Koukis
    from distribute_setup import use_setuptools
8 68caea79 Vangelis Koukis
    use_setuptools()
9 68caea79 Vangelis Koukis

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

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

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