|
1 Automatic Buildout Updates |
|
2 ========================== |
|
3 |
|
4 When a buildout is run, one of the first steps performed is to check |
|
5 for updates to either zc.buildout or setuptools. To demonstrate this, |
|
6 we've created some "new releases" of buildout and setuptools in a |
|
7 new_releases folder: |
|
8 |
|
9 >>> ls(new_releases) |
|
10 d setuptools |
|
11 - setuptools-99.99-py2.4.egg |
|
12 d zc.buildout |
|
13 - zc.buildout-100.0b1-pyN.N.egg |
|
14 - zc.buildout-99.99-py2.4.egg |
|
15 |
|
16 Let's update the sample buildout.cfg to look in this area: |
|
17 |
|
18 >>> write(sample_buildout, 'buildout.cfg', |
|
19 ... """ |
|
20 ... [buildout] |
|
21 ... find-links = %(new_releases)s |
|
22 ... index = %(new_releases)s |
|
23 ... parts = show-versions |
|
24 ... develop = showversions |
|
25 ... |
|
26 ... [show-versions] |
|
27 ... recipe = showversions |
|
28 ... """ % dict(new_releases=new_releases)) |
|
29 |
|
30 We'll also include a recipe that echos the versions of setuptools and |
|
31 zc.buildout used: |
|
32 |
|
33 >>> mkdir(sample_buildout, 'showversions') |
|
34 |
|
35 >>> write(sample_buildout, 'showversions', 'showversions.py', |
|
36 ... """ |
|
37 ... import pkg_resources |
|
38 ... |
|
39 ... class Recipe: |
|
40 ... |
|
41 ... def __init__(self, buildout, name, options): |
|
42 ... pass |
|
43 ... |
|
44 ... def install(self): |
|
45 ... for project in 'zc.buildout', 'setuptools': |
|
46 ... req = pkg_resources.Requirement.parse(project) |
|
47 ... print project, pkg_resources.working_set.find(req).version |
|
48 ... return () |
|
49 ... update = install |
|
50 ... """) |
|
51 |
|
52 |
|
53 >>> write(sample_buildout, 'showversions', 'setup.py', |
|
54 ... """ |
|
55 ... from setuptools import setup |
|
56 ... |
|
57 ... setup( |
|
58 ... name = "showversions", |
|
59 ... entry_points = {'zc.buildout': ['default = showversions:Recipe']}, |
|
60 ... ) |
|
61 ... """) |
|
62 |
|
63 |
|
64 Now if we run the buildout, the buildout will upgrade itself to the |
|
65 new versions found in new releases: |
|
66 |
|
67 >>> print system(buildout), |
|
68 Getting distribution for 'zc.buildout'. |
|
69 Got zc.buildout 99.99. |
|
70 Getting distribution for 'setuptools'. |
|
71 Got setuptools 99.99. |
|
72 Upgraded: |
|
73 zc.buildout version 99.99, |
|
74 setuptools version 99.99; |
|
75 restarting. |
|
76 Generated script '/sample-buildout/bin/buildout'. |
|
77 Develop: '/sample-buildout/showversions' |
|
78 Installing show-versions. |
|
79 zc.buildout 99.99 |
|
80 setuptools 99.99 |
|
81 |
|
82 Notice that, even though we have a newer beta version of zc.buildout |
|
83 available, the final "99.99" was selected. If you want to get non-final |
|
84 versions, specify a specific version in your buildout's versions |
|
85 section, you typically want to use the --accept-buildout-test-releases |
|
86 option to the bootstrap script, which internally uses the |
|
87 ``accept-buildout-test-releases = true`` discussed below. |
|
88 |
|
89 Our buildout script's site.py has been updated to use the new eggs: |
|
90 |
|
91 >>> cat(sample_buildout, 'parts', 'buildout', 'site.py') |
|
92 ... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS |
|
93 "... |
|
94 def addsitepackages(known_paths): |
|
95 """Add site packages, as determined by zc.buildout. |
|
96 <BLANKLINE> |
|
97 See original_addsitepackages, below, for the original version.""" |
|
98 setuptools_path = '/sample-buildout/eggs/setuptools-99.99-pyN.N.egg' |
|
99 sys.path.append(setuptools_path) |
|
100 known_paths.add(os.path.normcase(setuptools_path)) |
|
101 import pkg_resources |
|
102 buildout_paths = [ |
|
103 '/sample-buildout/eggs/zc.buildout-99.99-pyN.N.egg', |
|
104 '/sample-buildout/eggs/setuptools-99.99-pyN.N.egg' |
|
105 ] |
|
106 for path in buildout_paths: |
|
107 sitedir, sitedircase = makepath(path) |
|
108 if not sitedircase in known_paths and os.path.exists(sitedir): |
|
109 sys.path.append(sitedir) |
|
110 known_paths.add(sitedircase) |
|
111 pkg_resources.working_set.add_entry(sitedir) |
|
112 sys.__egginsert = len(buildout_paths) # Support setuptools. |
|
113 original_paths = [ |
|
114 ... |
|
115 ] |
|
116 for path in original_paths: |
|
117 if path == setuptools_path or path not in known_paths: |
|
118 addsitedir(path, known_paths) |
|
119 return known_paths |
|
120 ... |
|
121 |
|
122 Now, let's recreate the sample buildout. If we specify constraints on |
|
123 the versions of zc.buildout and setuptools (or distribute) to use, |
|
124 running the buildout will install earlier versions of these packages: |
|
125 |
|
126 >>> write(sample_buildout, 'buildout.cfg', |
|
127 ... """ |
|
128 ... [buildout] |
|
129 ... find-links = %(new_releases)s |
|
130 ... index = %(new_releases)s |
|
131 ... parts = show-versions |
|
132 ... develop = showversions |
|
133 ... zc.buildout-version = < 99 |
|
134 ... setuptools-version = < 99 |
|
135 ... distribute-version = < 99 |
|
136 ... |
|
137 ... [show-versions] |
|
138 ... recipe = showversions |
|
139 ... """ % dict(new_releases=new_releases)) |
|
140 |
|
141 Now we can see that we actually "upgrade" to an earlier version. |
|
142 |
|
143 >>> print system(buildout), |
|
144 Upgraded: |
|
145 zc.buildout version 1.0.0, |
|
146 setuptools version 0.6; |
|
147 restarting. |
|
148 Develop: '/sample-buildout/showversions' |
|
149 Updating show-versions. |
|
150 zc.buildout 1.0.0 |
|
151 setuptools 0.6 |
|
152 |
|
153 There are a number of cases, described below, in which the updates |
|
154 don't happen. |
|
155 |
|
156 We won't upgrade in offline mode: |
|
157 |
|
158 >>> write(sample_buildout, 'buildout.cfg', |
|
159 ... """ |
|
160 ... [buildout] |
|
161 ... find-links = %(new_releases)s |
|
162 ... index = %(new_releases)s |
|
163 ... parts = show-versions |
|
164 ... develop = showversions |
|
165 ... |
|
166 ... [show-versions] |
|
167 ... recipe = showversions |
|
168 ... """ % dict(new_releases=new_releases)) |
|
169 |
|
170 >>> print system(buildout+' -o'), |
|
171 Develop: '/sample-buildout/showversions' |
|
172 Updating show-versions. |
|
173 zc.buildout 1.0.0 |
|
174 setuptools 0.6 |
|
175 |
|
176 Or in non-newest mode: |
|
177 |
|
178 >>> print system(buildout+' -N'), |
|
179 Develop: '/sample-buildout/showversions' |
|
180 Updating show-versions. |
|
181 zc.buildout 1.0.0 |
|
182 setuptools 0.6 |
|
183 |
|
184 We also won't upgrade if the buildout script being run isn't in the |
|
185 buildout's bin directory. To see this we'll create a new buildout |
|
186 directory: |
|
187 |
|
188 >>> sample_buildout2 = tmpdir('sample_buildout2') |
|
189 >>> write(sample_buildout2, 'buildout.cfg', |
|
190 ... """ |
|
191 ... [buildout] |
|
192 ... find-links = %(new_releases)s |
|
193 ... index = %(new_releases)s |
|
194 ... parts = |
|
195 ... """ % dict(new_releases=new_releases)) |
|
196 |
|
197 >>> cd(sample_buildout2) |
|
198 >>> print system(buildout), |
|
199 Creating directory '/sample_buildout2/bin'. |
|
200 Creating directory '/sample_buildout2/parts'. |
|
201 Creating directory '/sample_buildout2/eggs'. |
|
202 Creating directory '/sample_buildout2/develop-eggs'. |
|
203 Getting distribution for 'zc.buildout'. |
|
204 Got zc.buildout 99.99. |
|
205 Getting distribution for 'setuptools'. |
|
206 Got setuptools 99.99. |
|
207 Not upgrading because not running a local buildout command. |
|
208 |
|
209 >>> ls('bin') |
|
210 |
|
211 As mentioned above, the ``accept-buildout-test-releases = true`` means that |
|
212 newer non-final versions of these dependencies are preferred. Typically |
|
213 users are not expected to actually manipulate this value. Instead, the |
|
214 bootstrap script creates a buildout buildout script that passes in the |
|
215 value as a command line override. This then results in the buildout |
|
216 script being rewritten to remember the decision. |
|
217 |
|
218 We'll mimic this by passing the argument actually in the command line. |
|
219 |
|
220 >>> cd(sample_buildout) |
|
221 >>> write(sample_buildout, 'buildout.cfg', |
|
222 ... """ |
|
223 ... [buildout] |
|
224 ... find-links = %(new_releases)s |
|
225 ... index = %(new_releases)s |
|
226 ... parts = show-versions |
|
227 ... develop = showversions |
|
228 ... |
|
229 ... [show-versions] |
|
230 ... recipe = showversions |
|
231 ... """ % dict(new_releases=new_releases)) |
|
232 |
|
233 >>> print system(buildout + |
|
234 ... ' buildout:accept-buildout-test-releases=true'), |
|
235 ... # doctest: +NORMALIZE_WHITESPACE |
|
236 Getting distribution for 'zc.buildout'. |
|
237 Got zc.buildout 100.0b1. |
|
238 Upgraded: |
|
239 zc.buildout version 100.0b1, |
|
240 setuptools version 99.99; |
|
241 restarting. |
|
242 Generated script '/sample-buildout/bin/buildout'. |
|
243 NOTE: Accepting early releases of build system packages. Rerun bootstrap |
|
244 without --accept-buildout-test-releases (-t) to return to default |
|
245 behavior. |
|
246 Develop: '/sample-buildout/showversions' |
|
247 Updating show-versions. |
|
248 zc.buildout 100.0b1 |
|
249 setuptools 99.99 |
|
250 |
|
251 The buildout script shows the change. |
|
252 |
|
253 >>> buildout_script = join(sample_buildout, 'bin', 'buildout') |
|
254 >>> import sys |
|
255 >>> if sys.platform.startswith('win'): |
|
256 ... buildout_script += '-script.py' |
|
257 >>> print open(buildout_script).read() # doctest: +ELLIPSIS |
|
258 #... |
|
259 sys.argv.insert(1, 'buildout:accept-buildout-test-releases=true') |
|
260 print ('NOTE: Accepting early releases of build system packages. Rerun ' |
|
261 'bootstrap without --accept-buildout-test-releases (-t) to return to ' |
|
262 'default behavior.') |
|
263 ... |