Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / distribute_setup.py @ c7493368

History | View | Annotate | Download (15.5 kB)

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

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

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

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

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

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