Statistics
| Branch: | Tag: | Revision:

root / astakosclient / distribute_setup.py @ 1ecb12b5

History | View | Annotate | Download (15.4 kB)

1 99165736 Christos Stavrakakis
#!python
2 99165736 Christos Stavrakakis
"""Bootstrap distribute installation
3 99165736 Christos Stavrakakis

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

7 99165736 Christos Stavrakakis
    from distribute_setup import use_setuptools
8 99165736 Christos Stavrakakis
    use_setuptools()
9 99165736 Christos Stavrakakis

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

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

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