Statistics
| Branch: | Tag: | Revision:

root / snf-deploy / distribute_setup.py @ 26f6ab93

History | View | Annotate | Download (15.4 kB)

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

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

7 ad76b118 Dimitris Aragiorgis
    from distribute_setup import use_setuptools
8 ad76b118 Dimitris Aragiorgis
    use_setuptools()
9 ad76b118 Dimitris Aragiorgis

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

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

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