[Checkins] SVN: Sandbox/J1m/metarecipe/ meta-recipe helper

jim cvs-admin at zope.org
Thu May 31 16:30:39 UTC 2012


Log message for revision 126538:
  meta-recipe helper

Changed:
  U   Sandbox/J1m/metarecipe/buildout.cfg
  U   Sandbox/J1m/metarecipe/setup.py
  A   Sandbox/J1m/metarecipe/src/zc/metarecipe/
  A   Sandbox/J1m/metarecipe/src/zc/metarecipe/README.txt
  A   Sandbox/J1m/metarecipe/src/zc/metarecipe/__init__.py
  A   Sandbox/J1m/metarecipe/src/zc/metarecipe/testing.py
  A   Sandbox/J1m/metarecipe/src/zc/metarecipe/tests.py

-=-
Modified: Sandbox/J1m/metarecipe/buildout.cfg
===================================================================
--- Sandbox/J1m/metarecipe/buildout.cfg	2012-05-31 16:28:38 UTC (rev 126537)
+++ Sandbox/J1m/metarecipe/buildout.cfg	2012-05-31 16:30:35 UTC (rev 126538)
@@ -4,7 +4,7 @@
 
 [test]
 recipe = zc.recipe.testrunner
-eggs = 
+eggs = zc.metarecipe [test]
 
 [py]
 recipe = zc.recipe.egg

Modified: Sandbox/J1m/metarecipe/setup.py
===================================================================
--- Sandbox/J1m/metarecipe/setup.py	2012-05-31 16:28:38 UTC (rev 126537)
+++ Sandbox/J1m/metarecipe/setup.py	2012-05-31 16:30:35 UTC (rev 126538)
@@ -11,10 +11,10 @@
 # FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
-name, version = 'zc.', '0'
+name, version = 'zc.metarecipe', '0'
 
 install_requires = ['setuptools']
-extras_require = dict(test=['zope.testing'])
+extras_require = dict(test=['zope.testing', 'manuel'])
 
 entry_points = """
 """

Added: Sandbox/J1m/metarecipe/src/zc/metarecipe/README.txt
===================================================================
--- Sandbox/J1m/metarecipe/src/zc/metarecipe/README.txt	                        (rev 0)
+++ Sandbox/J1m/metarecipe/src/zc/metarecipe/README.txt	2012-05-31 16:30:35 UTC (rev 126538)
@@ -0,0 +1,200 @@
+============
+Meta-recipes
+============
+
+Buildout recipes provide resuable Python modukes for common
+configuration tasks. The most widely used recipes tend to provide
+low-level functions, like installing eggs or softwarte distributions,
+creating configuration files, and so on.  The normal recipe framework
+is fairly well suited to building these general components.
+
+Full-blown applications may require many, often tens, of parts.
+Defining the many parts that make up an application can be tedious and
+often entails a lot of repetition.  Buildout provides a number of
+mechanisms to avoid repetition, including merging of configuration
+files and macros, but these, while useful to an extent, don't scale
+very will.  Buildout isn't and shouldn't be a programming language.
+
+Meta-recipes allow us to bring Python to bear to provide higher-level
+abstractions for buildouts.
+
+A meta-recipe is a regular Python recipe that primarily operates by
+creating parts.  A meta recipe isn't merely a high level recipe.  It's
+a recipe that defers most of it's work to lower-level recipe by
+manipulating the buildout database.
+
+Unfortunatly, buildout doesn't yet provide a high-level API for
+creating parts.  It has a private low-level API which has been
+promoted to public (meaning it won't be broken by future release), and
+it's straightforward to write the needed high-level API, but it's
+annoying to repeat the high-level API in each meta recipe.
+
+This small package provides the high-lebel API needed for meta recipes
+and a simple testing framework.  It will be merged into a future
+buildout release.
+
+A `presentation at PyCon 2011
+<http://blip.tv/pycon-us-videos-2009-2010-2011/pycon-2011-deploying-applications-with-zc-buildout-4897770>`_
+described early work with meta recipes.
+
+A simple meta-recipe example
+============================
+
+Let's look at a fairly simple meta-recipe example.  First, consider a
+buildout configuration that builds a database deployment::
+
+  [buildout]
+  parts = ctl pack
+
+  [deployment]
+  recipe = zc.recipe.deployment
+  name = ample
+  user = zope
+
+  [ctl]
+  recipe = zc.recipe.rhrc
+  deployment = deployment
+  chkconfig = 345 99 10
+  parts = main index
+
+  [main]
+  recipe = zc.zodbrecipes:server
+  deployment = deployment
+  address = :8100
+  path = /var/databases/ample/main.fs
+  zeo.conf =
+     <zeo>
+        address ${:address}
+     </zeo>
+     %import zc.zlibstorage
+     <zlibstorage>
+       <filestorage>
+          path ${:path}
+       </filestorage>
+     </zlibstorage>
+
+  [pack]
+  recipe = zc.recipe.deployment:crontab
+  deployment = deployment
+  times = 1 2 * * 6
+  command = ${buildout:bin-directory}/zeopack -d3 -t00 ${main:address}
+
+.. -> low_level
+
+This buildout doesn't build software. Rather it builds configuration
+for deploying a database configuration using already-deployed
+software.  For the purpose of this document, however, the details are
+totally unimportant.
+
+Rather than crafting the configuration above every time, we can write
+a meta-recipe that crafts it for us.  We'll use our meta-recipe as
+follows::
+
+  [buildout]
+  parts = ample
+
+  [ample]
+  recipe = com.example.ample:db
+  path = /var/databases/ample/main.fs
+
+The idea here is that the meta recipe allows us to specify the minimal
+information necessary.  A meta-recipe often automates policies and
+assumptions that are application and organization dependent.  The
+example above assumes, for exampe, that we want to pack on Saturdays
+to to 3 days in the past.
+
+So now, let's see the meta recipe that automates this::
+
+  import zc.metarecipe
+
+  class Recipe(zc.metarecipe.Recipe):
+
+      def __init__(self, buildout, name, options):
+          super(Recipe, self).__init__(buildout, name, options)
+
+          self.parse('''
+              [deployment]
+              recipe = zc.recipe.deployment
+              name = %s
+              user = zope
+              ''' % name)
+
+          self['main'] = dict(
+              recipe = 'zc.zodbrecipes:server',
+              deployment = 'deployment',
+              address = ':8100',
+              path = options['path'],
+              **{
+                'zeo.conf': '''
+                  <zeo>
+                    address ${:address}
+                  </zeo>
+
+                  %import zc.zlibstorage
+
+                  <zlibstorage>
+                    <filestorage>
+                      path ${:path}
+                    </filestorage>
+                  </zlibstorage>
+                  '''}
+              )
+
+          self.parse('''
+              [pack]
+              recipe = zc.recipe.deployment:crontab
+              deployment = deployment
+              times = 1 2 * * 6
+              command =
+                ${buildout:bin-directory}/zeopack -d3 -t00 ${main:address}
+
+              [ctl]
+              recipe = zc.recipe.rhrc
+              deployment = deployment
+              chkconfig = 345 99 10
+              parts = main index
+              ''')
+
+.. -> source
+
+    >>> exec source
+
+Now, let's test it.  We'll test it without actually running
+buildout. Rather, we'll use a faux buildout provided by the
+zc.metarecipe.testing module.
+
+    >>> import zc.metarecipe.testing
+    >>> buildout = zc.metarecipe.testing.Buildout()
+
+    >>> _ = Recipe(buildout, 'ample', dict(path='/var/databases/ample/main.fs'))
+    [deployment]
+    name = ample
+    recipe = zc.recipe.deployment
+    user = zope
+    [main]
+    address = :8100
+    deployment = deployment
+    path = /var/databases/ample/main.fs
+    recipe = zc.zodbrecipes:server
+    zeo.conf = <zeo>
+                        address ${:address}
+                      </zeo>
+    <BLANKLINE>
+                      %import zc.zlibstorage
+    <BLANKLINE>
+                      <zlibstorage>
+                        <filestorage>
+                          path ${:path}
+                        </filestorage>
+                      </zlibstorage>
+    [ctl]
+    chkconfig = 345 99 10
+    deployment = deployment
+    parts = main index
+    recipe = zc.recipe.rhrc
+    [pack]
+    command = ${buildout:bin-directory}/zeopack -d3 -t00 ${main:address}
+    deployment = deployment
+    recipe = zc.recipe.deployment:crontab
+    times = 1 2 * * 6
+


Property changes on: Sandbox/J1m/metarecipe/src/zc/metarecipe/README.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: Sandbox/J1m/metarecipe/src/zc/metarecipe/__init__.py
===================================================================
--- Sandbox/J1m/metarecipe/src/zc/metarecipe/__init__.py	                        (rev 0)
+++ Sandbox/J1m/metarecipe/src/zc/metarecipe/__init__.py	2012-05-31 16:30:35 UTC (rev 126538)
@@ -0,0 +1,24 @@
+import ConfigParser, cStringIO, textwrap
+
+class Recipe(object):
+
+    def __init__(self, buildout, name, options):
+        self.buildout = buildout
+        self.name = name
+        self.options = options
+
+    def install(self):
+        return ()
+
+    update = install
+
+    def __setitem__(self, name, data):
+        self.buildout._raw[name] = data
+        self.buildout[name]
+
+    def parse(self, data):
+        parser = ConfigParser.RawConfigParser()
+        parser.readfp(cStringIO.StringIO(textwrap.dedent(data)))
+
+        for section in parser.sections():
+            self[section] = dict(parser.items(section))


Property changes on: Sandbox/J1m/metarecipe/src/zc/metarecipe/__init__.py
___________________________________________________________________
Added: svn:keywords
   + Id
Added: svn:eol-style
   + native

Added: Sandbox/J1m/metarecipe/src/zc/metarecipe/testing.py
===================================================================
--- Sandbox/J1m/metarecipe/src/zc/metarecipe/testing.py	                        (rev 0)
+++ Sandbox/J1m/metarecipe/src/zc/metarecipe/testing.py	2012-05-31 16:30:35 UTC (rev 126538)
@@ -0,0 +1,11 @@
+
+
+class Buildout:
+
+    def __init__(self):
+        self._raw = {}
+
+    def __getitem__(self, name):
+        print "[%s]" % name
+        for k, v in sorted(self._raw[name].items()):
+            print "%s = %s" % (k, v.replace("\n", "\n  ").strip())


Property changes on: Sandbox/J1m/metarecipe/src/zc/metarecipe/testing.py
___________________________________________________________________
Added: svn:keywords
   + Id
Added: svn:eol-style
   + native

Added: Sandbox/J1m/metarecipe/src/zc/metarecipe/tests.py
===================================================================
--- Sandbox/J1m/metarecipe/src/zc/metarecipe/tests.py	                        (rev 0)
+++ Sandbox/J1m/metarecipe/src/zc/metarecipe/tests.py	2012-05-31 16:30:35 UTC (rev 126538)
@@ -0,0 +1,28 @@
+##############################################################################
+#
+# Copyright (c) 2010 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+from zope.testing import setupstack
+import manuel.capture
+import manuel.doctest
+import manuel.testing
+import unittest
+
+def test_suite():
+    return unittest.TestSuite((
+        manuel.testing.TestSuite(
+            manuel.doctest.Manuel() + manuel.capture.Manuel(),
+            'README.txt',
+            setUp=setupstack.setUpDirectory, tearDown=setupstack.tearDown,
+            ),
+        ))
+


Property changes on: Sandbox/J1m/metarecipe/src/zc/metarecipe/tests.py
___________________________________________________________________
Added: svn:keywords
   + Id
Added: svn:eol-style
   + native



More information about the checkins mailing list