Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / distribute_setup.py @ 6bd1416f

History | View | Annotate | Download (15.4 kB)

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

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

7 14a1245e Kostas Papadimitriou
    from distribute_setup import use_setuptools
8 14a1245e Kostas Papadimitriou
    use_setuptools()
9 14a1245e Kostas Papadimitriou

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

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

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