Merge lp:~gary/zc.buildout/betafix6 into lp:zc.buildout

Proposed by Gary Poster
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
Reviewer Review Type Date Requested Status
Francis J. Lacoste (community) code Approve
Review via email: mp+31996@code.launchpad.net

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.

To post a comment you must log in.
Revision history for this message
Francis J. Lacoste (flacoste) wrote :

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.

review: Needs Information (code)
Revision history for this message
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.

review: Approve (code)
lp:~gary/zc.buildout/betafix6 updated
564. By Gary Poster

clarify that --accept-early-release must be accompanied with prefer-final-build-system= false.

Revision history for this message
Gary Poster (gary) wrote :

Hey Francis. What do you think of this approach to addressing your concerns?

http://pastebin.ubuntu.com/479699/

Essentially, you only have to use --accept-early-release when calling the bootstrap. This flag is remembered thanks to code scribbled in the buildout script. When you rerun bootstrap without that argument it goes back to the usual behavior.

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.

Revision history for this message
Francis J. Lacoste (flacoste) wrote :

I like that!

Revision history for this message
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://code.edge.launchpad.net/~gary/zc.buildout/betafix8/+merge/33077 .

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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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

Subscribers

People subscribed via source and target branches

to all changes: