17
17
The script accepts buildout command-line options, so you can
18
18
use the -c option to specify an alternate configuration file.
20
$Id: bootstrap.py 101930 2009-07-15 18:34:35Z gary $
23
import os, re, shutil, sys, tempfile, textwrap, urllib, urllib2
25
# We have to manually parse our options rather than using one of the stdlib
26
# tools because we want to pass the ones we don't recognize along to
27
# zc.buildout.buildout.main.
30
'--ez_setup-source': 'http://peak.telecommunity.com/dist/ez_setup.py',
32
'--download-base': None,
35
helpstring = __doc__ + textwrap.dedent('''
36
This script recognizes the following options itself. The first option it
37
encounters that is not one of these will cause the script to stop parsing
38
options and pass the rest on to buildout. Therefore, if you want to use
39
any of the following options *and* buildout command-line options like
40
-c, first use the following options, and then use the buildout options.
43
--version=ZC_BUILDOUT_VERSION
44
Specify a version number of the zc.buildout to use
45
--ez_setup-source=URL_OR_FILE
46
Specify a URL or file location for the ez_setup file.
49
--download-base=URL_OR_DIRECTORY
50
Specify a URL or directory for downloading setuptools and
51
zc.buildout. Defaults to PyPI.
53
Specify a directory for storing eggs. Defaults to a temporary
54
directory that is deleted when the bootstrap script completes.
56
By using --ez_setup-source and --download-base to point to local resources,
57
you can keep this script from going over the network.
59
match_equals = re.compile(r'(%s)=(.*)' % ('|'.join(configuration),)).match
61
if args == ['--help']:
65
# If we end up using a temporary directory for storing our eggs, this will
66
# hold the path of that directory. On the other hand, if an explicit directory
67
# is specified in the argv, this will remain None.
72
if val in configuration:
74
if not args or args[0].startswith('-'):
75
print "ERROR: %s requires an argument."
78
configuration[val] = args[0]
80
match = match_equals(val)
81
if match and match.group(1) in configuration:
82
configuration[match.group(1)] = match.group(2)
23
import os, shutil, sys, tempfile, textwrap, urllib, urllib2
24
from optparse import OptionParser
26
if sys.platform == 'win32':
29
return '"%s"' % c # work around spawn lamosity on windows
87
for name in ('--ez_setup-source', '--download-base'):
88
val = configuration[name]
89
if val is not None and '://' not in val: # We're being lazy.
90
configuration[name] = 'file://%s' % (
91
urllib.pathname2url(os.path.abspath(os.path.expanduser(val))),)
93
if (configuration['--download-base'] and
94
not configuration['--download-base'].endswith('/')):
95
# Download base needs a trailing slash to make the world happy.
96
configuration['--download-base'] += '/'
98
if not configuration['--eggs']:
99
configuration['--eggs'] = tmpeggs = tempfile.mkdtemp()
101
configuration['--eggs'] = os.path.abspath(
102
os.path.expanduser(configuration['--eggs']))
104
# The requirement is what we will pass to setuptools to specify zc.buildout.
105
requirement = 'zc.buildout'
106
if configuration['--version']:
107
requirement += '==' + configuration['--version']
35
# In order to be more robust in the face of system Pythons, we want to
36
# run without site-packages loaded. This is somewhat tricky, in
37
# particular because Python 2.6's distutils imports site, so starting
38
# with the -S flag is not sufficient. However, we'll start with that:
39
if 'site' in sys.modules:
40
# We will restart with python -S.
42
args[0:0] = [sys.executable, '-S']
43
args = map(quote, args)
44
os.execv(sys.executable, args)
45
# Now we are running with -S. We'll get the clean sys.path, import site
46
# because distutils will do it later, and then reset the path and clean
47
# out any namespace packages from site-packages that might have been
48
# loaded by .pth files.
49
clean_path = sys.path[:]
51
sys.path[:] = clean_path
52
for k, v in sys.modules.items():
53
if (hasattr(v, '__path__') and
54
len(v.__path__)==1 and
55
not os.path.exists(os.path.join(v.__path__[0],'__init__.py'))):
56
# This is a namespace package. Remove it.
59
is_jython = sys.platform.startswith('java')
61
setuptools_source = 'http://peak.telecommunity.com/dist/ez_setup.py'
62
distribute_source = 'http://python-distribute.org/distribute_setup.py'
65
def normalize_to_url(option, opt_str, value, parser):
67
if '://' not in value: # It doesn't smell like a URL.
68
value = 'file://%s' % (
70
os.path.abspath(os.path.expanduser(value))),)
71
if opt_str == '--download-base' and not value.endswith('/'):
72
# Download base needs a trailing slash to make the world happy.
76
name = opt_str[2:].replace('-', '_')
77
setattr(parser.values, name, value)
80
[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
82
Bootstraps a buildout-based project.
84
Simply run this script in a directory containing a buildout.cfg, using the
85
Python that you want bin/buildout to use.
87
Note that by using --setup-source and --download-base to point to
88
local resources, you can keep this script from going over the network.
91
parser = OptionParser(usage=usage)
92
parser.add_option("-v", "--version", dest="version",
93
help="use a specific zc.buildout version")
94
parser.add_option("-d", "--distribute",
95
action="store_true", dest="use_distribute", default=False,
96
help="Use Distribute rather than Setuptools.")
97
parser.add_option("--setup-source", action="callback", dest="setup_source",
98
callback=normalize_to_url, nargs=1, type="string",
99
help=("Specify a URL or file location for the setup file. "
100
"If you use Setuptools, this will default to " +
101
setuptools_source + "; if you use Distribute, this "
102
"will default to " + distribute_source +"."))
103
parser.add_option("--download-base", action="callback", dest="download_base",
104
callback=normalize_to_url, nargs=1, type="string",
105
help=("Specify a URL or directory for downloading "
106
"zc.buildout and either Setuptools or Distribute. "
107
"Defaults to PyPI."))
108
parser.add_option("--eggs",
109
help=("Specify a directory for storing eggs. Defaults to "
110
"a temporary directory that is deleted when the "
111
"bootstrap script completes."))
112
parser.add_option("-c", None, action="store", dest="config_file",
113
help=("Specify the path to the buildout configuration "
116
options, args = parser.parse_args()
118
# if -c was provided, we push it back into args for buildout' main function
119
if options.config_file is not None:
120
args += ['-c', options.config_file]
123
eggs_dir = os.path.abspath(os.path.expanduser(options.eggs))
125
eggs_dir = tempfile.mkdtemp()
127
if options.setup_source is None:
128
if options.use_distribute:
129
options.setup_source = distribute_source
131
options.setup_source = setuptools_source
133
args = args + ['bootstrap']
140
if not hasattr(pkg_resources, '_distribute'):
110
142
import setuptools # A flag. Sometimes pkg_resources is installed alone.
112
143
except ImportError:
144
ez_code = urllib2.urlopen(
145
options.setup_source).read().replace('\r\n', '\n')
114
exec urllib2.urlopen(configuration['--ez_setup-source']).read() in ez
115
setuptools_args = dict(to_dir=configuration['--eggs'], download_delay=0)
116
if configuration['--download-base']:
117
setuptools_args['download_base'] = configuration['--download-base']
118
ez['use_setuptools'](**setuptools_args)
148
setup_args = dict(to_dir=eggs_dir, download_delay=0)
149
if options.download_base:
150
setup_args['download_base'] = options.download_base
151
if options.use_distribute:
152
setup_args['no_fake'] = True
153
ez['use_setuptools'](**setup_args)
155
reload(pkg_resources)
120
158
# This does not (always?) update the default working set. We will
122
160
for path in sys.path:
123
161
if path not in pkg_resources.working_set.entries:
124
162
pkg_resources.working_set.add_entry(path)
126
if sys.platform == 'win32':
129
return '"%s"' % c # work around spawn lamosity on windows
135
164
cmd = [quote(sys.executable),
137
166
quote('from setuptools.command.easy_install import main; main()'),
139
quote(configuration['--eggs'])]
141
if configuration['--download-base']:
142
cmd.extend(['-f', quote(configuration['--download-base'])])
170
if options.download_base:
171
cmd.extend(['-f', quote(options.download_base)])
173
requirement = 'zc.buildout'
175
requirement = '=='.join((requirement, options.version))
144
176
cmd.append(requirement)
178
if options.use_distribute:
179
setup_requirement = 'distribute'
181
setup_requirement = 'setuptools'
146
182
ws = pkg_resources.working_set
149
PYTHONPATH=ws.find(pkg_resources.Requirement.parse('setuptools')).location)
186
pkg_resources.Requirement.parse(setup_requirement)).location)
151
is_jython = sys.platform.startswith('java')
153
189
import subprocess
154
190
exitcode = subprocess.Popen(cmd, env=env).wait()
155
else: # Windows needs this, apparently; otherwise we would prefer subprocess
191
else: # Windows prefers this, apparently; otherwise we would prefer subprocess
156
192
exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env]))
157
193
if exitcode != 0:
158
194
sys.stdout.flush()
159
196
print ("An error occured when trying to install zc.buildout. "
160
197
"Look above this message for any errors that "
161
198
"were output by easy_install.")
162
199
sys.exit(exitcode)
164
ws.add_entry(configuration['--eggs'])
201
ws.add_entry(eggs_dir)
165
202
ws.require(requirement)
166
203
import zc.buildout.buildout
167
args.append('bootstrap')
168
204
zc.buildout.buildout.main(args)
169
if tmpeggs is not None:
170
shutil.rmtree(tmpeggs)
205
if not options.eggs: # clean up temporary egg directory
206
shutil.rmtree(eggs_dir)