Statistics
| Branch: | Tag: | Revision:

root / snf-stats-app / distribute_setup.py @ 2439c9d6

History | View | Annotate | Download (15.4 kB)

1 7fcec5d7 Stratos Psomadakis
#!python
2 7fcec5d7 Stratos Psomadakis
"""Bootstrap distribute installation
3 7fcec5d7 Stratos Psomadakis

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

7 7fcec5d7 Stratos Psomadakis
    from distribute_setup import use_setuptools
8 7fcec5d7 Stratos Psomadakis
    use_setuptools()
9 7fcec5d7 Stratos Psomadakis

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

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

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