Statistics
| Branch: | Tag: | Revision:

root / snf-pithos-app / distribute_setup.py @ 09572034

History | View | Annotate | Download (15.4 kB)

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

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

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

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

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

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