Statistics
| Branch: | Tag: | Revision:

root / snf-quotaholder-app / distribute_setup.py @ 2e1e6844

History | View | Annotate | Download (15.4 kB)

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

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

7 e6f3e652 Kostas Papadimitriou
    from distribute_setup import use_setuptools
8 e6f3e652 Kostas Papadimitriou
    use_setuptools()
9 e6f3e652 Kostas Papadimitriou

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

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

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