Statistics
| Branch: | Tag: | Revision:

root / snf-deploy / distribute_setup.py @ 4b36944e

History | View | Annotate | Download (15.4 kB)

1 0ac84a9a Dimitris Aragiorgis
#!python
2 0ac84a9a Dimitris Aragiorgis
"""Bootstrap distribute installation
3 0ac84a9a Dimitris Aragiorgis

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

7 0ac84a9a Dimitris Aragiorgis
    from distribute_setup import use_setuptools
8 0ac84a9a Dimitris Aragiorgis
    use_setuptools()
9 0ac84a9a Dimitris Aragiorgis

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

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

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