Merge lp:~gary/zc.buildout/betafix6 into lp:zc.buildout
- betafix6
- Merge into trunk
Status: | Needs review |
---|---|
Proposed branch: | lp:~gary/zc.buildout/betafix6 |
Merge into: | lp:zc.buildout |
Prerequisite: | lp:~gary/zc.buildout/betafix5 |
Diff against target: |
979 lines (+465/-123) 7 files modified
CHANGES.txt (+37/-4) src/zc/buildout/bootstrap.txt (+103/-24) src/zc/buildout/buildout.py (+60/-55) src/zc/buildout/buildout.txt (+24/-12) src/zc/buildout/easy_install.py (+20/-15) src/zc/buildout/tests.py (+183/-11) src/zc/buildout/update.txt (+38/-2) |
To merge this branch: | bzr merge lp:~gary/zc.buildout/betafix6 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Francis J. Lacoste (community) | code | Approve | |
Review via email: mp+31996@code.launchpad.net |
Commit message
Description of the change
By default, Buildout and the bootstrap script now prefer final versions of Buildout, recipes, and extensions. This was done to try and prevent problems such as those that happened the last time I tried to make a zc.buildout release. See the CHANGES file updates (which also include some notes I should have included in an earlier revision) for how it works; also not that betafix7 has a help document for users, so if you think the mechanism is fine but you want the users to have some better docs, please look at that branch. The logic for figuring out final versions in bootstrap was ripped from easy_install. The bootstrap test had to do some new tricks to exercise the changes. These new tricks revealed that, once the new version of zc.buildout was released, the bootstrap test would have failed. I believe this is now fixed as a side effect of the main effort.
I factored out some bool parsing behavior into a method on the Options object, because I was adding yet another bool and wanted to not copy and paste the code again. Note that I change the behavior of get_bool in betafix7, so it might be better to comment on its approach on that branch.
Francis J. Lacoste (flacoste) wrote : | # |
Francis J. Lacoste (flacoste) wrote : | # |
OK, after discussion on IRC it does seem that this limitation is what is best acceptable trade-off. There is already duplication of options already (download-cache, eggs) etc.
If it's easy to detect that buildout would be downgraded (boostrap used --accept, but the option is missing in buildout), then I'd suggest adding an error asking the user to either rerun bootstrap without the option or change the buildout.cfg variable.
Otherwise (or in addition) change the documentation of the option to make it clear that one should set the buildout.cfg option when using the bootstrap option otherwise things will get confused.
- 564. By Gary Poster
-
clarify that --accept-
early-release must be accompanied with prefer- final-build- system= false.
Gary Poster (gary) wrote : | # |
Hey Francis. What do you think of this approach to addressing your concerns?
http://
Essentially, you only have to use --accept-
This is much nicer usability, at the expense of a somewhat odd pattern; however, I think it is defensible since what we are trying to control extends from bootstrapping through normal use.
If you think this is reasonable, I'll need to update CHANGES and make sure the rest of the tests still pass.
Gary Poster (gary) wrote : | # |
Cool. The patch got on the big side (526 lines) so I made it into another branch based on betafix7: https:/
Unmerged revisions
- 564. By Gary Poster
-
clarify that --accept-
early-release must be accompanied with prefer- final-build- system= false. - 563. By Gary Poster
-
merge from trunk/previous branches
- 562. By Gary Poster
-
By default, Buildout and the bootstrap script now prefer final versions of Buildout, recipes, and extensions.
- 561. By Gary Poster
-
get tests passing for Python 2.7. Also includes Lennart Regebro changes to use the standard library doctest.
- 560. By Gary Poster
-
small Python 2.6 bugfix and Distribute test clean-ups
- 559. By Gary Poster
-
fix tests for changes
- 558. By Gary Poster
-
mimic standard site.py behavior for inclusion of .pth files
- 557. By Gary Poster
-
eliminate spurious warning if you are using distribute.
- 556. By Gary Poster
-
add files so releases can be made from a non-SVN checkout
- 555. By Gary Poster
-
fix virtualenv interaction by identfying broken virtualenv characteristic and reverting to previous behavior in that case.
Preview Diff
1 | === modified file 'CHANGES.txt' |
2 | --- CHANGES.txt 2010-08-07 00:12:52 +0000 |
3 | +++ CHANGES.txt 2010-08-07 00:12:52 +0000 |
4 | @@ -1,19 +1,52 @@ |
5 | Change History |
6 | ************** |
7 | |
8 | +1.5.0b3 (unreleased) |
9 | +==================== |
10 | + |
11 | +New features: |
12 | + |
13 | +- zc.buildout supports Python 2.7. |
14 | + |
15 | +- By default, Buildout and the bootstrap script now prefer final versions of |
16 | + Buildout, recipes, and extensions. This can be changed by setting |
17 | + ``prefer-final-build-system = false`` in your configuration's |
18 | + [buildout] section, and by using the --accept-early-release flag when |
19 | + calling bootstrap. This will hopefully allow beta releases to be more |
20 | + easily and safely made in the future. Note that dependencies of your |
21 | + software do not have this behavior: use the pre-existing switch |
22 | + ``prefer-final = true`` to get this behavior. |
23 | + |
24 | +Bugs fixed: |
25 | + |
26 | +- You can now again use virtualenv with zc.buildout. The new features to let |
27 | + buildout be used with a system Python are disabled in this configuration, |
28 | + and the previous script generation behavior (1.4.3) is used, even if |
29 | + the new function ``zc.buildout.easy_install.sitepackage_safe_scripts`` |
30 | + is used. |
31 | + |
32 | +1.5.0b2 (2010-04-29) |
33 | +==================== |
34 | + |
35 | +This was a re-release of 1.4.3 in order to keep 1.5.0b1 release from hurting |
36 | +workflows that combined virtualenv with zc.buildout. |
37 | + |
38 | 1.5.0b1 (2010-04-29) |
39 | ==================== |
40 | |
41 | New Features: |
42 | |
43 | -- zc.buildout supports Python 2.7. |
44 | - |
45 | - Added buildout:socket-timout option so that socket timeout can be configured |
46 | both from command line and from config files. (gotcha) |
47 | |
48 | - Buildout can be safely used with a system Python (or any Python with code |
49 | - in site-packages), as long as you use the new z3c.recipe.scripts |
50 | - recipe to generate scripts and interpreters, rather than zc.recipe.egg. |
51 | + in site-packages), as long as you use (1) A fresh checkout, (2) the |
52 | + new bootstrap.py, and (3) recipes that use the new |
53 | + ``zc.buildout.easy_install.sitepackage_safe_scripts`` function to generate |
54 | + scripts and interpreters. Many recipes will need to be updated to use |
55 | + this new function. The scripts and interpreters generated by |
56 | + ``zc.recipe.egg`` will continue to use the older function, not safe |
57 | + with system Pythons. Use the ``z3c.recipe.scripts`` as a replacement. |
58 | |
59 | zc.recipe.egg is still a fully supported, and simpler, way of |
60 | generating scripts and interpreters if you are using a "clean" Python, |
61 | |
62 | === modified file 'src/zc/buildout/bootstrap.txt' |
63 | --- src/zc/buildout/bootstrap.txt 2010-08-07 00:12:52 +0000 |
64 | +++ src/zc/buildout/bootstrap.txt 2010-08-07 00:12:52 +0000 |
65 | @@ -47,6 +47,87 @@ |
66 | X... |
67 | d zc.buildout-...egg |
68 | |
69 | +The buildout script it has generated is a new-style script, using a |
70 | +customized site.py. |
71 | + |
72 | + >>> buildout_script = join(sample_buildout, 'bin', 'buildout') |
73 | + >>> if sys.platform.startswith('win'): |
74 | + ... buildout_script += '-script.py' |
75 | + >>> print open(buildout_script).read() # doctest: +ELLIPSIS |
76 | + #... |
77 | + <BLANKLINE> |
78 | + import sys |
79 | + sys.path[0:0] = [ |
80 | + '/sample/parts/buildout', |
81 | + ] |
82 | + <BLANKLINE> |
83 | + <BLANKLINE> |
84 | + import os |
85 | + path = sys.path[0] |
86 | + if os.environ.get('PYTHONPATH'): |
87 | + path = os.pathsep.join([path, os.environ['PYTHONPATH']]) |
88 | + os.environ['PYTHONPATH'] = path |
89 | + import site # imports custom buildout-generated site.py |
90 | + <BLANKLINE> |
91 | + import zc.buildout.buildout |
92 | + <BLANKLINE> |
93 | + if __name__ == '__main__': |
94 | + zc.buildout.buildout.main() |
95 | + <BLANKLINE> |
96 | + |
97 | +The bootstrap process prefers final versions of zc.buildout, so it has |
98 | +selected the (generated-locally) 99.99 egg rather than the also-available |
99 | +100.0b1 egg. We can see that in the buildout script's site.py. |
100 | + |
101 | + >>> buildout_site_py = join( |
102 | + ... sample_buildout, 'parts', 'buildout', 'site.py') |
103 | + >>> print open(buildout_site_py).read() # doctest: +ELLIPSIS |
104 | + "... |
105 | + buildout_paths = [ |
106 | + '/sample/eggs/setuptools-...egg', |
107 | + '/sample/eggs/zc.buildout-99.99-pyN.N.egg' |
108 | + ] |
109 | + ... |
110 | + |
111 | +If you want to accept early releases of zc.buildout, you either need to |
112 | +specify an explicit version (using --version here and specifying the |
113 | +version in the buildout configuration file using the |
114 | +``buildout-version`` option or the ``versions`` option) or specify that you |
115 | +accept early releases. |
116 | + |
117 | +You accept early releases by using ``--accept-early-release`` on the |
118 | +bootstrap script and specifying ``prefer-final-build-system = false`` in the |
119 | +buildout configuration file. You must do both. |
120 | + |
121 | +Here's an example. |
122 | + |
123 | + >>> write('buildout.cfg', |
124 | + ... ''' |
125 | + ... [buildout] |
126 | + ... parts = |
127 | + ... prefer-final-build-system = false |
128 | + ... ''') |
129 | + >>> ignored = system( |
130 | + ... zc.buildout.easy_install._safe_arg(sys.executable)+' '+ |
131 | + ... 'bootstrap.py --accept-early-release') |
132 | + >>> print open(buildout_site_py).read() # doctest: +ELLIPSIS |
133 | + "... |
134 | + buildout_paths = [ |
135 | + '/sample/eggs/setuptools-...egg', |
136 | + '/sample/eggs/zc.buildout-100.0b1-pyN.N.egg' |
137 | + ] |
138 | + ... |
139 | + |
140 | +Notice we are now using zc.buildout 100.0b1, a non-final release. |
141 | + |
142 | +Now we'll go back to the default of preferring final versions. |
143 | + |
144 | + >>> write('buildout.cfg', |
145 | + ... ''' |
146 | + ... [buildout] |
147 | + ... parts = |
148 | + ... ''') |
149 | + |
150 | Now we will try the `--version` option, which lets you define a version for |
151 | `zc.buildout`. If not provided, bootstrap will look for the latest one. |
152 | |
153 | @@ -71,11 +152,9 @@ |
154 | <BLANKLINE> |
155 | X |
156 | |
157 | -Let's make sure the generated `buildout` script uses it:: |
158 | +Versions older than 1.5.0 put their egg dependencies in the ``buildout`` script. |
159 | +Let's make sure it was generated as we expect:: |
160 | |
161 | - >>> buildout_script = join(sample_buildout, 'bin', 'buildout') |
162 | - >>> if sys.platform.startswith('win'): |
163 | - ... buildout_script += '-script.py' |
164 | >>> print open(buildout_script).read() # doctest: +ELLIPSIS |
165 | #... |
166 | <BLANKLINE> |
167 | @@ -102,7 +181,7 @@ |
168 | <BLANKLINE> |
169 | X |
170 | |
171 | -Let's make sure the generated `buildout` script uses it:: |
172 | +Let's make sure the generated ``buildout`` script uses it:: |
173 | |
174 | >>> print open(buildout_script).read() # doctest: +ELLIPSIS |
175 | #... |
176 | @@ -119,7 +198,7 @@ |
177 | zc.buildout.buildout.main() |
178 | <BLANKLINE> |
179 | |
180 | -`zc.buildout` now can also run with `Distribute` with the `--distribute` |
181 | +``zc.buildout`` now can also run with `Distribute` with the `--distribute` |
182 | option:: |
183 | |
184 | >>> print 'X'; print system( |
185 | @@ -131,22 +210,14 @@ |
186 | Generated script '/sample/bin/buildout'... |
187 | X |
188 | |
189 | -Let's make sure the generated `buildout` script uses it:: |
190 | - |
191 | - >>> print open(buildout_script).read() # doctest: +ELLIPSIS |
192 | - #... |
193 | - <BLANKLINE> |
194 | - import sys |
195 | - sys.path[0:0] = [ |
196 | - '/sample/eggs/distribute-...egg', |
197 | - '/sample/eggs/zc.buildout-...egg', |
198 | - ] |
199 | - <BLANKLINE> |
200 | - import zc.buildout.buildout |
201 | - <BLANKLINE> |
202 | - if __name__ == '__main__': |
203 | - zc.buildout.buildout.main() |
204 | - <BLANKLINE> |
205 | +Let's make sure the generated ``site.py`` uses it:: |
206 | + >>> print open(buildout_site_py).read() # doctest: +ELLIPSIS |
207 | + "... |
208 | + buildout_paths = [ |
209 | + '/sample/eggs/distribute-...egg', |
210 | + '/sample/eggs/zc.buildout-99.99-pyN.N.egg' |
211 | + ] |
212 | + ... |
213 | |
214 | Make sure both options can be used together:: |
215 | |
216 | @@ -160,8 +231,8 @@ |
217 | Generated script '/sample/bin/buildout'... |
218 | X |
219 | |
220 | -Let's make sure the generated `buildout` script uses ``Distribute`` *and* |
221 | -``zc.buildout-1.2.1``:: |
222 | +Let's make sure the old-style generated ``buildout`` script uses |
223 | +``Distribute`` *and* ``zc.buildout-1.2.1``:: |
224 | |
225 | >>> print open(buildout_script).read() # doctest: +ELLIPSIS |
226 | #... |
227 | @@ -258,5 +329,13 @@ |
228 | --eggs=EGGS Specify a directory for storing eggs. Defaults to a |
229 | temporary directory that is deleted when the bootstrap |
230 | script completes. |
231 | + --accept-early-release |
232 | + Normally, if you do not specify a --version, the |
233 | + bootstrap script gets the newest *final* versions of |
234 | + zc.buildout for you. If you use this flag, and also |
235 | + set ``prefer-final-build-system= false`` in the |
236 | + [buildout] section of your configuration file, |
237 | + bootstrap will get the newest releases even if they |
238 | + are alphas or betas. |
239 | -c CONFIG_FILE Specify the path to the buildout configuration file to |
240 | be used. |
241 | |
242 | === modified file 'src/zc/buildout/buildout.py' |
243 | --- src/zc/buildout/buildout.py 2010-08-07 00:12:52 +0000 |
244 | +++ src/zc/buildout/buildout.py 2010-08-07 00:12:52 +0000 |
245 | @@ -131,6 +131,7 @@ |
246 | 'offline': 'false', |
247 | 'parts-directory': 'parts', |
248 | 'prefer-final': 'false', |
249 | + 'prefer-final-build-system': 'true', |
250 | 'python': 'buildout', |
251 | 'relative-paths': 'false', |
252 | 'socket-timeout': '', |
253 | @@ -234,6 +235,8 @@ |
254 | self._logger = logging.getLogger('zc.buildout') |
255 | self.offline = (buildout_section['offline'] == 'true') |
256 | self.newest = (buildout_section['newest'] == 'true') |
257 | + self.prefer_final_build_system = ( |
258 | + buildout_section['prefer-final-build-system'] == 'true') |
259 | |
260 | ################################################################## |
261 | ## WARNING!!! |
262 | @@ -267,42 +270,26 @@ |
263 | |
264 | self._setup_logging() |
265 | |
266 | - offline = options['offline'] |
267 | - if offline not in ('true', 'false'): |
268 | - self._error('Invalid value for offline option: %s', offline) |
269 | - self.offline = (offline == 'true') |
270 | - |
271 | - if self.offline: |
272 | - newest = options['newest'] = 'false' |
273 | - else: |
274 | - newest = options['newest'] |
275 | - if newest not in ('true', 'false'): |
276 | - self._error('Invalid value for newest option: %s', newest) |
277 | - self.newest = (newest == 'true') |
278 | - |
279 | versions = options.get('versions') |
280 | if versions: |
281 | zc.buildout.easy_install.default_versions(dict(self[versions])) |
282 | |
283 | - prefer_final = options['prefer-final'] |
284 | - if prefer_final not in ('true', 'false'): |
285 | - self._error('Invalid value for prefer-final option: %s', |
286 | - prefer_final) |
287 | - zc.buildout.easy_install.prefer_final(prefer_final=='true') |
288 | |
289 | - use_dependency_links = options['use-dependency-links'] |
290 | - if use_dependency_links not in ('true', 'false'): |
291 | - self._error('Invalid value for use-dependency-links option: %s', |
292 | - use_dependency_links) |
293 | + self.offline = options.get_bool('offline') |
294 | + if self.offline: |
295 | + options['newest'] = 'false' |
296 | + self.newest = options.get_bool('newest') |
297 | + zc.buildout.easy_install.prefer_final( |
298 | + options.get_bool('prefer-final')) |
299 | + self.prefer_final_build_system = options.get_bool( |
300 | + 'prefer-final-build-system') |
301 | zc.buildout.easy_install.use_dependency_links( |
302 | - use_dependency_links == 'true') |
303 | - |
304 | - allow_picked_versions = options['allow-picked-versions'] |
305 | - if allow_picked_versions not in ('true', 'false'): |
306 | - self._error('Invalid value for allow-picked-versions option: %s', |
307 | - allow_picked_versions) |
308 | + options.get_bool('use-dependency-links')) |
309 | zc.buildout.easy_install.allow_picked_versions( |
310 | - allow_picked_versions == 'true') |
311 | + options.get_bool('allow-picked-versions')) |
312 | + zc.buildout.easy_install.install_from_cache( |
313 | + options.get_bool('install-from-cache')) |
314 | + zc.buildout.easy_install.always_unzip(options.get_bool('unzip')) |
315 | |
316 | download_cache = options.get('download-cache') |
317 | if download_cache: |
318 | @@ -319,19 +306,6 @@ |
319 | |
320 | zc.buildout.easy_install.download_cache(download_cache) |
321 | |
322 | - install_from_cache = options['install-from-cache'] |
323 | - if install_from_cache not in ('true', 'false'): |
324 | - self._error('Invalid value for install-from-cache option: %s', |
325 | - install_from_cache) |
326 | - zc.buildout.easy_install.install_from_cache( |
327 | - install_from_cache=='true') |
328 | - |
329 | - always_unzip = options['unzip'] |
330 | - if always_unzip not in ('true', 'false'): |
331 | - self._error('Invalid value for unzip option: %s', |
332 | - always_unzip) |
333 | - zc.buildout.easy_install.always_unzip(always_unzip=='true') |
334 | - |
335 | # "Use" each of the defaults so they aren't reported as unused options. |
336 | for name in _buildout_default_options: |
337 | options[name] |
338 | @@ -364,6 +338,7 @@ |
339 | [options['develop-eggs-directory'], |
340 | options['eggs-directory']], |
341 | include_site_packages=_sys_executable_has_broken_dash_S, |
342 | + prefer_final = self.prefer_final_build_system, |
343 | ) |
344 | else: |
345 | ws = zc.buildout.easy_install.install( |
346 | @@ -375,6 +350,7 @@ |
347 | newest=self.newest, |
348 | allow_hosts=self._allow_hosts, |
349 | include_site_packages=_sys_executable_has_broken_dash_S, |
350 | + prefer_final = self.prefer_final_build_system, |
351 | ) |
352 | |
353 | # Now copy buildout and setuptools eggs, and record destination eggs: |
354 | @@ -410,6 +386,8 @@ |
355 | else: |
356 | assert relative_paths == 'false' |
357 | relative_paths = '' |
358 | + # Ideally the (possibly) new version of buildout would get a |
359 | + # chance to write the script. Not sure how to do that. |
360 | zc.buildout.easy_install.sitepackage_safe_scripts( |
361 | options['bin-directory'], ws, options['executable'], partsdir, |
362 | reqs=['zc.buildout'], relative_paths=relative_paths, |
363 | @@ -427,7 +405,7 @@ |
364 | # for eggs: |
365 | sys.path.insert(0, self['buildout']['develop-eggs-directory']) |
366 | |
367 | - # Check for updates. This could cause the process to be rstarted |
368 | + # Check for updates. This could cause the process to be restarted. |
369 | self._maybe_upgrade() |
370 | |
371 | # load installed data |
372 | @@ -480,7 +458,7 @@ |
373 | # compute new part recipe signatures |
374 | self._compute_part_signatures(install_parts) |
375 | |
376 | - # uninstall parts that are no-longer used or who's configs |
377 | + # uninstall parts that are no-longer used or whose configs |
378 | # have changed |
379 | for part in reversed(installed_parts): |
380 | if part in install_parts: |
381 | @@ -626,11 +604,11 @@ |
382 | f.close() |
383 | |
384 | def _uninstall_part(self, part, installed_part_options): |
385 | - # ununstall part |
386 | + # uninstall part |
387 | __doing__ = 'Uninstalling %s.', part |
388 | self._logger.info(*__doing__) |
389 | |
390 | - # run uinstall recipe |
391 | + # run uninstall recipe |
392 | recipe, entry = _recipe(installed_part_options[part]) |
393 | try: |
394 | uninstaller = _install_and_load( |
395 | @@ -859,7 +837,8 @@ |
396 | index = options.get('index'), |
397 | path = [options['develop-eggs-directory']], |
398 | allow_hosts = self._allow_hosts, |
399 | - include_site_packages=_sys_executable_has_broken_dash_S |
400 | + include_site_packages=_sys_executable_has_broken_dash_S, |
401 | + prefer_final=self.prefer_final_build_system, |
402 | ) |
403 | |
404 | upgraded = [] |
405 | @@ -913,6 +892,8 @@ |
406 | # fast for Python to know to regenerate the .pyc/.pyo files. |
407 | shutil.rmtree(partsdir) |
408 | os.mkdir(partsdir) |
409 | + # Ideally the new version of buildout would get a chance to write the |
410 | + # script. Not sure how to do that. |
411 | zc.buildout.easy_install.sitepackage_safe_scripts( |
412 | options['bin-directory'], ws, sys.executable, partsdir, |
413 | reqs=['zc.buildout'], |
414 | @@ -957,7 +938,8 @@ |
415 | links = self['buildout'].get('find-links', '').split(), |
416 | index = self['buildout'].get('index'), |
417 | newest=self.newest, allow_hosts=self._allow_hosts, |
418 | - include_site_packages=_sys_executable_has_broken_dash_S) |
419 | + include_site_packages=_sys_executable_has_broken_dash_S, |
420 | + prefer_final=self.prefer_final_build_system) |
421 | |
422 | # Clear cache because extensions might now let us read pages we |
423 | # couldn't read before. |
424 | @@ -988,6 +970,7 @@ |
425 | setup = os.path.abspath(setup) |
426 | |
427 | fd, tsetup = tempfile.mkstemp() |
428 | + exe = zc.buildout.easy_install._safe_arg(sys.executable) |
429 | try: |
430 | os.write(fd, zc.buildout.easy_install.runsetup_template % dict( |
431 | setuptools=pkg_resources_loc, |
432 | @@ -1001,14 +984,10 @@ |
433 | for a in args: |
434 | arg_list.append(zc.buildout.easy_install._safe_arg(a)) |
435 | |
436 | - subprocess.Popen( |
437 | - [zc.buildout.easy_install._safe_arg(sys.executable)] |
438 | - + list(tsetup) |
439 | - + arg_list |
440 | - ).wait() |
441 | + subprocess.Popen([exe] + list(tsetup) + arg_list).wait() |
442 | |
443 | else: |
444 | - os.spawnl(os.P_WAIT, sys.executable, zc.buildout.easy_install._safe_arg (sys.executable), tsetup, |
445 | + os.spawnl(os.P_WAIT, sys.executable, exe, tsetup, |
446 | *[zc.buildout.easy_install._safe_arg(a) |
447 | for a in args]) |
448 | finally: |
449 | @@ -1075,7 +1054,8 @@ |
450 | working_set=pkg_resources.working_set, |
451 | newest=buildout.newest, |
452 | allow_hosts=buildout._allow_hosts, |
453 | - include_site_packages=_sys_executable_has_broken_dash_S) |
454 | + include_site_packages=_sys_executable_has_broken_dash_S, |
455 | + prefer_final=buildout.prefer_final_build_system) |
456 | |
457 | __doing__ = 'Loading %s recipe entry %s:%s.', group, spec, entry |
458 | return pkg_resources.load_entry_point( |
459 | @@ -1297,6 +1277,31 @@ |
460 | self.name) |
461 | return self._created |
462 | |
463 | + def get_bool(self, name, default=None, on_error=None): |
464 | + """Given a name, return a boolean value for that name. |
465 | + |
466 | + ``default``, if given, should be 'true', 'false', or None. None |
467 | + is the default, and means that there is no default for the |
468 | + value: the call should raise a MissingOption error if the name |
469 | + is not present. |
470 | + |
471 | + ``on_error``, if given, should be a callable that takes the name and |
472 | + the found value. |
473 | + """ |
474 | + if default is None: |
475 | + value = self[name] |
476 | + else: |
477 | + value = self.get(name, default=default) |
478 | + if value not in ('true', 'false'): |
479 | + if on_error is None: |
480 | + raise zc.buildout.UserError( |
481 | + 'Invalid value for %s option: %s' % (name, value)) |
482 | + else: |
483 | + on_error(name, value) |
484 | + else: |
485 | + return value == 'true' |
486 | + |
487 | + |
488 | _spacey_nl = re.compile('[ \t\r\f\v]*\n[ \t\r\f\v\n]*' |
489 | '|' |
490 | '^[ \t\r\f\v]+' |
491 | |
492 | === modified file 'src/zc/buildout/buildout.txt' |
493 | --- src/zc/buildout/buildout.txt 2010-06-23 12:07:30 +0000 |
494 | +++ src/zc/buildout/buildout.txt 2010-08-07 00:12:52 +0000 |
495 | @@ -765,6 +765,8 @@ |
496 | DEFAULT_VALUE |
497 | prefer-final= false |
498 | DEFAULT_VALUE |
499 | + prefer-final-build-system= true |
500 | + DEFAULT_VALUE |
501 | python= buildout |
502 | DEFAULT_VALUE |
503 | relative-paths= false |
504 | @@ -2244,6 +2246,7 @@ |
505 | parts = |
506 | parts-directory = /sample-buildout/parts |
507 | prefer-final = false |
508 | + prefer-final-build-system = true |
509 | python = buildout |
510 | relative-paths = false |
511 | socket-timeout = |
512 | @@ -2484,25 +2487,34 @@ |
513 | Preferring Final Releases |
514 | ------------------------- |
515 | |
516 | -Currently, when searching for new releases, the newest available |
517 | -release is used. This isn't usually ideal, as you may get a |
518 | -development release or alpha releases not ready to be widely used. |
519 | -You can request that final releases be preferred using the prefer |
520 | -final option in the buildout section:: |
521 | +Currently, when searching for new releases of your project's |
522 | +dependencies, the newest available release is used. This isn't usually |
523 | +ideal, as you may get a development release or alpha releases not ready |
524 | +to be widely used. You can request that final releases be preferred |
525 | +using the ``prefer-final`` option in the buildout section:: |
526 | |
527 | [buildout] |
528 | ... |
529 | prefer-final = true |
530 | |
531 | -When the prefer-final option is set to true, then when searching for |
532 | +When the ``prefer-final`` option is set to true, then when searching for |
533 | new releases, final releases are preferred. If there are final |
534 | releases that satisfy distribution requirements, then those releases |
535 | -are used even if newer non-final releases are available. The buildout |
536 | -prefer-final option can be used to override this behavior. |
537 | - |
538 | -In buildout version 2, final releases will be preferred by default. |
539 | -You will then need to use a false value for prefer-final to get the |
540 | -newest releases. |
541 | +are used even if newer non-final releases are available. |
542 | + |
543 | +A separate option controls the behavior of the build system itself. |
544 | +When buildout looks for recipes, extensions, and for updates to itself, |
545 | +it does prefer final releases by default, as of the 1.5.0 release. The |
546 | +``prefer-final-build-system`` option will let you override this behavior. |
547 | + |
548 | + [buildout] |
549 | + ... |
550 | + prefer-final-build-system = false |
551 | + |
552 | +In buildout version 2, all final releases will be preferred by |
553 | +default--that is ``prefer-final`` will also default to 'true'. You will |
554 | +then need to use a 'false' value for ``prefer-final`` to get the newest |
555 | +releases, like with ``prefer-final-build-system``. |
556 | |
557 | Finding distributions |
558 | --------------------- |
559 | |
560 | === modified file 'src/zc/buildout/easy_install.py' |
561 | --- src/zc/buildout/easy_install.py 2010-08-07 00:12:52 +0000 |
562 | +++ src/zc/buildout/easy_install.py 2010-08-07 00:12:52 +0000 |
563 | @@ -322,7 +322,8 @@ |
564 | use_dependency_links=None, |
565 | allow_hosts=('*',), |
566 | include_site_packages=None, |
567 | - allowed_eggs_from_site_packages=None |
568 | + allowed_eggs_from_site_packages=None, |
569 | + prefer_final=None, |
570 | ): |
571 | self._dest = dest |
572 | self._allow_hosts = allow_hosts |
573 | @@ -336,6 +337,8 @@ |
574 | |
575 | if use_dependency_links is not None: |
576 | self._use_dependency_links = use_dependency_links |
577 | + if prefer_final is not None: |
578 | + self._prefer_final = prefer_final |
579 | self._links = links = list(_fix_file_links(links)) |
580 | if self._download_cache and (self._download_cache not in links): |
581 | links.insert(0, self._download_cache) |
582 | @@ -1060,13 +1063,14 @@ |
583 | executable=sys.executable, always_unzip=None, |
584 | path=None, working_set=None, newest=True, versions=None, |
585 | use_dependency_links=None, allow_hosts=('*',), |
586 | - include_site_packages=None, allowed_eggs_from_site_packages=None): |
587 | - installer = Installer(dest, links, index, executable, always_unzip, path, |
588 | - newest, versions, use_dependency_links, |
589 | - allow_hosts=allow_hosts, |
590 | - include_site_packages=include_site_packages, |
591 | - allowed_eggs_from_site_packages= |
592 | - allowed_eggs_from_site_packages) |
593 | + include_site_packages=None, allowed_eggs_from_site_packages=None, |
594 | + prefer_final=None): |
595 | + installer = Installer( |
596 | + dest, links, index, executable, always_unzip, path, newest, |
597 | + versions, use_dependency_links, allow_hosts=allow_hosts, |
598 | + include_site_packages=include_site_packages, |
599 | + allowed_eggs_from_site_packages=allowed_eggs_from_site_packages, |
600 | + prefer_final=prefer_final) |
601 | return installer.install(specs, working_set) |
602 | |
603 | |
604 | @@ -1075,11 +1079,11 @@ |
605 | executable=sys.executable, |
606 | path=None, newest=True, versions=None, allow_hosts=('*',), |
607 | include_site_packages=None, allowed_eggs_from_site_packages=None): |
608 | - installer = Installer(dest, links, index, executable, True, path, newest, |
609 | - versions, allow_hosts=allow_hosts, |
610 | - include_site_packages=include_site_packages, |
611 | - allowed_eggs_from_site_packages= |
612 | - allowed_eggs_from_site_packages) |
613 | + installer = Installer( |
614 | + dest, links, index, executable, True, path, newest, versions, |
615 | + allow_hosts=allow_hosts, |
616 | + include_site_packages=include_site_packages, |
617 | + allowed_eggs_from_site_packages=allowed_eggs_from_site_packages) |
618 | return installer.build(spec, build_ext) |
619 | |
620 | |
621 | @@ -1175,11 +1179,12 @@ |
622 | [f() for f in undo] |
623 | |
624 | def working_set(specs, executable, path, include_site_packages=None, |
625 | - allowed_eggs_from_site_packages=None): |
626 | + allowed_eggs_from_site_packages=None, prefer_final=None): |
627 | return install( |
628 | specs, None, executable=executable, path=path, |
629 | include_site_packages=include_site_packages, |
630 | - allowed_eggs_from_site_packages=allowed_eggs_from_site_packages) |
631 | + allowed_eggs_from_site_packages=allowed_eggs_from_site_packages, |
632 | + prefer_final=prefer_final) |
633 | |
634 | ############################################################################ |
635 | # Script generation functions |
636 | |
637 | === modified file 'src/zc/buildout/tests.py' |
638 | --- src/zc/buildout/tests.py 2010-08-07 00:12:52 +0000 |
639 | +++ src/zc/buildout/tests.py 2010-08-07 00:12:52 +0000 |
640 | @@ -3126,6 +3126,105 @@ |
641 | |
642 | """ |
643 | |
644 | +def buildout_prefer_final_build_system_option(): |
645 | + """ |
646 | +The prefer-final-build-system buildout option can be used for overriding |
647 | +the default preference for final distributions for recipes, buildout |
648 | +extensions, and buildout itself. |
649 | + |
650 | +Set up. This creates sdists for demorecipe 1.0 and 1.1b1, and for |
651 | +demoextension 1.0 and 1.1b1. |
652 | + |
653 | + >>> create_sample_recipe_sdists(sample_eggs) |
654 | + >>> create_sample_extension_sdists(sample_eggs) |
655 | + |
656 | +The default is prefer-final-build-system = true: |
657 | + |
658 | + >>> write('buildout.cfg', |
659 | + ... ''' |
660 | + ... [buildout] |
661 | + ... parts = demo |
662 | + ... find-links = %(link_server)s |
663 | + ... extensions = demoextension |
664 | + ... |
665 | + ... [demo] |
666 | + ... recipe = demorecipe |
667 | + ... ''' % globals()) |
668 | + |
669 | + >>> print system(buildout+' -v'), # doctest: +ELLIPSIS |
670 | + Installing ... |
671 | + Picked: demoextension = 1.0 |
672 | + ... |
673 | + Picked: demorecipe = 1.0 |
674 | + ... |
675 | + |
676 | +Here we see that the final versions of demorecipe and demoextension were used. |
677 | + |
678 | +We get the same behavior if we explicitly state that |
679 | +prefer-final-build-system = true. |
680 | + |
681 | + >>> write('buildout.cfg', |
682 | + ... ''' |
683 | + ... [buildout] |
684 | + ... parts = demo |
685 | + ... find-links = %(link_server)s |
686 | + ... extensions = demoextension |
687 | + ... prefer-final-build-system = true |
688 | + ... |
689 | + ... [demo] |
690 | + ... recipe = demorecipe |
691 | + ... ''' % globals()) |
692 | + |
693 | + >>> print system(buildout+' -v'), # doctest: +ELLIPSIS |
694 | + Installing ... |
695 | + Picked: demoextension = 1.0 |
696 | + ... |
697 | + Picked: demorecipe = 1.0 |
698 | + ... |
699 | + |
700 | +If we specify prefer-final-build-system = false, we'll get the newest |
701 | +distributions in the build system: |
702 | + |
703 | + >>> write('buildout.cfg', |
704 | + ... ''' |
705 | + ... [buildout] |
706 | + ... parts = demo |
707 | + ... find-links = %(link_server)s |
708 | + ... extensions = demoextension |
709 | + ... prefer-final-build-system = false |
710 | + ... |
711 | + ... [demo] |
712 | + ... recipe = demorecipe |
713 | + ... ''' % globals()) |
714 | + |
715 | + >>> print system(buildout+' -v'), # doctest: +ELLIPSIS |
716 | + Installing ... |
717 | + Picked: demoextension = 1.1b1 |
718 | + ... |
719 | + Picked: demorecipe = 1.1b1 |
720 | + ... |
721 | + |
722 | +We get an error if we specify anything but true or false: |
723 | + |
724 | + >>> write('buildout.cfg', |
725 | + ... ''' |
726 | + ... [buildout] |
727 | + ... parts = demo |
728 | + ... find-links = %(link_server)s |
729 | + ... extensions = demoextension |
730 | + ... prefer-final-build-system = no |
731 | + ... |
732 | + ... [demo] |
733 | + ... recipe = demorecipe |
734 | + ... ''' % globals()) |
735 | + |
736 | + >>> print system(buildout+' -v'), # doctest: +ELLIPSIS |
737 | + While: |
738 | + Initializing. |
739 | + Error: Invalid value for prefer-final-build-system option: no |
740 | + |
741 | + """ |
742 | + |
743 | def develop_with_modules(): |
744 | """ |
745 | Distribution setup scripts can import modules in the distribution directory: |
746 | @@ -3492,6 +3591,68 @@ |
747 | finally: |
748 | shutil.rmtree(tmp) |
749 | |
750 | +def create_sample_extension_sdists(dest): |
751 | + from zc.buildout.testing import write, mkdir |
752 | + name = 'demoextension' |
753 | + for version in ('1.0', '1.1b1'): |
754 | + tmp = tempfile.mkdtemp() |
755 | + try: |
756 | + write(tmp, 'README.txt', '') |
757 | + write(tmp, name + '.py', |
758 | + "def ext(buildout):\n" |
759 | + " pass\n" |
760 | + "def unload(buildout):\n" |
761 | + " pass\n" |
762 | + % locals()) |
763 | + write(tmp, 'setup.py', |
764 | + "from setuptools import setup\n" |
765 | + "setup(\n" |
766 | + " name = %(name)r,\n" |
767 | + " py_modules = [%(name)r],\n" |
768 | + " entry_points = {\n" |
769 | + " 'zc.buildout.extension': " |
770 | + "['ext = %(name)s:ext'],\n" |
771 | + " 'zc.buildout.unloadextension': " |
772 | + "['ext = %(name)s:unload'],\n" |
773 | + " },\n" |
774 | + " zip_safe=True, version=%(version)r,\n" |
775 | + " author='bob', url='bob', author_email='bob')\n" |
776 | + % locals()) |
777 | + zc.buildout.testing.sdist(tmp, dest) |
778 | + finally: |
779 | + shutil.rmtree(tmp) |
780 | + |
781 | +def create_sample_recipe_sdists(dest): |
782 | + from zc.buildout.testing import write, mkdir |
783 | + name = 'demorecipe' |
784 | + for version in ('1.0', '1.1b1'): |
785 | + tmp = tempfile.mkdtemp() |
786 | + try: |
787 | + write(tmp, 'README.txt', '') |
788 | + write(tmp, name + '.py', |
789 | + "import logging, os, zc.buildout\n" |
790 | + "class Demorecipe:\n" |
791 | + " def __init__(self, buildout, name, options):\n" |
792 | + " self.name, self.options = name, options\n" |
793 | + " def install(self):\n" |
794 | + " return ()\n" |
795 | + " def update(self):\n" |
796 | + " pass\n" |
797 | + % locals()) |
798 | + write(tmp, 'setup.py', |
799 | + "from setuptools import setup\n" |
800 | + "setup(\n" |
801 | + " name = %(name)r,\n" |
802 | + " py_modules = [%(name)r],\n" |
803 | + " entry_points = {'zc.buildout': " |
804 | + "['default = %(name)s:Demorecipe']},\n" |
805 | + " zip_safe=True, version=%(version)r,\n" |
806 | + " author='bob', url='bob', author_email='bob')\n" |
807 | + % locals()) |
808 | + zc.buildout.testing.sdist(tmp, dest) |
809 | + finally: |
810 | + shutil.rmtree(tmp) |
811 | + |
812 | def _write_eggrecipedemoneeded(tmp, minor_version, suffix=''): |
813 | from zc.buildout.testing import write |
814 | write(tmp, 'README.txt', '') |
815 | @@ -3639,37 +3800,33 @@ |
816 | |
817 | egg_parse = re.compile('([0-9a-zA-Z_.]+)-([0-9a-zA-Z_.]+)-py(\d[.]\d).egg$' |
818 | ).match |
819 | -def makeNewRelease(project, ws, dest): |
820 | +def makeNewRelease(project, ws, dest, version='99.99'): |
821 | dist = ws.find(pkg_resources.Requirement.parse(project)) |
822 | eggname, oldver, pyver = egg_parse( |
823 | os.path.basename(dist.location) |
824 | ).groups() |
825 | - dest = os.path.join(dest, "%s-99.99-py%s.egg" % (eggname, pyver)) |
826 | + dest = os.path.join(dest, "%s-%s-py%s.egg" % (eggname, version, pyver)) |
827 | if os.path.isfile(dist.location): |
828 | shutil.copy(dist.location, dest) |
829 | zip = zipfile.ZipFile(dest, 'a') |
830 | zip.writestr( |
831 | 'EGG-INFO/PKG-INFO', |
832 | zip.read('EGG-INFO/PKG-INFO').replace("Version: %s" % oldver, |
833 | - "Version: 99.99") |
834 | + "Version: %s" % version) |
835 | ) |
836 | zip.close() |
837 | else: |
838 | shutil.copytree(dist.location, dest) |
839 | info_path = os.path.join(dest, 'EGG-INFO', 'PKG-INFO') |
840 | info = open(info_path).read().replace("Version: %s" % oldver, |
841 | - "Version: 99.99") |
842 | + "Version: %s" % version) |
843 | open(info_path, 'w').write(info) |
844 | |
845 | - |
846 | -def updateSetup(test): |
847 | - zc.buildout.testing.buildoutSetUp(test) |
848 | - new_releases = test.globs['tmpdir']('new_releases') |
849 | - test.globs['new_releases'] = new_releases |
850 | +def getWorkingSetWithBuildoutEgg(test): |
851 | sample_buildout = test.globs['sample_buildout'] |
852 | eggs = os.path.join(sample_buildout, 'eggs') |
853 | |
854 | - # If the zc.buildout dist is a develo dist, convert it to a |
855 | + # If the zc.buildout dist is a develop dist, convert it to a |
856 | # regular egg in the sample buildout |
857 | req = pkg_resources.Requirement.parse('zc.buildout') |
858 | dist = pkg_resources.working_set.find(req) |
859 | @@ -3699,9 +3856,16 @@ |
860 | os.path.join(sample_buildout, 'bin')) |
861 | else: |
862 | ws = pkg_resources.working_set |
863 | + return ws |
864 | |
865 | +def updateSetup(test): |
866 | + zc.buildout.testing.buildoutSetUp(test) |
867 | + new_releases = test.globs['tmpdir']('new_releases') |
868 | + test.globs['new_releases'] = new_releases |
869 | + ws = getWorkingSetWithBuildoutEgg(test) |
870 | # now let's make the new releases |
871 | makeNewRelease('zc.buildout', ws, new_releases) |
872 | + makeNewRelease('zc.buildout', ws, new_releases, '100.0b1') |
873 | os.mkdir(os.path.join(new_releases, 'zc.buildout')) |
874 | if zc.buildout.easy_install.is_distribute: |
875 | makeNewRelease('distribute', ws, new_releases) |
876 | @@ -3710,6 +3874,13 @@ |
877 | makeNewRelease('setuptools', ws, new_releases) |
878 | os.mkdir(os.path.join(new_releases, 'setuptools')) |
879 | |
880 | +def bootstrapSetup(test): |
881 | + easy_install_SetUp(test) |
882 | + sample_eggs = test.globs['sample_eggs'] |
883 | + ws = getWorkingSetWithBuildoutEgg(test) |
884 | + makeNewRelease('zc.buildout', ws, sample_eggs) |
885 | + makeNewRelease('zc.buildout', ws, sample_eggs, '100.0b1') |
886 | + os.environ['bootstrap-testing-find-links'] = test.globs['link_server'] |
887 | |
888 | normalize_bang = ( |
889 | re.compile(re.escape('#!'+ |
890 | @@ -3952,12 +4123,13 @@ |
891 | if os.path.exists(bootstrap_py): |
892 | test_suite.append(doctest.DocFileSuite( |
893 | 'bootstrap.txt', |
894 | - setUp=easy_install_SetUp, |
895 | + setUp=bootstrapSetup, |
896 | tearDown=zc.buildout.testing.buildoutTearDown, |
897 | checker=renormalizing.RENormalizing([ |
898 | zc.buildout.testing.normalize_path, |
899 | zc.buildout.testing.normalize_endings, |
900 | zc.buildout.testing.normalize_script, |
901 | + zc.buildout.testing.normalize_egg_py, |
902 | normalize_bang, |
903 | (re.compile('Downloading.*setuptools.*egg\n'), ''), |
904 | (re.compile('options:'), 'Options:'), |
905 | |
906 | === modified file 'src/zc/buildout/update.txt' |
907 | --- src/zc/buildout/update.txt 1970-01-01 00:00:00 +0000 |
908 | +++ src/zc/buildout/update.txt 2010-08-07 00:12:52 +0000 |
909 | @@ -3,13 +3,14 @@ |
910 | |
911 | When a buildout is run, one of the first steps performed is to check |
912 | for updates to either zc.buildout or setuptools. To demonstrate this, |
913 | -we've creates some "new releases" of buildout and setuptools in a |
914 | +we've created some "new releases" of buildout and setuptools in a |
915 | new_releases folder: |
916 | |
917 | >>> ls(new_releases) |
918 | d setuptools |
919 | - setuptools-99.99-py2.4.egg |
920 | d zc.buildout |
921 | + - zc.buildout-100.0b1-pyN.N.egg |
922 | - zc.buildout-99.99-py2.4.egg |
923 | |
924 | Let's update the sample buildout.cfg to look in this area: |
925 | @@ -78,6 +79,11 @@ |
926 | zc.buildout 99.99 |
927 | setuptools 99.99 |
928 | |
929 | +Notice that, even though we have a newer beta version of zc.buildout |
930 | +available, the final "99.99" was selected. If you want to get non-final |
931 | +versions, specify a specific version in your buildout's versions section, |
932 | +or use the ``prefer-final-build-system = false`` discussed below. |
933 | + |
934 | Our buildout script's site.py has been updated to use the new eggs: |
935 | |
936 | >>> cat(sample_buildout, 'parts', 'buildout', 'site.py') |
937 | @@ -162,7 +168,7 @@ |
938 | setuptools 0.6 |
939 | |
940 | We also won't upgrade if the buildout script being run isn't in the |
941 | -buildouts bin directory. To see this we'll create a new buildout |
942 | +buildout's bin directory. To see this we'll create a new buildout |
943 | directory: |
944 | |
945 | >>> sample_buildout2 = tmpdir('sample_buildout2') |
946 | @@ -187,3 +193,33 @@ |
947 | Not upgrading because not running a local buildout command. |
948 | |
949 | >>> ls('bin') |
950 | + |
951 | +Notice that, as mentioned above, the ``prefer-final-build-system = |
952 | +false`` means that newer non-final versions of these dependencies are |
953 | +preferred. |
954 | + |
955 | + >>> cd(sample_buildout) |
956 | + >>> write(sample_buildout, 'buildout.cfg', |
957 | + ... """ |
958 | + ... [buildout] |
959 | + ... find-links = %(new_releases)s |
960 | + ... index = %(new_releases)s |
961 | + ... parts = show-versions |
962 | + ... develop = showversions |
963 | + ... prefer-final-build-system = false |
964 | + ... |
965 | + ... [show-versions] |
966 | + ... recipe = showversions |
967 | + ... """ % dict(new_releases=new_releases)) |
968 | + |
969 | + >>> print system(buildout), |
970 | + Getting distribution for 'zc.buildout'. |
971 | + Got zc.buildout 100.0b1. |
972 | + Upgraded: |
973 | + zc.buildout version 100.0b1, |
974 | + setuptools version 99.99; |
975 | + restarting. |
976 | + Develop: '/sample-buildout/showversions' |
977 | + Updating show-versions. |
978 | + zc.buildout 100.0b1 |
979 | + setuptools 99.99 |
Hi Gary,
I don't understand the need for both an option to bootstrap and one for
buildout. What happen if we only use the bootstrap.py option?
Is it that buildout/setuptools will upgrade itself whenever the buildout is
used? Or only the recipes? I think some clarifications of why one would use
the various options is needed to make this clearer.
Otherwise, everything looks good.