Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / distribute_setup.py @ 8ed29e14

History | View | Annotate | Download (15.4 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 a11acc65 Kostas Papadimitriou
            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 a11acc65 Kostas Papadimitriou
                "The required version of distribute (>=%s) is not available,\n"
154 a11acc65 Kostas Papadimitriou
                "and can't be installed while this script is running. Please\n"
155 a11acc65 Kostas Papadimitriou
                "install a more recent version first, using\n"
156 a11acc65 Kostas Papadimitriou
                "'easy_install -U distribute'."
157 a11acc65 Kostas Papadimitriou
                "\n\n(Currently using %r)\n" % (version, e.args[0]))
158 a11acc65 Kostas Papadimitriou
                sys.exit(2)
159 a11acc65 Kostas Papadimitriou
            else:
160 a11acc65 Kostas Papadimitriou
                del pkg_resources, sys.modules['pkg_resources']    # reload ok
161 a11acc65 Kostas Papadimitriou
                return _do_download(version, download_base, to_dir,
162 a11acc65 Kostas Papadimitriou
                                    download_delay)
163 a11acc65 Kostas Papadimitriou
        except pkg_resources.DistributionNotFound:
164 a11acc65 Kostas Papadimitriou
            return _do_download(version, download_base, to_dir,
165 a11acc65 Kostas Papadimitriou
                                download_delay)
166 a11acc65 Kostas Papadimitriou
    finally:
167 a11acc65 Kostas Papadimitriou
        if not no_fake:
168 a11acc65 Kostas Papadimitriou
            _create_fake_setuptools_pkg_info(to_dir)
169 a11acc65 Kostas Papadimitriou
170 a11acc65 Kostas Papadimitriou
def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
171 a11acc65 Kostas Papadimitriou
                        to_dir=os.curdir, delay=15):
172 a11acc65 Kostas Papadimitriou
    """Download distribute from a specified location and return its filename
173 a11acc65 Kostas Papadimitriou

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