~launchpad-pqm/launchpad/devel

8234.1.2 by Gary Poster
checkpoint: this initial buildout variant has several parts working, including run, start, stop, and harness.
1
##############################################################################
2
#
11411.1.1 by Gary Poster
use the newest zc.buildout, zc.recipe.egg, z3c.recipe.scripts, and bootstrap.
3
# Copyright (c) 2006 Zope Foundation and Contributors.
8234.1.2 by Gary Poster
checkpoint: this initial buildout variant has several parts working, including run, start, stop, and harness.
4
# All Rights Reserved.
5
#
6
# This software is subject to the provisions of the Zope Public License,
7
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
8
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11
# FOR A PARTICULAR PURPOSE.
12
#
13
##############################################################################
14
"""Bootstrap a buildout-based project
15
16
Simply run this script in a directory containing a buildout.cfg.
17
The script accepts buildout command-line options, so you can
18
use the -c option to specify an alternate configuration file.
19
"""
20
11411.1.1 by Gary Poster
use the newest zc.buildout, zc.recipe.egg, z3c.recipe.scripts, and bootstrap.
21
import os, shutil, sys, tempfile, textwrap, urllib, urllib2, subprocess
10303.1.10 by Gary Poster
update to newer version of buildout branch
22
from optparse import OptionParser
23
24
if sys.platform == 'win32':
25
    def quote(c):
26
        if ' ' in c:
27
            return '"%s"' % c # work around spawn lamosity on windows
8827.2.1 by Gary Poster
use experimental eggs for buildout and friends
28
        else:
10303.1.10 by Gary Poster
update to newer version of buildout branch
29
            return c
30
else:
31
    quote = str
32
11411.1.1 by Gary Poster
use the newest zc.buildout, zc.recipe.egg, z3c.recipe.scripts, and bootstrap.
33
# See zc.buildout.easy_install._has_broken_dash_S for motivation and comments.
34
stdout, stderr = subprocess.Popen(
35
    [sys.executable, '-Sc',
36
     'try:\n'
37
     '    import ConfigParser\n'
38
     'except ImportError:\n'
39
     '    print 1\n'
40
     'else:\n'
41
     '    print 0\n'],
42
    stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
43
has_broken_dash_S = bool(int(stdout.strip()))
44
10303.1.10 by Gary Poster
update to newer version of buildout branch
45
# In order to be more robust in the face of system Pythons, we want to
46
# run without site-packages loaded.  This is somewhat tricky, in
47
# particular because Python 2.6's distutils imports site, so starting
48
# with the -S flag is not sufficient.  However, we'll start with that:
11411.1.1 by Gary Poster
use the newest zc.buildout, zc.recipe.egg, z3c.recipe.scripts, and bootstrap.
49
if not has_broken_dash_S and 'site' in sys.modules:
10303.1.10 by Gary Poster
update to newer version of buildout branch
50
    # We will restart with python -S.
51
    args = sys.argv[:]
52
    args[0:0] = [sys.executable, '-S']
53
    args = map(quote, args)
54
    os.execv(sys.executable, args)
55
# Now we are running with -S.  We'll get the clean sys.path, import site
56
# because distutils will do it later, and then reset the path and clean
57
# out any namespace packages from site-packages that might have been
58
# loaded by .pth files.
59
clean_path = sys.path[:]
60
import site
61
sys.path[:] = clean_path
62
for k, v in sys.modules.items():
63
    if (hasattr(v, '__path__') and
64
        len(v.__path__)==1 and
65
        not os.path.exists(os.path.join(v.__path__[0],'__init__.py'))):
66
        # This is a namespace package.  Remove it.
67
        sys.modules.pop(k)
68
69
is_jython = sys.platform.startswith('java')
70
71
setuptools_source = 'http://peak.telecommunity.com/dist/ez_setup.py'
72
distribute_source = 'http://python-distribute.org/distribute_setup.py'
73
74
# parsing arguments
75
def normalize_to_url(option, opt_str, value, parser):
76
    if value:
77
        if '://' not in value: # It doesn't smell like a URL.
78
            value = 'file://%s' % (
79
                urllib.pathname2url(
80
                    os.path.abspath(os.path.expanduser(value))),)
81
        if opt_str == '--download-base' and not value.endswith('/'):
82
            # Download base needs a trailing slash to make the world happy.
83
            value += '/'
84
    else:
85
        value = None
86
    name = opt_str[2:].replace('-', '_')
87
    setattr(parser.values, name, value)
88
89
usage = '''\
90
[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
91
92
Bootstraps a buildout-based project.
93
94
Simply run this script in a directory containing a buildout.cfg, using the
95
Python that you want bin/buildout to use.
96
97
Note that by using --setup-source and --download-base to point to
98
local resources, you can keep this script from going over the network.
99
'''
100
101
parser = OptionParser(usage=usage)
102
parser.add_option("-v", "--version", dest="version",
103
                          help="use a specific zc.buildout version")
104
parser.add_option("-d", "--distribute",
105
                   action="store_true", dest="use_distribute", default=False,
106
                   help="Use Distribute rather than Setuptools.")
107
parser.add_option("--setup-source", action="callback", dest="setup_source",
108
                  callback=normalize_to_url, nargs=1, type="string",
109
                  help=("Specify a URL or file location for the setup file. "
110
                        "If you use Setuptools, this will default to " +
111
                        setuptools_source + "; if you use Distribute, this "
112
                        "will default to " + distribute_source +"."))
113
parser.add_option("--download-base", action="callback", dest="download_base",
114
                  callback=normalize_to_url, nargs=1, type="string",
115
                  help=("Specify a URL or directory for downloading "
116
                        "zc.buildout and either Setuptools or Distribute. "
117
                        "Defaults to PyPI."))
118
parser.add_option("--eggs",
119
                  help=("Specify a directory for storing eggs.  Defaults to "
120
                        "a temporary directory that is deleted when the "
121
                        "bootstrap script completes."))
11411.1.1 by Gary Poster
use the newest zc.buildout, zc.recipe.egg, z3c.recipe.scripts, and bootstrap.
122
parser.add_option("-t", "--accept-buildout-test-releases",
123
                  dest='accept_buildout_test_releases',
124
                  action="store_true", default=False,
125
                  help=("Normally, if you do not specify a --version, the "
126
                        "bootstrap script and buildout gets the newest "
127
                        "*final* versions of zc.buildout and its recipes and "
128
                        "extensions for you.  If you use this flag, "
129
                        "bootstrap and buildout will get the newest releases "
130
                        "even if they are alphas or betas."))
10303.1.10 by Gary Poster
update to newer version of buildout branch
131
parser.add_option("-c", None, action="store", dest="config_file",
132
                   help=("Specify the path to the buildout configuration "
133
                         "file to be used."))
134
135
options, args = parser.parse_args()
136
11411.1.1 by Gary Poster
use the newest zc.buildout, zc.recipe.egg, z3c.recipe.scripts, and bootstrap.
137
# if -c was provided, we push it back into args for buildout's main function
10303.1.10 by Gary Poster
update to newer version of buildout branch
138
if options.config_file is not None:
139
    args += ['-c', options.config_file]
140
141
if options.eggs:
142
    eggs_dir = os.path.abspath(os.path.expanduser(options.eggs))
143
else:
144
    eggs_dir = tempfile.mkdtemp()
145
146
if options.setup_source is None:
147
    if options.use_distribute:
148
        options.setup_source = distribute_source
149
    else:
150
        options.setup_source = setuptools_source
151
11411.1.1 by Gary Poster
use the newest zc.buildout, zc.recipe.egg, z3c.recipe.scripts, and bootstrap.
152
if options.accept_buildout_test_releases:
153
    args.append('buildout:accept-buildout-test-releases=true')
154
args.append('bootstrap')
8234.1.2 by Gary Poster
checkpoint: this initial buildout variant has several parts working, including run, start, stop, and harness.
155
156
try:
10303.1.10 by Gary Poster
update to newer version of buildout branch
157
    import pkg_resources
11411.1.1 by Gary Poster
use the newest zc.buildout, zc.recipe.egg, z3c.recipe.scripts, and bootstrap.
158
    import setuptools # A flag.  Sometimes pkg_resources is installed alone.
10303.1.10 by Gary Poster
update to newer version of buildout branch
159
    if not hasattr(pkg_resources, '_distribute'):
160
        raise ImportError
8234.1.2 by Gary Poster
checkpoint: this initial buildout variant has several parts working, including run, start, stop, and harness.
161
except ImportError:
10303.1.10 by Gary Poster
update to newer version of buildout branch
162
    ez_code = urllib2.urlopen(
163
        options.setup_source).read().replace('\r\n', '\n')
8234.1.2 by Gary Poster
checkpoint: this initial buildout variant has several parts working, including run, start, stop, and harness.
164
    ez = {}
10303.1.10 by Gary Poster
update to newer version of buildout branch
165
    exec ez_code in ez
166
    setup_args = dict(to_dir=eggs_dir, download_delay=0)
167
    if options.download_base:
168
        setup_args['download_base'] = options.download_base
169
    if options.use_distribute:
170
        setup_args['no_fake'] = True
171
    ez['use_setuptools'](**setup_args)
11411.1.1 by Gary Poster
use the newest zc.buildout, zc.recipe.egg, z3c.recipe.scripts, and bootstrap.
172
    reload(sys.modules['pkg_resources'])
173
    import pkg_resources
8926.1.1 by Gary Poster
handle a couple more site-packages issues; one if pkg_resources is around but setuptools is not; and the other to make developing an egg have the same sys.path as bin/buildout
174
    # This does not (always?) update the default working set.  We will
175
    # do it.
176
    for path in sys.path:
177
        if path not in pkg_resources.working_set.entries:
178
            pkg_resources.working_set.add_entry(path)
8234.1.2 by Gary Poster
checkpoint: this initial buildout variant has several parts working, including run, start, stop, and harness.
179
8827.2.1 by Gary Poster
use experimental eggs for buildout and friends
180
cmd = [quote(sys.executable),
181
       '-c',
182
       quote('from setuptools.command.easy_install import main; main()'),
183
       '-mqNxd',
10303.1.10 by Gary Poster
update to newer version of buildout branch
184
       quote(eggs_dir)]
185
11411.1.1 by Gary Poster
use the newest zc.buildout, zc.recipe.egg, z3c.recipe.scripts, and bootstrap.
186
if not has_broken_dash_S:
187
    cmd.insert(1, '-S')
10303.1.10 by Gary Poster
update to newer version of buildout branch
188
11411.1.1 by Gary Poster
use the newest zc.buildout, zc.recipe.egg, z3c.recipe.scripts, and bootstrap.
189
find_links = options.download_base
190
if not find_links:
191
    find_links = os.environ.get('bootstrap-testing-find-links')
192
if find_links:
193
    cmd.extend(['-f', quote(find_links)])
8827.2.1 by Gary Poster
use experimental eggs for buildout and friends
194
10303.1.10 by Gary Poster
update to newer version of buildout branch
195
if options.use_distribute:
196
    setup_requirement = 'distribute'
197
else:
198
    setup_requirement = 'setuptools'
8827.2.1 by Gary Poster
use experimental eggs for buildout and friends
199
ws = pkg_resources.working_set
11411.1.1 by Gary Poster
use the newest zc.buildout, zc.recipe.egg, z3c.recipe.scripts, and bootstrap.
200
setup_requirement_path = ws.find(
201
    pkg_resources.Requirement.parse(setup_requirement)).location
8827.2.1 by Gary Poster
use experimental eggs for buildout and friends
202
env = dict(
203
    os.environ,
11411.1.1 by Gary Poster
use the newest zc.buildout, zc.recipe.egg, z3c.recipe.scripts, and bootstrap.
204
    PYTHONPATH=setup_requirement_path)
205
206
requirement = 'zc.buildout'
207
version = options.version
208
if version is None and not options.accept_buildout_test_releases:
209
    # Figure out the most recent final version of zc.buildout.
210
    import setuptools.package_index
211
    _final_parts = '*final-', '*final'
212
    def _final_version(parsed_version):
213
        for part in parsed_version:
214
            if (part[:1] == '*') and (part not in _final_parts):
215
                return False
216
        return True
217
    index = setuptools.package_index.PackageIndex(
218
        search_path=[setup_requirement_path])
219
    if find_links:
220
        index.add_find_links((find_links,))
221
    req = pkg_resources.Requirement.parse(requirement)
222
    if index.obtain(req) is not None:
223
        best = []
224
        bestv = None
225
        for dist in index[req.project_name]:
226
            distv = dist.parsed_version
227
            if _final_version(distv):
228
                if bestv is None or distv > bestv:
229
                    best = [dist]
230
                    bestv = distv
231
                elif distv == bestv:
232
                    best.append(dist)
233
        if best:
234
            best.sort()
235
            version = best[-1].version
236
if version:
237
    requirement = '=='.join((requirement, version))
238
cmd.append(requirement)
8827.2.1 by Gary Poster
use experimental eggs for buildout and friends
239
8827.2.2 by Gary Poster
use temporary, local eggs for buildout work.
240
if is_jython:
8234.1.2 by Gary Poster
checkpoint: this initial buildout variant has several parts working, including run, start, stop, and harness.
241
    import subprocess
8827.2.2 by Gary Poster
use temporary, local eggs for buildout work.
242
    exitcode = subprocess.Popen(cmd, env=env).wait()
10303.1.10 by Gary Poster
update to newer version of buildout branch
243
else: # Windows prefers this, apparently; otherwise we would prefer subprocess
8827.2.1 by Gary Poster
use experimental eggs for buildout and friends
244
    exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env]))
245
if exitcode != 0:
8827.2.4 by Gary Poster
try to make ec2test happy, and fix up a bootstrap bug.
246
    sys.stdout.flush()
10303.1.10 by Gary Poster
update to newer version of buildout branch
247
    sys.stderr.flush()
11411.1.1 by Gary Poster
use the newest zc.buildout, zc.recipe.egg, z3c.recipe.scripts, and bootstrap.
248
    print ("An error occurred when trying to install zc.buildout. "
8827.2.2 by Gary Poster
use temporary, local eggs for buildout work.
249
           "Look above this message for any errors that "
250
           "were output by easy_install.")
8827.2.1 by Gary Poster
use experimental eggs for buildout and friends
251
    sys.exit(exitcode)
8697.27.1 by Gary Poster
bugfixes for problems revealed in ec2test
252
10303.1.10 by Gary Poster
update to newer version of buildout branch
253
ws.add_entry(eggs_dir)
8827.2.3 by Gary Poster
put in new zc.buildout eggs
254
ws.require(requirement)
8234.1.2 by Gary Poster
checkpoint: this initial buildout variant has several parts working, including run, start, stop, and harness.
255
import zc.buildout.buildout
8827.2.1 by Gary Poster
use experimental eggs for buildout and friends
256
zc.buildout.buildout.main(args)
10303.1.10 by Gary Poster
update to newer version of buildout branch
257
if not options.eggs: # clean up temporary egg directory
258
    shutil.rmtree(eggs_dir)