[Checkins] SVN: zc.buildout/trunk/ Added support for repeatable buildouts by allowing egg versions to

Jim Fulton jim at zope.com
Tue Mar 6 14:23:51 EST 2007


Log message for revision 73017:
  Added support for repeatable buildouts by allowing egg versions to
  be specified in a versions section.
  
  Changed the log format for picked versions.
  

Changed:
  U   zc.buildout/trunk/CHANGES.txt
  U   zc.buildout/trunk/src/zc/buildout/buildout.py
  U   zc.buildout/trunk/src/zc/buildout/buildout.txt
  U   zc.buildout/trunk/src/zc/buildout/easy_install.py
  U   zc.buildout/trunk/src/zc/buildout/easy_install.txt
  A   zc.buildout/trunk/src/zc/buildout/repeatable.txt
  U   zc.buildout/trunk/src/zc/buildout/tests.py

-=-
Modified: zc.buildout/trunk/CHANGES.txt
===================================================================
--- zc.buildout/trunk/CHANGES.txt	2007-03-06 18:36:09 UTC (rev 73016)
+++ zc.buildout/trunk/CHANGES.txt	2007-03-06 19:23:50 UTC (rev 73017)
@@ -17,12 +17,15 @@
 Change History
 **************
 
-1.0.0b21 (2007-03-??)
+1.0.0b21 (2007-03-06)
 =====================
 
 Feature Changes
 ---------------
 
+- Added support for repeatable buildouts by allowing egg versions to
+  be specified in a versions section.
+
 - The easy_install module install and build functions now accept a
   versions argument that supplied to mapping from project name to
   version numbers.  This can be used to fix version numbers for

Modified: zc.buildout/trunk/src/zc/buildout/buildout.py
===================================================================
--- zc.buildout/trunk/src/zc/buildout/buildout.py	2007-03-06 18:36:09 UTC (rev 73016)
+++ zc.buildout/trunk/src/zc/buildout/buildout.py	2007-03-06 19:23:50 UTC (rev 73017)
@@ -142,6 +142,10 @@
             options['newest'] = newest
         self.newest = newest == 'true'
 
+        versions = options.get('versions')
+        if versions:
+            zc.buildout.easy_install.default_versions(dict(self[versions]))
+
     def _buildout_path(self, *names):
         return os.path.join(self._buildout_dir, *names)
 

Modified: zc.buildout/trunk/src/zc/buildout/buildout.txt
===================================================================
--- zc.buildout/trunk/src/zc/buildout/buildout.txt	2007-03-06 18:36:09 UTC (rev 73016)
+++ zc.buildout/trunk/src/zc/buildout/buildout.txt	2007-03-06 19:23:50 UTC (rev 73017)
@@ -1598,10 +1598,9 @@
     >>> print system(buildout+' -v'),
     zc.buildout.easy_install: Installing ['zc.buildout', 'setuptools']
     zc.buildout.easy_install: We have a develop egg for zc.buildout
-    zc.buildout.easy_install: Picked version for zc.buildout = 1.0.0
     zc.buildout.easy_install: We have the best distribution that satisfies
     setuptools
-    zc.buildout.easy_install: Picked version for setuptools = 0.6
+    zc.buildout.easy_install.picked: setuptools = 0.6
     <BLANKLINE>
     Configuration data:
     [buildout]

Modified: zc.buildout/trunk/src/zc/buildout/easy_install.py
===================================================================
--- zc.buildout/trunk/src/zc/buildout/easy_install.py	2007-03-06 18:36:09 UTC (rev 73016)
+++ zc.buildout/trunk/src/zc/buildout/easy_install.py	2007-03-06 19:23:50 UTC (rev 73017)
@@ -31,6 +31,7 @@
 default_index_url = os.environ.get('buildout-testing-index-url')
 
 logger = logging.getLogger('zc.buildout.easy_install')
+picked = logging.getLogger('zc.buildout.easy_install.picked')
 
 url_match = re.compile('[a-z0-9+.-]+://').match
 
@@ -348,10 +349,11 @@
 
         # Check whether we picked a version and, if we did, report it:
         if not (
-            len(requirement.specs) == 1 and requirement.specs[0][0] == '=='
+            dist.precedence == pkg_resources.DEVELOP_DIST
+            or
+            (len(requirement.specs) == 1 and requirement.specs[0][0] == '==')
             ):
-            logger.debug('Picked version for %s = %s',
-                         dist.project_name, dist.version)
+            picked.debug('%s = %s', dist.project_name, dist.version)
 
         return dist
 

Modified: zc.buildout/trunk/src/zc/buildout/easy_install.txt
===================================================================
--- zc.buildout/trunk/src/zc/buildout/easy_install.txt	2007-03-06 18:36:09 UTC (rev 73016)
+++ zc.buildout/trunk/src/zc/buildout/easy_install.txt	2007-03-06 19:23:50 UTC (rev 73017)
@@ -247,15 +247,15 @@
     zc.buildout.easy_install DEBUG
       We have the best distribution that satisfies
     demo
+    zc.buildout.easy_install.picked DEBUG
+      demo = 0.3
     zc.buildout.easy_install DEBUG
-      Picked version for demo = 0.3
-    zc.buildout.easy_install DEBUG
       Getting required demoneeded
     zc.buildout.easy_install DEBUG
       We have the best distribution that satisfies
     demoneeded
-    zc.buildout.easy_install DEBUG
-      Picked version for demoneeded = 1.1
+    zc.buildout.easy_install.picked DEBUG
+      demoneeded = 1.1
 
     >>> handler.uninstall()
     >>> logging.getLogger('zc.buildout.easy_install').propagate = True

Added: zc.buildout/trunk/src/zc/buildout/repeatable.txt
===================================================================
--- zc.buildout/trunk/src/zc/buildout/repeatable.txt	2007-03-06 18:36:09 UTC (rev 73016)
+++ zc.buildout/trunk/src/zc/buildout/repeatable.txt	2007-03-06 19:23:50 UTC (rev 73017)
@@ -0,0 +1,168 @@
+Repeatable buildouts: controlling eggs used
+===========================================
+
+One of the goals of zc.buildout is to provide enough control to make
+buildouts repeatable.  It should be possible to check the buildout
+configuration files for a project into a version control system and
+later use the checked in files to get the same buildout, subject to
+changes in the environment outside the buildout.
+
+An advantage of using Python eggs is that depenencies of eggs used are
+automatically determined and used.  The automatic inclusion of
+depenent distributions is at odds with the goal of repeatable
+buildouts.
+
+To support repeatable buildouts, a versions section can be created
+with options for each distribution name whos version is to be fixed.
+The section can then be specified via the buildout versions option.
+
+To see how this works, we'll create two versions of a recipe egg:
+
+    >>> mkdir('recipe')
+    >>> write('recipe', 'recipe.py',
+    ... '''
+    ... class Recipe:
+    ...     def __init__(*a): pass
+    ...     def install(self):
+    ...         print 'recipe v1'
+    ...         return ()
+    ...     update = install
+    ... ''')
+
+    >>> write('recipe', 'setup.py',
+    ... '''
+    ... from setuptools import setup
+    ... setup(name='spam', version='1', py_modules=['recipe'],
+    ...       entry_points={'zc.buildout': ['default = recipe:Recipe']},
+    ...       )
+    ... ''')
+
+    >>> write('recipe', 'README', '')
+
+    >>> print system(buildout+' setup recipe bdist_egg'), # doctest: +ELLIPSIS
+    buildout: Running setup script recipe/setup.py
+    ...
+
+    >>> rmdir('recipe', 'build')
+
+    >>> write('recipe', 'recipe.py',
+    ... '''
+    ... class Recipe:
+    ...     def __init__(*a): pass
+    ...     def install(self):
+    ...         print 'recipe v2'
+    ...         return ()
+    ...     update = install
+    ... ''')
+
+    >>> write('recipe', 'setup.py',
+    ... '''
+    ... from setuptools import setup
+    ... setup(name='spam', version='2', py_modules=['recipe'],
+    ...       entry_points={'zc.buildout': ['default = recipe:Recipe']},
+    ...       )
+    ... ''')
+
+
+    >>> print system(buildout+' setup recipe bdist_egg'), # doctest: +ELLIPSIS
+    buildout: Running setup script recipe/setup.py
+    ...
+
+and we'll configure a buildout to use it:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... parts = foo
+    ... find-links = %s
+    ...
+    ... [foo]
+    ... recipe = spam
+    ... ''' % join('recipe', 'dist'))
+
+If we run the buildout, it will use version 2:
+
+    >>> print system(buildout),
+    zc.buildout.easy_install: Getting new distribution for spam
+    zc.buildout.easy_install: Got spam 2
+    buildout: Installing foo
+    recipe v2
+
+We can specify a versions section that lists our recipe and name it in
+the buildout section:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... parts = foo
+    ... find-links = %s
+    ... versions = release-1
+    ...
+    ... [release-1]
+    ... spam = 1
+    ... eggs = 2.2
+    ...
+    ... [foo]
+    ... recipe = spam
+    ... ''' % join('recipe', 'dist'))
+
+Here we created a release-1 section listing the version 1 for the spam
+distribution.  We told the buildout to use it by specifying release-1
+as in the versions option.
+
+Now, if we run the buildout, we'll use version 1 of the spam recipe:
+
+    >>> print system(buildout),
+    zc.buildout.easy_install: Getting new distribution for spam==1
+    zc.buildout.easy_install: Got spam 1
+    buildout: Uninstalling foo
+    buildout: Installing foo
+    recipe v1
+
+Running the buildout in verbose mode will help us get information
+about versions used. If we run the buildout in verbose mode without
+specifying a versions section:
+
+    >>> print system(buildout+' buildout:versions= -v'), # doctest: +ELLIPSIS
+    zc.buildout.easy_install: Installing ['zc.buildout', 'setuptools']
+    zc.buildout.easy_install: We have a develop egg for zc.buildout
+    zc.buildout.easy_install: We have the best distribution that satisfies
+    setuptools
+    zc.buildout.easy_install.picked: setuptools = 0.6
+    zc.buildout.easy_install: Installing ['spam']
+    zc.buildout.easy_install: We have the best distribution that satisfies
+    spam
+    zc.buildout.easy_install.picked: spam = 2
+    ...
+    buildout: Uninstalling foo
+    buildout: Installing foo
+    recipe v2
+
+We'll get output that includes lines that tell us what versions
+buildout chose a for us, like::
+
+    zc.buildout.easy_install.picked: spam = 2
+
+This allows us to discover versions that are picked dynamically, so
+that we can fix them in a versions section.
+
+If we run the buildout with the versions section:
+
+    >>> print system(buildout+' -v'), # doctest: +ELLIPSIS
+    zc.buildout.easy_install: Installing ['zc.buildout', 'setuptools']
+    zc.buildout.easy_install: We have a develop egg for zc.buildout
+    zc.buildout.easy_install: We have the best distribution that satisfies
+    setuptools
+    zc.buildout.easy_install.picked: setuptools = 0.6
+    zc.buildout.easy_install: Installing ['spam']
+    zc.buildout.easy_install: We have the best distribution that satisfies
+    spam==1
+    ...
+    buildout: Uninstalling foo
+    buildout: Installing foo
+    recipe v1
+
+We won't get output for the spam distribution, which we didn't pick,
+but we will get output for setuptools, which we didn't specify
+versions for.
+


Property changes on: zc.buildout/trunk/src/zc/buildout/repeatable.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: zc.buildout/trunk/src/zc/buildout/tests.py
===================================================================
--- zc.buildout/trunk/src/zc/buildout/tests.py	2007-03-06 18:36:09 UTC (rev 73016)
+++ zc.buildout/trunk/src/zc/buildout/tests.py	2007-03-06 19:23:50 UTC (rev 73017)
@@ -1420,7 +1420,7 @@
     import zc.buildout.testselectingpython
     suite = unittest.TestSuite((
         doctest.DocFileSuite(
-            'buildout.txt', 'runsetup.txt',
+            'buildout.txt', 'runsetup.txt', 'repeatable.txt',
             setUp=zc.buildout.testing.buildoutSetUp,
             tearDown=zc.buildout.testing.buildoutTearDown,
             checker=renormalizing.RENormalizing([
@@ -1436,8 +1436,8 @@
                 'zc.buildout.egg'),
                (re.compile('creating \S*setup.cfg'), 'creating setup.cfg'),
                (re.compile('hello\%ssetup' % os.path.sep), 'hello/setup'),
-               (re.compile('Picked version for (\S+) = \S+'),
-                'Picked version for \\1 = V.V'),
+               (re.compile('zc.buildout.easy_install.picked: (\S+) = \S+'),
+                'picked \\1 = V.V'),
                ])
             ),
 



More information about the Checkins mailing list