Statistics
| Branch: | Tag: | Revision:

root / snf-pithos-webclient / distribute_setup.py @ 02f1204b

History | View | Annotate | Download (15.4 kB)

1 f9fee161 Antony Chazapis
#!python
2 f9fee161 Antony Chazapis
"""Bootstrap distribute installation
3 f9fee161 Antony Chazapis

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

7 f9fee161 Antony Chazapis
    from distribute_setup import use_setuptools
8 f9fee161 Antony Chazapis
    use_setuptools()
9 f9fee161 Antony Chazapis

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

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

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