Statistics
| Branch: | Tag: | Revision:

root / astakosclient / distribute_setup.py @ 26498848

History | View | Annotate | Download (15.4 kB)

1 99165736 Christos Stavrakakis
#!python
2 99165736 Christos Stavrakakis
"""Bootstrap distribute installation
3 99165736 Christos Stavrakakis

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

7 99165736 Christos Stavrakakis
    from distribute_setup import use_setuptools
8 99165736 Christos Stavrakakis
    use_setuptools()
9 99165736 Christos Stavrakakis

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

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

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