<?xml version="1.0" ?>
<?xml-stylesheet href="" type="text/css"?>

<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:dc="http://purl.org/dc/elements/1.1/"
         xmlns:dcterms="http://purl.org/dc/terms/"
         xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
         xmlns:rss="http://purl.org/rss/1.0/"
         xmlns:content="http://purl.org/rss/1.0/modules/content/">

    <rss:channel rdf:about="http://maurits.vanrees.org/weblog">

        <rss:title>Weblog</rss:title>
        <rss:link>http://maurits.vanrees.org/weblog</rss:link>

        
        <rss:description>Weblog RSS 1.0 feed.</rss:description>

        <rss:image rdf:resource="http://maurits.vanrees.org/logo.png"/>

        <sy:updatePeriod>daily</sy:updatePeriod>
        <sy:updateFrequency>1</sy:updateFrequency>

        <rss:items>
            <rdf:Seq>
                
                <rdf:li rdf:resource="http://maurits.vanrees.org/weblog/archive/2008/05/omelette-now-even-tastier"/>
                
                
                <rdf:li rdf:resource="http://maurits.vanrees.org/weblog/archive/2008/05/grok-sprint-wrapup-sunday"/>
                
                
                <rdf:li rdf:resource="http://maurits.vanrees.org/weblog/archive/2008/04/a-grok-tour-and-todo"/>
                
                
                <rdf:li rdf:resource="http://maurits.vanrees.org/weblog/archive/2008/04/first-impressions-of-ubuntu-hardy-heron"/>
                
                
                <rdf:li rdf:resource="http://maurits.vanrees.org/weblog/archive/2008/01/missing-files-from-eggs"/>
                
                
                <rdf:li rdf:resource="http://maurits.vanrees.org/weblog/archive/2008/01/skin-switching-with-pre-traversal"/>
                
                
                <rdf:li rdf:resource="http://maurits.vanrees.org/weblog/archive/2008/01/switch-your-skin-if-you-are-logged-in"/>
                
                
                <rdf:li rdf:resource="http://maurits.vanrees.org/weblog/archive/2008/01/switch-your-skin-based-on-the-url"/>
                
                
                <rdf:li rdf:resource="http://maurits.vanrees.org/weblog/archive/2008/01/easily-creating-repeatable-buildouts"/>
                
                
                <rdf:li rdf:resource="http://maurits.vanrees.org/weblog/archive/2008/01/creating-repeatable-buildouts"/>
                
                
                <rdf:li rdf:resource="http://maurits.vanrees.org/weblog/archive/2007/11/search-forms-with-zope-formlib-and-batching"/>
                
                
                <rdf:li rdf:resource="http://maurits.vanrees.org/weblog/archive/2007/11/american-oil-consumption"/>
                
                
                <rdf:li rdf:resource="http://maurits.vanrees.org/weblog/archive/2007/10/plone-3-0-and-instancemanager"/>
                
                
                <rdf:li rdf:resource="http://maurits.vanrees.org/weblog/archive/2007/10/getpaid-making-money-with-plone"/>
                
                
                <rdf:li rdf:resource="http://maurits.vanrees.org/weblog/archive/2007/10/untested-code-is-broken-code"/>
                
            </rdf:Seq>
        </rss:items>
    </rss:channel>

    <rss:image rdf:about="http://maurits.vanrees.org/logo.png">
        <rss:title>Weblog</rss:title>
        <rss:link>http://maurits.vanrees.org/weblog</rss:link>
        <rss:url>http://maurits.vanrees.org/logo.png</rss:url>
    </rss:image>

    

    <rss:item rdf:about="http://maurits.vanrees.org/weblog/archive/2008/05/omelette-now-even-tastier">

        <rss:title>Omelette: now even tastier!</rss:title>

        <rss:link>http://maurits.vanrees.org/weblog/archive/2008/05/omelette-now-even-tastier</rss:link>       

        <rss:description>collective.recipe.omelette is a must.</rss:description>

        <content:encoded>
          <![CDATA[
          <p>David Glick has just released <a class="reference" href="http://pypi.python.org/pypi/collective.recipe.omelette">collective.recipe.omelette</a> version
0.5.  You have <em>got</em> to try it.  As you may know, it makes a
<tt class="docutils literal"><span class="pre">parts/omelette/</span></tt> directory with links to all the various eggs that
you have in your buildout.  With version 0.5 it can do the same for
Products.  And you can point it to some more packages.  In a standard
Plone buildout you would have this part:</p>
<pre class="literal-block">
[omelette]
recipe = collective.recipe.omelette
eggs = ${instance:eggs}
products = ${instance:products}
packages = ${zope2:location}/lib/python ./
</pre>
<p>Don't forget the <tt class="docutils literal"><span class="pre">./</span></tt> at the end.  Note: the <tt class="docutils literal"><span class="pre">README.txt</span></tt> of the
recipe mentions <tt class="docutils literal"><span class="pre">modules</span></tt> instead of <tt class="docutils literal"><span class="pre">packages</span></tt> but that is a
typo.  Fixed in subversion.</p>
<p>I especially like it that with this configuration you can look in
<tt class="docutils literal"><span class="pre">parts/omelette/Products</span></tt> and have links to the exact same Products
that your zope instance will be using, whether a Product is in an egg,
in the <tt class="docutils literal"><span class="pre">productsdistros/checkouts</span></tt> directory, in <tt class="docutils literal"><span class="pre">parts/plone</span></tt> or
in the Zope 2 Products dir.  That is sweet.</p>
<p>Thanks a lot David!</p>

          ]]>
        </content:encoded>        

        <dc:date>2008-05-29T11:40:34+02:00</dc:date>

        <dcterms:modified>2008-05-29T11:40:34+02:00</dcterms:modified>

        <dc:creator>Maurits van Rees</dc:creator>

        

        
            <dc:subject>plone</dc:subject>
        

    </rss:item>

    
    

    <rss:item rdf:about="http://maurits.vanrees.org/weblog/archive/2008/05/grok-sprint-wrapup-sunday">

        <rss:title>Grok sprint wrapup Sunday</rss:title>

        <rss:link>http://maurits.vanrees.org/weblog/archive/2008/05/grok-sprint-wrapup-sunday</rss:link>       

        <rss:description>I will just briefly list what has been done.</rss:description>

        <content:encoded>
          <![CDATA[
          <ul class="simple">
<li>Jasper and Reinout finished work on traversable stuff.</li>
<li>We have ordered containers.</li>
<li>Peter and Christian Klinger worked on caching response headers.</li>
<li>The grok.url method got cleaned up.</li>
<li>In grok.require you can point to a Permission class.</li>
<li>A lot got done for Relational Database integration with SQLAlchemy,
without actually needing a lot of code.</li>
<li>We have a sample implementation for a BREAD/CRUD application; will
be checked into the grokapps subversion section.</li>
<li>We worked on KSS integration.</li>
<li>We talked about resource directories and the static directory.</li>
<li>Peter made a sample application and tutorial about skins and layers.</li>
<li>Philipp released grokcore.component and merged the needed changes to
core grok.</li>
<li>Wim made a mockup for the Grok homepage.</li>
<li>A lot of documentation was written.  Automation is done using
grokdocs.</li>
<li>z3c.testsetup/grok.testing was added by Uli.</li>
<li>&quot;Zope 2 stuff&quot; was worked on by Godefroid and Eric.  So five.grok.</li>
<li>JW and Philipp worked on martian directives.  Three merges need to
happen, which we will work on now.  Makes it easier to write new
directives and easier to get information from directives.  All
existing third party grokkers will then not more work anymore; we
feel it is still early enough to do this, but the merge should
happen sooner rather than later.</li>
<li>Christian Theuni worked on the testrunner and the zodb.</li>
</ul>

          ]]>
        </content:encoded>        

        <dc:date>2008-05-04T16:43:53+02:00</dc:date>

        <dcterms:modified>2008-05-04T16:43:53+02:00</dcterms:modified>

        <dc:creator>Maurits van Rees</dc:creator>

        

        
            <dc:subject>grok</dc:subject>
        
        
            <dc:subject>plone</dc:subject>
        

    </rss:item>

    
    

    <rss:item rdf:about="http://maurits.vanrees.org/weblog/archive/2008/04/a-grok-tour-and-todo">

        <rss:title>A Grok Tour and Todo</rss:title>

        <rss:link>http://maurits.vanrees.org/weblog/archive/2008/04/a-grok-tour-and-todo</rss:link>       

        <rss:description>Welcome to the Grokkerdam sprint!</rss:description>

        <content:encoded>
          <![CDATA[
          <p>The <a class="reference" href="http://wiki.zope.org/grok/GrokkerdamSprint">Grokkerdam sprint</a> has just started in Rotterdam.  Martijn gave
a big introduction to Grok, throwing in things that can be done in the
Sprint, and with comments by the audience.</p>
<div class="section" id="some-core-grok-concepts">
<h3><a name="some-core-grok-concepts">Some core Grok concepts</a></h3>
<ul class="simple">
<li>DRY: Don't repeat yourself.  By not needing to add code to lots of
files, you save time and errors.</li>
<li>Convention over configuration: sensible defaults.  You can more
easily look at other people's code and still understand where
everything is.</li>
<li>We have &quot;grokkers&quot; that deduce declarations from python code.  So
hardly any zope 3 configuration (zcml) is necessary.</li>
</ul>
</div>
<div class="section" id="grokking">
<h3><a name="grokking">Grokking</a></h3>
<p>Grokking is triggered from zcml, with the grok directive.  This should
be the only zcml that is needed.  It scans modules in your code for
classes that subclass grok's base classes.  Grok then registers these
components with the Zope Component Architecture (ZCA).</p>
<p>If you follow standard patterns, you can leave out grok directives
(grok.name, grok.require, etc) from your code, but if you need more
control, you can use them.</p>
</div>
<div class="section" id="storage">
<h3><a name="storage">Storage</a></h3>
<p><tt class="docutils literal"><span class="pre">grok.Model</span></tt> is usually your base class.  Very light weight.  It
should be contained in a class with <tt class="docutils literal"><span class="pre">grok.Container</span></tt> as base class.
There is no ordered container class yet; we will add it to the todo
list of the sprint.</p>
</div>
<div class="section" id="traversal">
<h3><a name="traversal">Traversal</a></h3>
<p>Traversal in Grok is very easy.  There is of course the default
traversal that just works.  But if you need more control, you add a
<tt class="docutils literal"><span class="pre">traverse</span></tt> method to your model.  This can instantiate virtual
objects on the fly.</p>
<p>You can also use <tt class="docutils literal"><span class="pre">grok.Traverser</span></tt> to implement custom behaviour for
someone else's context.</p>
</div>
<div class="section" id="sites">
<h3><a name="sites">Sites</a></h3>
<p>Sites is Zope 3 is a place to store local utilities and tools.  Grok
has <tt class="docutils literal"><span class="pre">grok.Site</span></tt> for this.  As todo we may want to add locally
defined views and adapters.  And having non-persistent local utilities
would be useful as well.  And we want to be able to install local
utilities in an existing site, instead of only in a new site, without
hairy upgrade code.</p>
<p><tt class="docutils literal"><span class="pre">grok.Application</span></tt> is a special kind of <tt class="docutils literal"><span class="pre">grok.Site</span></tt>.</p>
<p>Todo: look at GenericSetup to make upgrades easier.</p>
<p><tt class="docutils literal"><span class="pre">grok.Indexes</span></tt> makes working with the catalog easier.  Todo:
upgrading indexes in an existing site should be possible.</p>
</div>
<div class="section" id="components">
<h3><a name="components">Components</a></h3>
<p><tt class="docutils literal"><span class="pre">grokcore.component</span></tt> has several components you can use, also in
plain Zope 3:</p>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">grok.Adapter</span></tt></li>
<li><tt class="docutils literal"><span class="pre">grok.GlobalUtility</span></tt> for looking up e.g. the global email sending
utility.</li>
<li><tt class="docutils literal"><span class="pre">grok.MultiAdapter</span></tt> if you need to adapt more than just one
context (for which you would use <tt class="docutils literal"><span class="pre">grok.Context</span></tt>.  Not used a lot
currently.</li>
<li><tt class="docutils literal"><span class="pre">&#64;grok.subscribe</span></tt> is a decorator for subscribing to zope 3 events</li>
</ul>
<p>Todo: set up caching for views.</p>
</div>
<div class="section" id="miscellaneous-other-utilities">
<h3><a name="miscellaneous-other-utilities">Miscellaneous other utilities</a></h3>
<p>Using persistance:</p>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">grok.LocalUtility</span></tt></li>
<li><tt class="docutils literal"><span class="pre">grok.Annotation</span></tt>: you don't need to mess around with own
generated keys anymore.</li>
</ul>
</div>
<div class="section" id="views">
<h3><a name="views">Views</a></h3>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">grok.View</span></tt>: the most magic of the grok base classes, as we wanted
to make this really simple.  There is the <tt class="docutils literal"><span class="pre">url</span></tt> method which you
can give some parameters (optional context and optional string for
an alternative view).  Todo: explore keyword arguments for these
parameters.  And explore improving flash messages (compare with
Plone portal status message), which does not always show in
combination with redirection.</li>
<li><tt class="docutils literal"><span class="pre">grok.Skin</span></tt>: this is just a name and a single layer
(<tt class="docutils literal"><span class="pre">grok.Layer</span></tt>) that is associated with it.  <tt class="docutils literal"><span class="pre">grok.Layer</span></tt> is just
an interface; you can use inheritance to combine layers.  Todo: more
skin based control of what views exist.  From a security perspective
it is not nice that anyone can just add e.g. <tt class="docutils literal"><span class="pre">&#64;&#64;contents</span></tt> and see
the ZMI.  We need to make that easy (grokking it).</li>
<li><tt class="docutils literal"><span class="pre">grok.GrokTemplate</span></tt>: ugly name, needs more implementation.  Some
integration to use e.g. Genshi instead of Zope page templates.
Todo: write Jinja (from Django) integration and other template
languages.</li>
<li><tt class="docutils literal"><span class="pre">grok.ViewletManager</span></tt>, <tt class="docutils literal"><span class="pre">grok.Viewlet</span></tt>: You register viewlets
(html snippets) for a viewlet manager.  In zope 3 you need to do
quite a bit of stuff to set up viewlets and viewlet managers.  Grok
of course makes that easier.  Having viewlets available at a
specific url is good for caching; the Lovely guys have done
something for this.  Todo: look at <tt class="docutils literal"><span class="pre">z3c.traverser</span></tt> for maybe
making that easier and default.  KSS (or any Ajax) likes viewlets.
Todo: viewlet documentation.</li>
</ul>
</div>
<div class="section" id="alternative-views">
<h3><a name="alternative-views">Alternative views</a></h3>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">grok.XMLRPC</span></tt></li>
<li><tt class="docutils literal"><span class="pre">grok.REST</span></tt></li>
<li><tt class="docutils literal"><span class="pre">grok.RESTProtocol</span></tt></li>
<li><tt class="docutils literal"><span class="pre">grok.JSON</span></tt></li>
</ul>
</div>
<div class="section" id="security">
<h3><a name="security">Security</a></h3>
<p>Security is all view related.</p>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">grok.Permission</span></tt> is used to define permissions.  The
<tt class="docutils literal"><span class="pre">grok.require</span></tt> directive is used to require a permission.  Todo:
see if we can refer to classes instead of strings in
<tt class="docutils literal"><span class="pre">grok.require</span></tt>.</li>
<li>Todo: default authentication UI.  With Zope 2 you have the
<tt class="docutils literal"><span class="pre">acl_users</span></tt>.  With Grok we currently ask people to roll their own
code.  There is a good base in Zope 3 to use.</li>
<li>Todo: authorization APIs.</li>
<li>Todo: model-level security instead of only on views.  You can give
local permissions.  But security checks are currently only be done
on views.  We threw the object checks out as it is a pain to work
with, but we can look into making this easier.  The zope security is
very powerful.</li>
</ul>
</div>
<div class="section" id="formlib">
<h3><a name="formlib">Formlib</a></h3>
<p><tt class="docutils literal"><span class="pre">zope.formlib</span></tt> based forms.</p>
<ul class="simple">
<li>Use <tt class="docutils literal"><span class="pre">grok.Form</span></tt> as base.</li>
<li><tt class="docutils literal"><span class="pre">grok.EditForm</span></tt> uses the schema of your class.  The standard
template is pretty ugly though and does not integrate nicely with
your UI.  Todo: better templates for forms.  Viewlets might be handy
here.</li>
<li><tt class="docutils literal"><span class="pre">grok.DisplayForm</span></tt> just displays stuff.</li>
<li>Todo: <tt class="docutils literal"><span class="pre">z3c.form</span></tt> support.  Perfect candidate for making easier by
grokking it.</li>
</ul>
<p>That concludes the component tour.</p>
</div>
<div class="section" id="what-else">
<h3><a name="what-else">What else?</a></h3>
<p>Grok is more than just the API.  It is a sort of language with base
classes, decorators, methods.  It is an attitude to be friendly to
beginners.</p>
</div>
<div class="section" id="we-want-smooth-installation-for-grok">
<h3><a name="we-want-smooth-installation-for-grok">We want smooth installation for Grok.</a></h3>
<ul class="simple">
<li>Goal: smooth installation for Grok and Grok applications.</li>
<li>We maintain a list of versions of libraries we use: pinned versions.
That works for core Grok.  But it did not work for <tt class="docutils literal"><span class="pre">megrok.form</span></tt>
recently.  Todo: update to the Zope 3 KGS list of versions (from
Stephan Richter).  All tests in the KGS pass; with the Grok version
list the Grok tests pass, but the other tests did not all pass.
That is not good.</li>
<li>Todo: downloads sometimes fail.  Sourceforge sometimes moves stuff
around, the cheeseshop can be down, zope.org can be down.  Todo:
look at <tt class="docutils literal"><span class="pre">zc.sourcerelease</span></tt> to make one tarball of Grok.</li>
<li>Todo: version pinning for extensions.  <tt class="docutils literal"><span class="pre">buildout.cfg</span></tt> may or may
not be better than <tt class="docutils literal"><span class="pre">setup.py</span></tt> for this.</li>
</ul>
</div>
<div class="section" id="relation-database-integration">
<h3><a name="relation-database-integration">Relation database integration</a></h3>
<ul class="simple">
<li>This should be a first-class citizen in the zope world.</li>
<li>Todo: figure out default story for RDB integration.  This can be a
big discussion/fight about what we choose.</li>
<li>Todo: auto generation of Zope 3 schemas from database table schemas.
Often you will find you are repeating yourself here.</li>
<li>Todo: Model and Container base classes for RDB.  So these would not
have persistence as they are not stored in the ZODB.</li>
<li>Todo: patterns for security integration.  You need a bit too much
methods currently.</li>
<li>Todo: obviously add documentation.</li>
</ul>
</div>
<div class="section" id="wsgi">
<h3><a name="wsgi">WSGI</a></h3>
<p>Web Services Gateway Integration.  We have code for this, but we need
to make this easier; possibly put it in grokproject by default.</p>
<ul class="simple">
<li>Todo: check the differences between grokproject and zopeproject;
there should not be much differences.</li>
<li>Todo: make grokproject really available as a paster template.  It
can be done already, but we need to document this.</li>
<li>Todo: put in a few useful WSGI components for development.  Look at
repoze too.</li>
<li>Todo: development and deployment profile.</li>
</ul>
</div>
<div class="section" id="menus">
<h3><a name="menus">Menus</a></h3>
<p>Actions, drop-down lists, navigation, things like that.  An extension
should be able to add to a menu.  We can have <tt class="docutils literal"><span class="pre">grok.Menu</span></tt>,
<tt class="docutils literal"><span class="pre">grok.MenuItem</span></tt>.  Also see <tt class="docutils literal"><span class="pre">grok.Title</span></tt> and <tt class="docutils literal"><span class="pre">grok.Description</span></tt>,
perhaps later <tt class="docutils literal"><span class="pre">grok.Icon</span></tt>.</p>
<ul class="simple">
<li>Todo: examine zope 3 menu directive approach and compare it with
viewlets.  Investigate what is there, also in Plone.</li>
</ul>
</div>
<div class="section" id="ajax">
<h3><a name="ajax">AJAX</a></h3>
<ul class="simple">
<li>Todo: finalize KSS integration.</li>
</ul>
</div>
<div class="section" id="resources">
<h3><a name="resources">Resources</a></h3>
<ul class="simple">
<li>Todo: consider what is the right way for Grok to do this.</li>
<li>Todo: think about making it possible to overwrite static resources
in extensions.</li>
</ul>
</div>
<div class="section" id="introspector">
<h3><a name="introspector">Introspector</a></h3>
<ul class="simple">
<li>Uli has done work here and will be working on it for Google Summer
of Code.</li>
<li>Todo: improve the object browser UI.  Show which defaults are used
for directives that are not explicitly in the code.  In Firebug you
can see the calculated style; something like that would be useful.</li>
<li>Todo: new directive implementation in Martian.  <tt class="docutils literal"><span class="pre">grok.name</span></tt> has
different defaults depending on where it is called.  We can make
that more explicit, guard against unforeseen uses.</li>
</ul>
</div>
<div class="section" id="miscellaneous">
<h3><a name="miscellaneous">Miscellaneous</a></h3>
<ul class="simple">
<li>Back to the future: through the web (TTW) development.  This made
Zope 2 popular.  We can look at <tt class="docutils literal"><span class="pre">five.customerize</span></tt> for overriding
views.  Defining a schema TTW would be cool, if we can avoid the
problems from ZClasses.</li>
<li>Make CRUD UIs TTW.</li>
</ul>
</div>
<div class="section" id="documentation">
<h3><a name="documentation">Documentation</a></h3>
<ul class="simple">
<li>We have the beginner's tutorial.  It gets you started, but it can be
longer.  This is maintained in subversion.  For other documentation:
just add it to the website and publish it.</li>
<li>We have developer's notes in subversion.</li>
<li>Todo: The Reference.</li>
<li>Todo: website improvements.  I could not update the link and text in
the sidebar.  This was hardcoded.  Kevin Teague has done a lot of
work here, but we need more people here.</li>
</ul>
<p>Rule: a sprint project is <em>not</em> finished without documentation!</p>
</div>

          ]]>
        </content:encoded>        

        <dc:date>2008-04-30T14:53:02+02:00</dc:date>

        <dcterms:modified>2008-04-30T14:53:02+02:00</dcterms:modified>

        <dc:creator>Maurits van Rees</dc:creator>

        

        
            <dc:subject>grok</dc:subject>
        
        
            <dc:subject>plone</dc:subject>
        

    </rss:item>

    
    

    <rss:item rdf:about="http://maurits.vanrees.org/weblog/archive/2008/04/first-impressions-of-ubuntu-hardy-heron">

        <rss:title>First impressions of Ubuntu Hardy Heron </rss:title>

        <rss:link>http://maurits.vanrees.org/weblog/archive/2008/04/first-impressions-of-ubuntu-hardy-heron</rss:link>       

        <rss:description>No big issues, but watch out for not yet compatible Firefox extensions.
</rss:description>

        <content:encoded>
          <![CDATA[
          <p>A new Ubuntu Linux was <a class="reference" href="http://www.ubuntu.com/news/ubuntu-8.04-lts-desktop">released</a> on 21 April.  It is version 8.04, with
codename Hardy Heron.  So I upgraded my home desktop machine.  Emacs
still works and mutt still works so I am happy. ;-)  For me there were
two snags until now:</p>
<ul>
<li><p class="first">I want the Caps Lock key to behave as an extra Control key.  This
worked before and it still works, but now when I press the Caps Lock
key the light indicating that Caps Lock is on starts or stops
shining, even though I only really use it as a Control key.  See
this <a class="reference" href="https://bugs.launchpad.net/ubuntu/+bug/173350">bug report</a>, which also mentions some remedies.  I ended up
adding some lines to my <tt class="docutils literal"><span class="pre">~/.bashrc</span></tt> file:</p>
<pre class="literal-block">
xmodmap | grep lock | grep Caps_Lock &gt; /dev/null
if test $? -eq 0; then
    xmodmap -e &quot;remove Lock = Caps_Lock&quot; -e &quot;keysym Caps_Lock = Control_L&quot; -e &quot;add Control = Control_L&quot;
fi
</pre>
</li>
<li><p class="first">Firefox 3.0b5 is used.  There are not yet versions of Firebug and
Live HTTP Headers that are compatible with this.  That is not good
when you are doing web development.  I expect that this will get
fixed soon.</p>
</li>
</ul>
<p>In light of that last issue I think I will keep the laptop from my work
at the previous Ubuntu for a while until those extensions are
available.</p>
<p>Update: Both Wichert Akkerman and Jeroen Vloothuis tell me that there is a <a class="reference" href="http://www.getfirebug.com/releases/firebug/1.1/">Firebug 1.1 beta</a> that works with the new Firefox.  This was not automatically found when Firefox looked for updates.  This version indeed works, though for me it only works when opening Firebug in a new Window.</p>
<p>All in all a big thank you to everyone who made another Ubuntu version happen!</p>

          ]]>
        </content:encoded>        

        <dc:date>2008-04-27T01:28:52+02:00</dc:date>

        <dcterms:modified>2008-04-27T13:30:52+02:00</dcterms:modified>

        <dc:creator>Maurits van Rees</dc:creator>

        

        
            <dc:subject>computers</dc:subject>
        
        
            <dc:subject>plone</dc:subject>
        

    </rss:item>

    
    

    <rss:item rdf:about="http://maurits.vanrees.org/weblog/archive/2008/01/missing-files-from-eggs">

        <rss:title>Missing files from eggs</rss:title>

        <rss:link>http://maurits.vanrees.org/weblog/archive/2008/01/missing-files-from-eggs</rss:link>       

        <rss:description>That egg you just build might be missing some files.  Check that egg!
Update: I received some pointers for more info.</rss:description>

        <content:encoded>
          <![CDATA[
          <p>Today I discovered that an egg I just made for a package was missing some files.  Most noticeable was the missing of some zcml files.</p>
<p>It turns out that when you do an <tt class="docutils literal"><span class="pre">svn</span> <span class="pre">export</span></tt> and then a <tt class="docutils literal"><span class="pre">python2.4</span> <span class="pre">setup.py</span> <span class="pre">bdist_egg</span></tt> to create your egg, you are missing some files.  At least I was.  When you do an <tt class="docutils literal"><span class="pre">svn</span> <span class="pre">checkout</span></tt> and then make your egg, all files are there.</p>
<p>In neither case was any zcml file mentioned in the <tt class="docutils literal"><span class="pre">SOURCES.txt</span></tt> file in the automatically created egg-info directory.</p>
<p>For the tar ball created by a <tt class="docutils literal"><span class="pre">python2.4</span> <span class="pre">setup.py</span> <span class="pre">sdist</span></tt> I did not notice any difference.</p>
<p>Does anyone know what is going on here and how to solve this so it works from an svn export too?</p>
<p>Cooking lesson for today: check that egg!</p>
<p>Oh, and sorry for spamming <a class="reference" href="http://planet.plone.org">http://planet.plone.org</a> today.  I changed the language of a lot of weblog entries from neutral into English. Now they all needlessly show up on that home page.</p>
<div class="section" id="update">
<h3><a name="update">Update</a></h3>
<p>Daniel Nouri pointed me to the <a class="reference" href="http://peak.telecommunity.com/DevCenter/setuptools#including-data-files">setuptools docs</a> that explain what is going on; plus the docs for disutils, especially the part about adding a <a class="reference" href="http://docs.python.org/dist/manifest.html">manifest</a> file.  And Andreas Zeidler pointed to a thread on the <a class="reference" href="http://thread.gmane.org/gmane.comp.web.zope.plone.devel/16981">Plone developers list</a>. And Florian Schulze pointed me to both. :-)  I have the feeling there are a few people reading this weblog. :-) Thanks everyone!</p>
<p>In my case the tar ball problems pointed out by Florian did not affect me.  In fact, when I uploaded just the tar ball and tried to easy_install it, this went fine: an egg was automatically created from the tar ball.  But it is good to know that there can be problems in that area too.</p>
<p>Conclusion for me: easiest is just to create and upload an egg from a subversion checkout, not from an export.  And if you want more control, read those <a class="reference" href="http://peak.telecommunity.com/DevCenter/setuptools#including-data-files">setuptools docs</a>.</p>
</div>

          ]]>
        </content:encoded>        

        <dc:date>2008-01-30T23:36:13+01:00</dc:date>

        <dcterms:modified>2008-01-31T16:13:40+01:00</dcterms:modified>

        <dc:creator>Maurits van Rees</dc:creator>

        

        
            <dc:subject>plone</dc:subject>
        

    </rss:item>

    
    

    <rss:item rdf:about="http://maurits.vanrees.org/weblog/archive/2008/01/skin-switching-with-pre-traversal">

        <rss:title>Skin switching with pre-traversal</rss:title>

        <rss:link>http://maurits.vanrees.org/weblog/archive/2008/01/skin-switching-with-pre-traversal</rss:link>       

        <rss:description>collective.skinswitcher uses a pre-traversal hook now instead of an access rule.</rss:description>

        <content:encoded>
          <![CDATA[
          <p>For <tt class="docutils literal"><span class="pre">collective.editskinswitcher</span></tt> David Convent gave me the idea to
get rid of the Access Rule and use a pre-traversal hook instead.  That
turned out to be pretty easy to do.  This looks far cleaner to me.  So
<cite>collective.editskinswitcher</cite> is now available as version 0.3.  Thanks
for the idea David!</p>
<p>It now has an own <a class="reference" href="http://plone.org/products/editskin-switcher/">Product page</a> on plone.org too.  Not much is there
yet.  For downloads just use the <a class="reference" href="http://pypi.python.org/pypi/collective.editskinswitcher">cheese shop</a>.  If you are using it,
drop me a note: it would be nice to know.</p>
<p>Let me show some code.  We subscribe to an event in <tt class="docutils literal"><span class="pre">configure.zcml</span></tt>:</p>
<pre class="literal-block">
&lt;subscriber
    for=&quot;*
         zope.app.publication.interfaces.IBeforeTraverseEvent&quot;
    handler=&quot;.traversal.switch_skin&quot;
    /&gt;
</pre>
<p>And in <tt class="docutils literal"><span class="pre">traversal.py</span></tt> you then have this code:</p>
<pre class="literal-block">
def switch_skin(object, event):
    &quot;&quot;&quot;Switch to the Plone Default skin when we are editing.
    &quot;&quot;&quot;
    context = object
    request = event.request
    portal_props = getToolByName(context, 'portal_properties')
    editskin_props = portal_props.get('editskin_switcher')
    edit_skin = editskin_props.getProperty('edit_skin', '')
    ...
    context.changeSkin(edit_skin, request)
</pre>
<p>Well, the code is slightly longer, but this should give you an idea.
Except for details this is the same code as was in the External
Method, which is now gone.</p>
<p>All in all, for this change one file was added: <tt class="docutils literal"><span class="pre">traversal.py</span></tt>.  And
various files could be removed, mainly: <tt class="docutils literal"><span class="pre">Extensions/*</span></tt> and
<tt class="docutils literal"><span class="pre">setuphandlers.py</span></tt>.</p>
<p>More importantly: if you now remove this package from your zope
instance without properly reinstalling it, you are not left with an
ExternalMethod in your Plone Site that gives errors because the file
is not available anymore.</p>
<p>BTW, if you are using this package already, it is best to uninstall
version 0.2 and then install version 0.3; that way the quick installer
will take care of removing that external method with the access rule
for you.</p>

          ]]>
        </content:encoded>        

        <dc:date>2008-01-30T17:16:18+01:00</dc:date>

        <dcterms:modified>2008-01-30T23:20:40+01:00</dcterms:modified>

        <dc:creator>Maurits van Rees</dc:creator>

        

        
            <dc:subject>plone</dc:subject>
        

    </rss:item>

    
    

    <rss:item rdf:about="http://maurits.vanrees.org/weblog/archive/2008/01/switch-your-skin-if-you-are-logged-in">

        <rss:title>Switch your skin if you are logged in</rss:title>

        <rss:link>http://maurits.vanrees.org/weblog/archive/2008/01/switch-your-skin-if-you-are-logged-in</rss:link>       

        <rss:description>With collective.editskinswitcher 0.2 you can now also switch your skin if you are logged in.</rss:description>

        <content:encoded>
          <![CDATA[
          <p>I improved <tt class="docutils literal"><span class="pre">collective.editskinswitcher</span></tt> again.  For explanation on
what it is, see my <a class="reference" href="http://maurits.vanrees.org/weblog/archive/2008/01/switch-your-skin-based-on-the-url">first blog entry</a> about it.</p>
<p>You could already get a different skin (presumably for editors) when
you are visiting your Plone Site with an edit url, like
<tt class="docutils literal"><span class="pre">edit.yourdomain.com</span></tt>.</p>
<p>Now you can also get that edit skin when you are logged in.  More
precisely: when you have the <tt class="docutils literal"><span class="pre">__ac</span></tt> cookie.  This does not work when
you are logged in with basic authentication, in other words: via the
ZMI.</p>
<p>This is controlled by two new properties in the
<tt class="docutils literal"><span class="pre">portal_properties/editskin_switcher</span></tt>.</p>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">based_on_url</span></tt>: when True (the default) you get the behaviour
described earlier.</li>
<li><tt class="docutils literal"><span class="pre">need_authentication</span></tt>: when True you need to be logged in before
your skin is switched.  By default this is set to False.  This looks
for the <tt class="docutils literal"><span class="pre">__ac</span></tt> cookie that Plone gives you when logged in.  Note:
logging in via the Zope Management Interface is handled without
cookies, so the editskin switcher regards you as anonymous then.</li>
</ul>
<p>You can combine the two behaviours if you want.  If they are both
True, then you need to have the right url and you need to be logged
in.</p>
<p>When both are False, nothing happens: then you might as well simply
uninstall this product as it is not useful.</p>

          ]]>
        </content:encoded>        

        <dc:date>2008-01-28T16:23:39+01:00</dc:date>

        <dcterms:modified>2008-01-30T23:20:28+01:00</dcterms:modified>

        <dc:creator>Maurits van Rees</dc:creator>

        

        
            <dc:subject>plone</dc:subject>
        

    </rss:item>

    
    

    <rss:item rdf:about="http://maurits.vanrees.org/weblog/archive/2008/01/switch-your-skin-based-on-the-url">

        <rss:title>Switch your skin based on the url</rss:title>

        <rss:link>http://maurits.vanrees.org/weblog/archive/2008/01/switch-your-skin-based-on-the-url</rss:link>       

        <rss:description>Announcing the new collective.editskinswitcher package</rss:description>

        <content:encoded>
          <![CDATA[
          <h2 class="title">Collective Edit Skin Switcher</h2>
<p>For a customer of <a class="reference" href="http://zestsoftware.nl">Zest Software</a> I created a
package called <tt class="docutils literal"><span class="pre">collective.editskinswitcher</span></tt>.  I gladly took some code
from colleague Mark van Lent who did something similar for a different
web site.  The package is on the Cheese Shop so it can be easy
installed.  And the code is in the Plone <a class="reference" href="http://svn.plone.org/svn/collective/collective.editskinswitcher/">collective</a>.</p>
<div class="section" id="what-does-it-do">
<h3><a name="what-does-it-do">What does it do?</a></h3>
<p>Let's say you have a Plone Site.  I tested this with Plone 3.  I see
no reason why it should fail on Plone 2.5.  Maybe it even works on a
CMF site.  Anyway, whatever site you have is available on two urls:
<tt class="docutils literal"><span class="pre">www.yourdomain.com</span></tt> and <tt class="docutils literal"><span class="pre">edit.yourdomain.com</span></tt>.  Some day you
should ask your local Apache guru how he did that.</p>
<p>With <tt class="docutils literal"><span class="pre">collective.editskinswitcher</span></tt> installed (with the portal quick
installer), visitors that go to the website with the url
<tt class="docutils literal"><span class="pre">edit.yourdomain.com</span></tt> will see the Plone Default skin, which is
meant for content editors.  Visitors to <tt class="docutils literal"><span class="pre">www.yourdomain.com</span></tt> will
see whatever skin you have set as the default skin in portal_skins.
Can be pretty handy.</p>
<p>Developer types probably like the fact that you also get the default
skin when visiting <tt class="docutils literal"><span class="pre">localhost</span></tt> and the edit skin when you go to
<tt class="docutils literal"><span class="pre">127.0.0.1</span></tt>.</p>
<p>But maybe you want to turn it around: your visitors should see Plone
Default and your editors should see your brilliant Monty Python Skin!
Ni!  Just go to the <tt class="docutils literal"><span class="pre">portal_properties</span></tt>, then <tt class="docutils literal"><span class="pre">editskin_switcher</span></tt>
and change the <tt class="docutils literal"><span class="pre">edit_skin</span></tt> property to your dashing theme.</p>
</div>
<div class="section" id="why-not-cmfurlskinswitcher">
<h3><a name="why-not-cmfurlskinswitcher">Why not CMFUrlSkinSwitcher?</a></h3>
<p>I looked at CMFUrlSkinSwitcher first but it had not been touched in
two years.  One import error (CMFCorePermissions) could easily be
fixed as that import was not even used.  But after that tests were
failing all over the place.  Theoretically always fixable of course,
but rolling an own package seemed easier, cleaner and faster.</p>
<p>Also, CMFUrlSkinSwitcher does some more things.  At least it messes
around with some methods like absolute_url.  It could be that I find
out later that this is necessary in <tt class="docutils literal"><span class="pre">collective.editskinswitcher</span></tt> too,
but currently it does not look like that will be the case.</p>
</div>
<div class="section" id="how-do-i-know-this-is-working">
<h3><a name="how-do-i-know-this-is-working">How do I know this is working?</a></h3>
<p>The easiest way to test this package in a default plone site (apart
from running the tests of course), is:</p>
<ul class="simple">
<li>Install <tt class="docutils literal"><span class="pre">collective.editskinswitcher</span></tt>.</li>
<li>Go to portal_skins in the ZMI.</li>
<li>Create a new skin selection based on Plone Default.  In the tests I
call this Monty Python Skin, so I will use that term here as well.</li>
<li>Make Monty Python Skin the default skin.</li>
<li>Remove the custom skin layer from Plone Default.</li>
<li>Customize the main template or the logo or something else that
is easy to spot.</li>
<li>Visit <tt class="docutils literal"><span class="pre">127.0.0.1:8080/plonesite</span></tt> and you will see default Plone.</li>
<li>Visit <tt class="docutils literal"><span class="pre">localhost:8080/plonesite</span></tt> and you will see Plone with
your customization.</li>
</ul>
<p>On Linux you can edit <tt class="docutils literal"><span class="pre">/etc/hosts</span></tt> and add a line like:</p>
<pre class="literal-block">
127.0.0.1 edit.yourdomain.com www.yourdomain.com
</pre>
<p>Now visiting <tt class="docutils literal"><span class="pre">edit.yourdomain.com</span></tt> should give you default Plone and
<tt class="docutils literal"><span class="pre">www.yourdomain.com</span></tt> should give you the customized Plone.</p>
<p>You can also let the edit urls begin with <tt class="docutils literal"><span class="pre">cms</span></tt> or <tt class="docutils literal"><span class="pre">manage</span></tt>.  As
long as the url is something like:</p>
<pre class="literal-block">
...//(edit|cms|manage).something.something....
</pre>
<p>you end up in the edit skin.</p>
<p>Have fun!</p>
<p>Maurits van Rees</p>
</div>

          ]]>
        </content:encoded>        

        <dc:date>2008-01-25T20:48:09+01:00</dc:date>

        <dcterms:modified>2008-01-30T23:20:17+01:00</dcterms:modified>

        <dc:creator>Maurits van Rees</dc:creator>

        

        
            <dc:subject>plone</dc:subject>
        
        
            <dc:subject>zest</dc:subject>
        

    </rss:item>

    
    

    <rss:item rdf:about="http://maurits.vanrees.org/weblog/archive/2008/01/easily-creating-repeatable-buildouts">

        <rss:title>Easily creating repeatable buildouts</rss:title>

        <rss:link>http://maurits.vanrees.org/weblog/archive/2008/01/easily-creating-repeatable-buildouts</rss:link>       

        <rss:description>When you create a buildout for a production website, you want to be able to recreate that exact buildout one year from now on a different server.  How do you do that?  This is a more simple and better working version of an earlier post.</rss:description>

        <content:encoded>
          <![CDATA[
          <div class="section" id="background">
<h3><a name="background">Background</a></h3>
<p>I first wrote a <a class="reference" href="http://maurits.vanrees.org/weblog/archive/2008/01/creating-repeatable-buildouts">rather difficult guide</a> to getting a stable,
repeatable buildout.  After some helpful comments from Martijn Faassen
I could make this much simpler.  I decided to keep the old weblog
entry around: it could be helpful for people googling for strange
errors in their buildout.</p>
<p>I assume you know what buildout is, otherwise you would probably not
be reading this.  Martin Aspeli has written a tutorial on <a class="reference" href="http://plone.org/documentation/tutorial/buildout">Managing
projects with zc.buildout</a>.  This should be your first stop for
learning more about buildout, at least if you are a Plone developer.</p>
<p>My brother and colleague Reinout has written a weblog entry about the
<a class="reference" href="http://vanrees.org/weblog/archive/2007/12/27/buildout-development-production-strategy">Buildout development/production strategy</a> that we are starting to
use at <a class="reference" href="http://zestsoftware.nl">Zest Software</a>.  The goal is to use the same buildout for
both development and production deployment.</p>
<p>As the buildout should be repeatable, you may want to read the
<a class="reference" href="http://svn.zope.de/zope.org/zc.buildout/trunk/src/zc/buildout/repeatable.txt">repeatable test file</a> from the zc.buildout package.</p>
</div>
<div class="section" id="definitions">
<h3><a name="definitions">Definitions</a></h3>
<p>Now I am going to write about creating a really stable and repeatable
buildout.  In Reinout's story that would fit in with creating a
<tt class="docutils literal"><span class="pre">stable.cfg</span></tt>.  If you are not concerning yourself with development
or if you have a different buildout for production deployment, this
would just be the <tt class="docutils literal"><span class="pre">buildout.cfg</span></tt> file.</p>
<p>Let's begin with some perhaps arbitrary definitions.</p>
<p>With <em>stable</em> I mean: you run the buildout script in a directory; one
year later you run buildout for the second time; you get the same
result as one year earlier.  Use case: by accident you removed the
entire <tt class="docutils literal"><span class="pre">parts</span></tt> directory and you need to rebuild it.</p>
<p>With <em>repeatable</em> I mean: you run the buildout script in a directory;
one year later you run the buildout on a completely different server;
both directories are exactly the same.  Use case: you want to move the
zope instance of a customer to a new server.</p>
</div>
<div class="section" id="creating-the-buildout">
<h3><a name="creating-the-buildout">Creating the buildout</a></h3>
<p>What I write in this entry should be applicable to any buildout with
or without Plone.  My main focus and example is a Plone buildout
though.  You can fix up a current buildout of course, but here let's
start with a clean default buildout for Plone 3, which you can create
with <tt class="docutils literal"><span class="pre">paster</span></tt>:</p>
<pre class="literal-block">
paster create -t plone3_buildout test
cd test
python2.4 bootstrap.py
</pre>
</div>
<div class="section" id="no-newer-packages">
<h3><a name="no-newer-packages">No newer packages</a></h3>
<p>When running <tt class="docutils literal"><span class="pre">bin/buildout</span></tt> by default it picks the newest package
it can find for any dependency.  We can tell buildout to first look if
some version of that package is already available:</p>
<pre class="literal-block">
[buildout]
newest = false
</pre>
<p>This way, a second call of <tt class="docutils literal"><span class="pre">bin/buildout</span></tt> will not try to get any
new packages.  So it will finish quickly and just keep the current
packages.  This already makes the buildout stable in the sense that a
new run of <tt class="docutils literal"><span class="pre">bin/buildout</span></tt> in that same directory will give you no
new packages.</p>
<p>But if you want to recreate that buildout in a different directory or
even a different server, you can get other versions.  For starters,
currently this buildout config will give you Plone 3.0.5, but a few
months from now you will probably get Plone 3.1.  So this is not yet a
repeatable buildout.</p>
</div>
<div class="section" id="simple-index">
<h3><a name="simple-index">Simple index</a></h3>
<p>As an aside, while we are in the buildout section, let's quickly
specify a simpler (read: faster) index than the default <a class="reference" href="http://pypi.python.org/pypi">CheeseShop</a>:</p>
<pre class="literal-block">
[buildout]
newest = false
index = http://download.zope.org/ppix
</pre>
<p>See my brother's weblog entry on <a class="reference" href="http://vanrees.org/weblog/archive/2008/01/09/ppix-instead-of-pypi-from-now-on">ppix instead of pypi from now on</a>.</p>
<p>By the way, this has nothing to do with making your buildout more
stable or repeatable.</p>
</div>
<div class="section" id="pinning-versions">
<h3><a name="pinning-versions">Pinning versions</a></h3>
<p>Let's go get some more stability in our buildout.  For some recipes
and packages there are more ways to pin versions.  But none of them
work in all cases, except one.  So we will just use that one way:</p>
<pre class="literal-block">
[buildout]
...
versions = versions

[versions]
...
</pre>
<p>So in your <tt class="docutils literal"><span class="pre">[buildout]</span></tt> section you add an option <tt class="docutils literal"><span class="pre">versions</span></tt> in
which you point to another section that contains the versions that
packages should be pinned to.</p>
</div>
<div class="section" id="pinning-the-plone-version">
<h3><a name="pinning-the-plone-version">Pinning the plone version</a></h3>
<p>First things first: we pick a Plone version.  We simply add a line to
the <tt class="docutils literal"><span class="pre">[versions]</span></tt> section that we added above:</p>
<pre class="literal-block">
[versions]
plone.recipe.plone = 3.0.5
</pre>
<p>This recipe has strict versions for the Plone products and packages
that make up a Plone release, so for example <tt class="docutils literal"><span class="pre">Products.CMFPlone</span></tt>,
<tt class="docutils literal"><span class="pre">Products.CMFCore</span></tt>, the various <tt class="docutils literal"><span class="pre">plone.*</span></tt> packages, etcetera.</p>
<p>And this has a <tt class="docutils literal"><span class="pre">zope2-url</span></tt> property that tells the
<tt class="docutils literal"><span class="pre">plone.recipe.zope2install</span></tt> recipe that it should use Zope 2.10.5.</p>
<p>So the most important versions have already been pinned now.</p>
</div>
<div class="section" id="knowing-which-versions-are-not-pinned">
<h3><a name="knowing-which-versions-are-not-pinned">Knowing which versions are not pinned</a></h3>
<p>Wichert Akkerman came up with the following one-liner to get a list of
versions that are not pinned by you, but picked by buildout:</p>
<pre class="literal-block">
bin/buildout -Novvvvv |sed -ne 's/^Picked: //p' | sort | uniq
</pre>
<p>Currently this returns this list:</p>
<pre class="literal-block">
elementtree = 1.2.7-20070827-preview
plone.recipe.distros = 1.3
plone.recipe.zope2install = 1.2
plone.recipe.zope2instance = 1.3
python-openid = 2.0.1
setuptools = 0.6c7
zc.recipe.egg = 1.0.0
</pre>
<p>This basically means that the mentioned packages are not pinned by our
buildout config, but chosen (picked) by buildout.  This means that
they are not stable yet: rerunning this script in a few months time
will likely give you different versions.</p>
<p>So what should you do?  Very simple: you literally add those lines to
the <tt class="docutils literal"><span class="pre">[versions]</span></tt> section.  Now all your packages are pinned.</p>
</div>
<div class="section" id="pinning-extra-products">
<h3><a name="pinning-extra-products">Pinning extra products</a></h3>
<p>You can of course also pin any extra products that you want to use in
your buildout.  Best is to use an official release, such as a tar
ball:</p>
<pre class="literal-block">
[productdistros]
recipe = plone.recipe.distros
urls =
    http://plone.org/products/poi/releases/1.1/poi_1.1.tgz
</pre>
<p>or a checkout of a subversion tag:</p>
<pre class="literal-block">
[productcheckouts]
recipe = infrae.subversion
urls =
  http://svn.plone.org/svn/collective/eXtremeManagement/tags/1.5.2/ eXtremeManagement
</pre>
<p>If for some reason there is no tag you can use, you can still specify
a revision in the url with the <tt class="docutils literal"><span class="pre">&#64;</span></tt> sign.  Thanks to Guido Wesdorp
for pointing this out:</p>
<pre class="literal-block">
[productcheckouts]
recipe = infrae.subversion
urls =
    http://getpaid.googlecode.com/svn/trunk/products/PloneGetPaid&#64;1132 PloneGetPaid
</pre>
<p>For now let's keep the example simple here and remove these products
again from our <tt class="docutils literal"><span class="pre">buildout.cfg</span></tt>.</p>
</div>
<div class="section" id="conclusions">
<h3><a name="conclusions">Conclusions</a></h3>
<p>A buildout can be made very stable: just put <tt class="docutils literal"><span class="pre">newest</span> <span class="pre">=</span> <span class="pre">false</span></tt> in
your buildout section.  If one year later you accidentally remove the
parts directory, you can rerun buildout and get your original
directory back.  If you remove your eggs though, you are in trouble.</p>
<p>Making a buildout repeatable is not that difficult either after all.
Put this in your <tt class="docutils literal"><span class="pre">buildout.cfg</span></tt>:</p>
<pre class="literal-block">
[buildout]
...
versions = versions

[versions]
</pre>
<p>Right below <tt class="docutils literal"><span class="pre">[versions]</span></tt> add the result of this one-liner:</p>
<pre class="literal-block">
bin/buildout -Novvvvv |sed -ne 's/^Picked: //p' | sort | uniq
</pre>
<p>Contrary to some earlier conclusions that I drew, this is everything
that is needed to pin all packages.</p>
<p>For pinning <em>old-style</em> Products, see the section on <a class="reference" href="#pinning-extra-products">Pinning extra products</a>.</p>
</div>
<div class="section" id="bonus">
<h3><a name="bonus">Bonus</a></h3>
<p><tt class="docutils literal"><span class="pre">plone.recipe.plone</span></tt> rigourously depends on specific packages and
products.  So what do you do if you want to use a newer version of
just one or two packages?  For instance, I did some fixes for
<tt class="docutils literal"><span class="pre">plone.locking</span></tt> which are still not in Plone 3.0.5.  And for
multilingual sites you really want to use a newer version with an
important bug fix.  You might at first think that this would be
enough:</p>
<pre class="literal-block">
[versions]
plone.locking = 1.0.5
plone.app.i18n = 1.0.2
</pre>
<p>But running <tt class="docutils literal"><span class="pre">bin/buildout</span></tt> then gives an error:</p>
<pre class="literal-block">
The version, 1.0.2, is not consistent with the requirement,
'plone.app.i18n==1.0.1'.
While:
  Installing plone.
Error: Bad version 1.0.2
</pre>
<p>So you need to add two lines to the <tt class="docutils literal"><span class="pre">[plone]</span></tt> section:</p>
<pre class="literal-block">
[plone]
recipe = plone.recipe.plone
eggs =
    plone.locking
    plone.app.i18n
</pre>
<p>These lines basically erase the version pinning of those two packages
that is in the recipe.  After that, the pinning in the <tt class="docutils literal"><span class="pre">[versions]</span></tt>
section can take effect.</p>
</div>
<div class="section" id="the-final-version">
<h3><a name="the-final-version">The final version</a></h3>
<p>Let's end with showing what our <tt class="docutils literal"><span class="pre">buildout.cfg</span></tt> now looks like.  Or
actually, let's let's show a buildout that uses some earlier versions:
Plone 3.0.2, older recipes, and older setuptools and elementtree.  And
instead of <tt class="docutils literal"><span class="pre">plone.app.i18n</span></tt> 1.0 that is required by Plone 3.0.2 we
pin this package to a slightly newer version 1.0.1, which is not the
latest version in the <a class="reference" href="http://pypi.python.org/pypi">CheeseShop</a>.  This older buildout should show
nicely that you can have a stable, repeatable buildout months later.
Try it!  So here is the file itself:</p>
<pre class="literal-block">
[buildout]
newest = false
index = http://download.zope.org/ppix
parts =
    instance
    zope2
    plone
    zopepy
    productdistros

find-links =
    http://dist.plone.org
    http://download.zope.org/ppix/
    http://download.zope.org/distribution/
    http://effbot.org/downloads

# Add additional eggs here
# elementtree is required by Plone
eggs =
    elementtree

versions = versions

[versions]
setuptools = 0.6c6
zc.recipe.egg = 1.0.0b6
plone.recipe.plone = 3.0.2
elementtree = 1.2.6-20050316
plone.recipe.distros = 0.3
plone.recipe.zope2install = 1.0
plone.recipe.zope2instance = 1.0
python-openid = 2.0.1
plone.app.i18n = 1.0.1

[plone]
recipe = plone.recipe.plone
eggs =
    plone.app.i18n

[zope2]
recipe = plone.recipe.zope2install
url = ${plone:zope2-url}

[productdistros]
recipe = plone.recipe.distros
urls =
nested-packages =
version-suffix-packages = 

[instance]
recipe = plone.recipe.zope2instance
zope2-location = ${zope2:location}
user = admin:
http-address = 8080
#debug-mode = on
#verbose-security = on

# If you want Zope to know about any additional eggs, list them here.
# This should include any development eggs you listed in develop-eggs above,
# e.g. eggs = ${buildout:eggs} ${plone:eggs} my.package
eggs =
    ${buildout:eggs}
    ${plone:eggs}

# If you want to register ZCML slugs for any packages, list them here.
# e.g. zcml = my.package my.other.package
zcml = 

products =
    ${buildout:directory}/products
    ${productdistros:location}
    ${plone:products}

[zopepy]
recipe = zc.recipe.egg
eggs = ${instance:eggs}
interpreter = zopepy
extra-paths = ${zope2:location}/lib/python
scripts = zopepy
</pre>
</div>

          ]]>
        </content:encoded>        

        <dc:date>2008-01-19T17:34:31+01:00</dc:date>

        <dcterms:modified>2008-01-30T23:20:07+01:00</dcterms:modified>

        <dc:creator>Maurits van Rees</dc:creator>

        

        
            <dc:subject>plone</dc:subject>
        
        
            <dc:subject>zest</dc:subject>
        

    </rss:item>

    
    

    <rss:item rdf:about="http://maurits.vanrees.org/weblog/archive/2008/01/creating-repeatable-buildouts">

        <rss:title>Creating repeatable buildouts</rss:title>

        <rss:link>http://maurits.vanrees.org/weblog/archive/2008/01/creating-repeatable-buildouts</rss:link>       

        <rss:description>When you create a buildout for a production website, you want to be able to recreate that exact buildout one year from now on a different server.  How do you do that?  Earlier version, kept for historical reasons
</rss:description>

        <content:encoded>
          <![CDATA[
          <p>I made a <a class="reference" href="http://maurits.vanrees.org/weblog/archive/2008/01/easily-creating-repeatable-buildouts">better, easier version</a> of this weblog entry.  Please read that instead, unless you are interested in some strange buildout errors that can occur when you are doing things a bit too difficult, like I am doing here.</p>
<p>When you create a buildout for a production website, you want to be
able to recreate that exact buildout one year from now on a different
server.  How do you do that?</p>
<div class="section" id="background">
<h3><a name="background">Background</a></h3>
<p>I assume you know what buildout is, otherwise you would probably not
be reading this.  Martin Aspeli has written a tutorial on <a class="reference" href="http://plone.org/documentation/tutorial/buildout">Managing
projects with zc.buildout</a>.  This should be your first stop for
learning more about buildout, at least if you are a Plone developer.</p>
<p>My brother and colleague Reinout has written a weblog entry about the
<a class="reference" href="http://vanrees.org/weblog/archive/2007/12/27/buildout-development-production-strategy">Buildout development/production strategy</a> that we are starting to
use at <a class="reference" href="http://zestsoftware.nl">Zest Software</a>.  The goal is to use the same buildout for
both development and production deployment.</p>
<p>As the buildout should be repeatable, you may want to read the
<a class="reference" href="http://svn.zope.de/zope.org/zc.buildout/trunk/src/zc/buildout/repeatable.txt">repeatable test file</a> from the zc.buildout package.</p>
</div>
<div class="section" id="definitions">
<h3><a name="definitions">Definitions</a></h3>
<p>Now I am going to write about creating a really stable and repeatable
buildout.  In Reinout's story that would fit in with creating a
<tt class="docutils literal"><span class="pre">stable.cfg</span></tt>.  If you are not concerning yourself with development
or if you have a different buildout for production deployment, this
would just be the <tt class="docutils literal"><span class="pre">buildout.cfg</span></tt> file.</p>
<p>Let's begin with some perhaps arbitrary definitions.</p>
<p>With <em>stable</em> I mean: you run the buildout script in a directory; one
year later you run buildout for the second time; you get the same
result as one year earlier.  Use case: by accident you removed the
entire <tt class="docutils literal"><span class="pre">parts</span></tt> directory and you need to rebuild it.</p>
<p>With <em>repeatable</em> I mean: you run the buildout script in a directory;
one year later you run the buildout on a completely different server;
both directories are exactly the same.  Use case: you want to move the
zope instance of a customer to a new server.</p>
</div>
<div class="section" id="creating-the-buildout">
<h3><a name="creating-the-buildout">Creating the buildout</a></h3>
<p>What I write in this entry should be applicable to any buildout with
or without Plone.  My main focus and example is a Plone buildout
though.  You can fix up a current buildout of course, but here let's
start with a clean default buildout for Plone 3, which you can create
with <tt class="docutils literal"><span class="pre">paster</span></tt>:</p>
<pre class="literal-block">
paster create -t plone3_buildout test
cd test
python2.4 bootstrap.py
</pre>
</div>
<div class="section" id="no-newer-packages">
<h3><a name="no-newer-packages">No newer packages</a></h3>
<p>When running <tt class="docutils literal"><span class="pre">bin/buildout</span></tt> by default it picks the newest package
it can find for any dependency.  We can tell buildout to first look if
some version of that package is already available:</p>
<pre class="literal-block">
[buildout]
newest = false
</pre>
<p>This way, a second call of <tt class="docutils literal"><span class="pre">bin/buildout</span></tt> will not try to get any
new packages.  So it will finish quickly and just keep the current
packages.  This already makes the buildout stable in the sense that a
new run of <tt class="docutils literal"><span class="pre">bin/buildout</span></tt> in that same directory will give you no
new packages.</p>
<p>But if you want to recreate that buildout in a different directory or
even a different server, you can get other versions.  For starters,
currently this buildout config will give you Plone 3.0.5, but a few
months from now you will probably get Plone 3.1.  So this is not yet a
repeatable buildout.</p>
</div>
<div class="section" id="simple-index">
<h3><a name="simple-index">Simple index</a></h3>
<p>As an aside, while we are in the buildout section, let's quickly
specify a simpler (read: faster) index than the default <a class="reference" href="http://pypi.python.org/pypi">CheeseShop</a>:</p>
<pre class="literal-block">
[buildout]
newest = false
index = http://download.zope.org/ppix
</pre>
<p>See my brother's weblog entry on <a class="reference" href="http://vanrees.org/weblog/archive/2008/01/09/ppix-instead-of-pypi-from-now-on">ppix instead of pypi from now on</a>.</p>
<p>By the way, this has nothing to do with making your buildout more
stable or repeatable.</p>
</div>
<div class="section" id="pinning-the-plone-version">
<h3><a name="pinning-the-plone-version">Pinning the plone version</a></h3>
<p>Let's go get some more stability in our buildout.  First things first:
we pick a Plone version.  Change this:</p>
<pre class="literal-block">
recipe = plone.recipe.plone
</pre>
<p>into this:</p>
<pre class="literal-block">
recipe = plone.recipe.plone == 3.0.5
</pre>
<p>This recipe has strict versions for the Plone products and packages
that make up a Plone release, so for example <tt class="docutils literal"><span class="pre">Products.CMFPlone</span></tt>,
<tt class="docutils literal"><span class="pre">Products.CMFCore</span></tt>, the various <tt class="docutils literal"><span class="pre">plone.*</span></tt> packages, etcetera.</p>
<p>And this has a <tt class="docutils literal"><span class="pre">zope2-url</span></tt> property that tells the
<tt class="docutils literal"><span class="pre">plone.recipe.zope2install</span></tt> recipe that it should use Zope 2.10.5.</p>
<p>So the most important versions have been pinned now.</p>
</div>
<div class="section" id="pinning-extra-products">
<h3><a name="pinning-extra-products">Pinning extra products</a></h3>
<p>You can of course also pin any extra products that you want to use in
your buildout.  Best is to use an official release, such as a tar
ball:</p>
<pre class="literal-block">
[productdistros]
recipe = plone.recipe.distros
urls =
    http://plone.org/products/poi/releases/1.1/poi_1.1.tgz
</pre>
<p>or a checkout of a subversion tag:</p>
<pre class="literal-block">
[productcheckouts]
recipe = infrae.subversion
urls =
  http://svn.plone.org/svn/collective/eXtremeManagement/tags/1.5.2/ eXtremeManagement
</pre>
<p>If for some reason there is no tag you can use, you can still specify
a revision in the url with the <tt class="docutils literal"><span class="pre">&#64;</span></tt> sign.  Thanks to Guido Wesdorp
for pointing this out:</p>
<pre class="literal-block">
[productcheckouts]
recipe = infrae.subversion
urls =
    http://getpaid.googlecode.com/svn/trunk/products/PloneGetPaid&#64;1132 PloneGetPaid
</pre>
<p>You can of course also pin the eggs of packages that you need, which
we will see below.  For now let's keep the example simple here and
remove these products again from our <tt class="docutils literal"><span class="pre">buildout.cfg</span></tt>.</p>
</div>
<div class="section" id="knowing-which-versions-are-not-pinned">
<h3><a name="knowing-which-versions-are-not-pinned">Knowing which versions are not pinned</a></h3>
<p>Wichert Akkerman came up with the following one-liner to get a list of
versions that are not pinned by you, but picked by buildout:</p>
<pre class="literal-block">
bin/buildout -Novvvvv |sed -ne 's/^Picked: //p' | sort | uniq
</pre>
<p>Currently this returns this list:</p>
<pre class="literal-block">
elementtree = 1.2.7-20070827-preview
plone.recipe.distros = 1.3
plone.recipe.zope2install = 1.2
plone.recipe.zope2instance = 1.3
python-openid = 2.0.1
setuptools = 0.6c7
zc.recipe.egg = 1.0.0
</pre>
<p>This basically means that the mentioned packages are not pinned by our
buildout config, but chosen (picked) by buildout.  This means that
they are not stable yet: rerunning this script in a few months time
will likely give you different versions.</p>
</div>
<div class="section" id="pinning-a-package">
<h3><a name="pinning-a-package">Pinning a package</a></h3>
<p>We start easily enough by pin elementtree.  Instead of this:</p>
<pre class="literal-block">
eggs =
    elementtree
</pre>
<p>we write this:</p>
<pre class="literal-block">
eggs =
    elementtree == 1.2.7-20070827-preview
</pre>
<p>As an aside, note that the top directive <tt class="docutils literal"><span class="pre">eggs</span></tt> has one equals sign
after it and the option <tt class="docutils literal"><span class="pre">elementtree</span></tt> below it has a double equals
sign.  The point is that in the options you write a test, so you could
also choose greater than (<tt class="docutils literal"><span class="pre">&gt;=</span></tt>) or smaller than (<tt class="docutils literal"><span class="pre">&lt;=</span></tt>).  But we
want stability, so we keep the double equals sign.</p>
<p>If you now run <tt class="docutils literal"><span class="pre">bin/buildout</span></tt> and then run that one-liner from
Wichert again you will now see that the elementtree line has
disappeared from the output: buildout no longer picks that version for
us as we have pinned it.  We are getting closer to stability!</p>
</div>
<div class="section" id="timeout">
<h3><a name="timeout">Timeout</a></h3>
<p>At this point it is good to say that you could stop here: all Zope and
Plone products and packages are pinned, which is the most important.
Does it really matter if one year from now
<tt class="docutils literal"><span class="pre">plone.recipe.zope2instance</span></tt> is at version 2.0 instead of 1.3?
Probably not.  But there is still room for more stability and
repeatability.  So if you are still interested, let's continue our
quest.</p>
</div>
<div class="section" id="pinning-recipes">
<h3><a name="pinning-recipes">Pinning recipes</a></h3>
<p>Now we start pinning the other recipes that are in the output.  Find
these four lines in your <tt class="docutils literal"><span class="pre">buildout.cfg</span></tt> (they will not be right
below each other):</p>
<pre class="literal-block">
recipe = plone.recipe.zope2install
recipe = plone.recipe.distros
recipe = plone.recipe.zope2instance
recipe = zc.recipe.egg
</pre>
<p>and pin them to specific versions:</p>
<pre class="literal-block">
recipe = plone.recipe.zope2install == 1.2
recipe = plone.recipe.distros == 1.3
recipe = plone.recipe.zope2instance == 1.3
recipe = zc.recipe.egg == 1.0.0
</pre>
<p>Now we run the one-liner again and get:</p>
<pre class="literal-block">
plone.recipe.distros = 1.3
python-openid = 2.0.1
setuptools = 0.6c7
zc.recipe.egg = 1.0.0
</pre>
<p>This may not be what you had expected.  We have pinned
<tt class="docutils literal"><span class="pre">plone.recipe.distros</span></tt> and <tt class="docutils literal"><span class="pre">zc.recipe.egg</span></tt> right?  That is
correct, but look at this partial output of <tt class="docutils literal"><span class="pre">bin/buildout</span></tt> with the
verbose option:</p>
<pre class="literal-block">
$ bin/buildout -v
Installing 'plone.recipe.plone == 3.0.5'.
We have the distribution that satisfies 'plone.recipe.plone==3.0.5'.
Getting required 'plone.recipe.distros'
  required by plone.recipe.plone 3.0.5.
Picked: plone.recipe.distros = 1.3
Getting required 'zc.recipe.egg'
  required by plone.recipe.plone 3.0.5.
Picked: zc.recipe.egg = 1.0.0
</pre>
<p>What happens here is that <tt class="docutils literal"><span class="pre">plone.recipe.plone</span></tt> depends on two other
recipes.  They are in the <tt class="docutils literal"><span class="pre">install_requires</span></tt> option of the
<tt class="docutils literal"><span class="pre">setup.py</span></tt> file of the recipe.  So buildout itself picks a version
of those dependencies.  It does not look at our pinnings at it is
handling the <tt class="docutils literal"><span class="pre">[plone]</span></tt> part of <tt class="docutils literal"><span class="pre">buildout.cfg</span></tt> now and not the
<tt class="docutils literal"><span class="pre">[productdistros]</span></tt> or <tt class="docutils literal"><span class="pre">[zopepy]</span></tt> parts that try to pin versions
for those recipes.</p>
<p>In fact, you can get a conflict with this.  Temporarily we try to pin
<tt class="docutils literal"><span class="pre">plone.recipe.distros</span></tt> to an earlier version:</p>
<pre class="literal-block">
[productdistros]
recipe = plone.recipe.distros == 0.3
</pre>
<p>We run <tt class="docutils literal"><span class="pre">bin/buildout</span></tt>:</p>
<pre class="literal-block">
While:
  Installing.
  Getting section productdistros.
  Initializing section productdistros.
  Loading recipe 'plone.recipe.distros == 0.3'.

An internal error occured due to a bug in either zc.buildout or in a
recipe being used:

VersionConflict:
(plone.recipe.distros 1.3
 (.../plone.recipe.distros-1.3-py2.4.egg),
 Requirement.parse('plone.recipe.distros==0.3'))
</pre>
<p>In this case buildout already picked version <tt class="docutils literal"><span class="pre">1.3</span></tt> and now we tell
it that we require <tt class="docutils literal"><span class="pre">0.3</span></tt> so this conflicts.  How do we solve that?
We change the order in which the buildout parts are executed.
Currently it is this:</p>
<pre class="literal-block">
[buildout]
parts =
    plone
    zope2
    productdistros
    instance
    zopepy
</pre>
<p>Now we make sure that <tt class="docutils literal"><span class="pre">productdistros</span></tt> and <tt class="docutils literal"><span class="pre">zopepy</span></tt> are above
<tt class="docutils literal"><span class="pre">plone</span></tt>:</p>
<pre class="literal-block">
[buildout]
parts =
    productdistros
    zopepy
    plone
    zope2
    instance
</pre>
<p>We run <tt class="docutils literal"><span class="pre">bin/buildout</span> <span class="pre">-v</span></tt> again:</p>
<pre class="literal-block">
Uninstalling productdistros.
While:
  Installing.
  Uninstalling productdistros.
  Loading recipe 'plone.recipe.distros == 1.3'.

An internal error occured due to a bug in either zc.buildout or in a
recipe being used:

VersionConflict:
(plone.recipe.distros 0.3
 (.../plone.recipe.distros-0.3-py2.4.egg),
 Requirement.parse('plone.recipe.distros==1.3'))
</pre>
<p>Oops.  Here we are uninstalling version <tt class="docutils literal"><span class="pre">1.3</span></tt> as that was installed
by the previous buildout run and at the same time we want to install
<tt class="docutils literal"><span class="pre">0.3</span></tt>.  buildout does not like this.  Only solution I know: remove
the <tt class="docutils literal"><span class="pre">.installed.cfg</span></tt> file that is automatically created by buildout.
The function of that file is to keep track of what buildout has
previously installed, so it knows if it should do any uninstalling or
reinstalling or if it can just do nothing and finish within one
second.  In other words: removing that file should be okay.  Anyway,
you <em>are</em> keeping backups, right?</p>
<p>Five minutes later...</p>
<p>Right, we are keeping backups.  We remove that <tt class="docutils literal"><span class="pre">.installed.cfg</span></tt> file
and run <tt class="docutils literal"><span class="pre">bin/buildout</span></tt> again.  This will take a bit longer now, as
among others it compiles Zope again.  At least it completes without
conflicts now, and <tt class="docutils literal"><span class="pre">plone.recipe.distros</span></tt> is not picked by buildout
anymore, but pinned by us.</p>
<p>For some reason <tt class="docutils literal"><span class="pre">zc.recipe.egg</span></tt> is still picked though.  Ah, the 
<tt class="docutils literal"><span class="pre">[zopepy]</span></tt> part that pins this recipe contains this line:</p>
<pre class="literal-block">
extra-paths = ${zope2:location}/lib/python
</pre>
<p>So this part depends on the <tt class="docutils literal"><span class="pre">[zope2]</span></tt> part, which in turn depends on
the <tt class="docutils literal"><span class="pre">[plone]</span></tt> part, which in turn depends on the <tt class="docutils literal"><span class="pre">zc.recipe.egg</span></tt>
package, which is therefore picked by buildout, ignoring our pinning.</p>
<p>Wonderful.</p>
<p>Okay, seems like we have to resort to trickery.  We introduce a new
section <tt class="docutils literal"><span class="pre">[dummy-for-pinning]</span></tt>:</p>
<pre class="literal-block">
[dummy-for-pinning]
recipe = zc.recipe.egg == 1.0.0
eggs = zc.recipe.egg == 1.0.0
</pre>
<p>Yes, I tried this and you need the version number in both lines.  Now
we simply put that section at the top of the buildout parts.  And we
move the <tt class="docutils literal"><span class="pre">[zopepy]</span></tt> section down, as it depends on those other parts
anyway.  So our parts now looks like this:</p>
<pre class="literal-block">
parts =
    dummy-for-pinning
    productdistros
    plone
    zope2
    instance
    zopepy
</pre>
</div>
<div class="section" id="pinning-the-rest">
<h3><a name="pinning-the-rest">Pinning the rest</a></h3>
<p>What does the one-liner tell us?:</p>
<pre class="literal-block">
$ bin/buildout -Novvvvv |sed -ne 's/^Picked: //p' | sort | uniq
python-openid = 2.0.1
setuptools = 0.6c7
zc.buildout = 1.0.0
</pre>
<p><tt class="docutils literal"><span class="pre">zc.buildout</span></tt> is a new one.  This is a requirement of
<tt class="docutils literal"><span class="pre">zc.recipe.egg</span></tt>, though I could not say why it did not end up in
that list earlier.  We can add all three remaining picked packages to
our <tt class="docutils literal"><span class="pre">[dummy-for-pinning]</span></tt> section so it now looks like this:</p>
<pre class="literal-block">
[dummy-for-pinning]
recipe = zc.recipe.egg == 1.0.0
eggs =
    zc.recipe.egg == 1.0.0
    zc.buildout == 1.0.0
    setuptools == 0.6c7
    python-openid == 2.0.1
</pre>
<p>After this we hit the end of the road.  <tt class="docutils literal"><span class="pre">zc.buildout</span></tt> is pinned, but
<tt class="docutils literal"><span class="pre">setuptools</span></tt> and <tt class="docutils literal"><span class="pre">python-openid</span></tt> are still picked for us by
buildout.  The last possibility I can think of is adding those two to
a <tt class="docutils literal"><span class="pre">[versions]</span></tt> section, like this:</p>
<pre class="literal-block">
[versions]
setuptools = 0.6c7
python-openid = 2.0.1
</pre>
<p>But this has no noticeable effect.  In fact, when I change the
<tt class="docutils literal"><span class="pre">setuptools</span></tt> version to <tt class="docutils literal"><span class="pre">0.6c6</span></tt> (so 6 instead of 7) in both cases,
I get this output from buildout:</p>
<pre class="literal-block">
Installing dummy-for-pinning.
Installing 'zc.recipe.egg == 1.0.0', 'zc.buildout == 1.0.0', 'setuptools == 0.6c6', 'python-openid == 2.0.1'.
We have the distribution that satisfies 'zc.recipe.egg==1.0.0'.
We have the distribution that satisfies 'zc.buildout==1.0.0'.
We have the distribution that satisfies 'setuptools==0.6c6'.
We have the distribution that satisfies 'python-openid==2.0.1'.
...
Getting required 'setuptools'
  required by five.customerize 0.2.
  ...
  required by plone.app.kss 1.2.5.
Picked: setuptools = 0.6c7
</pre>
<p>So our pinning of <tt class="docutils literal"><span class="pre">setuptools</span></tt> is ignored.  The same is true for
<tt class="docutils literal"><span class="pre">python-openid</span></tt>:</p>
<pre class="literal-block">
Getting required 'python-openid&gt;=2.0.0,&lt;2.0.999'
  required by plone.openid 1.0.1.
Picked: python-openid = 2.0.1
</pre>
<p>One last resort: introduce a dummy package that requires a specific
version of those two packages in its <tt class="docutils literal"><span class="pre">setup.py</span></tt>.  We add it to our
buildout and see that it gets used correctly:</p>
<pre class="literal-block">
We have the distribution that satisfies 'zest.recipe.dummy==0.3'.
Getting required 'python-openid==2.0.1'
  required by zest.recipe.dummy 0.3.
We have the distribution that satisfies 'python-openid==2.0.1'.
Getting required 'setuptools==0.6c6'
  required by zest.recipe.dummy 0.3.
We have the distribution that satisfies 'setuptools==0.6c6'.
</pre>
<p>But further on in the buildout nothing has changed and buildout still
picks its own versions.</p>
<p>One final twist though: I removed both versions of <tt class="docutils literal"><span class="pre">setuptools</span></tt> from
the eggs directory.  I then ran buildout again.  It again fetched
version 6 and then claimed to have picked version 7, but the only
package that I could actually find, was version 6.  And the second
time I ran buildout, it already had version 6, so it no longer picked
version 7, but version 6.</p>
<p>Are you still with me? :-) Then maybe just a few more random notes
before we get to the conclusions.</p>
<ul class="simple">
<li>Try this: create a new buildout with paster.  Do the usual
<tt class="docutils literal"><span class="pre">python2.4</span> <span class="pre">bootstrap.py</span></tt>.  You will now have downloaded version 7
of <tt class="docutils literal"><span class="pre">setuptools</span></tt> and version 1.0.0 of <tt class="docutils literal"><span class="pre">zc.buildout</span></tt>.  The task of
persuading the bootstrap to give you earlier (or later) versions of
those two packages is left as an exercise to the reader.
Assignments are due next week.</li>
<li>What I had not realized yet: what you put in the <tt class="docutils literal"><span class="pre">[versions]</span></tt>
section influences what goes in the <tt class="docutils literal"><span class="pre">bin/buildout</span></tt> script itself.
I have not looked at what the end-effect here is.</li>
<li>After some of these changes I have seen <tt class="docutils literal"><span class="pre">bin/buildout</span></tt> finish
succesfully and then found that the <tt class="docutils literal"><span class="pre">bin/buildout</span></tt> file was gone.
Running <tt class="docutils literal"><span class="pre">python2.4</span> <span class="pre">bootstrap.py</span></tt> fixes that of course, but it <em>is</em>
strange.</li>
</ul>
</div>
<div class="section" id="conclusions">
<h3><a name="conclusions">Conclusions</a></h3>
<p>A buildout can be made very stable: just put <tt class="docutils literal"><span class="pre">newest</span> <span class="pre">=</span> <span class="pre">false</span></tt> in
your buildout section.  If one year later you accidentally remove the
parts directory, you can rerun buildout and get your original
directory back.  If you remove your eggs though, you are in trouble.</p>
<p>Making a buildout repeatable is more difficult.  The first easy step
is pinning the <tt class="docutils literal"><span class="pre">plone.recipe.plone</span></tt> package.  Any extra packages or
products can be pinned quite easily as well.</p>
<p>What is difficult is pinning dependencies.  If you do not do this
correctly, your pinning will cause a conflict.  The order in which the
buildout parts or sections get executed is important here.</p>
<p>You will have to resort to trickery to get the last few packages
pinned down.  And even then it does not seem possible to pin really
everything.  But we are very close and I think there is a good chance
that the remaining issues will get solved in buildout, setuptools or
easy_install.</p>
</div>
<div class="section" id="bonus">
<h3><a name="bonus">Bonus</a></h3>
<p><tt class="docutils literal"><span class="pre">plone.recipe.plone</span></tt> rigourously depends on specific packages and
products.  So what do you do if you want to use a newer version of
just one or two packages?  For instance, I did some fixes for
<tt class="docutils literal"><span class="pre">plone.locking</span></tt> which are still not in Plone 3.0.5.  And for
multilingual sites you really want to use a newer version with an
important bug fix.  You might at first think that this would be
enough:</p>
<pre class="literal-block">
[plone]
recipe = plone.recipe.plone == 3.0.5
eggs =
    plone.locking == 1.0.5
    plone.app.i18n == 1.0.2
</pre>
<p>But running <tt class="docutils literal"><span class="pre">bin/buildout</span></tt> then gives an error:</p>
<pre class="literal-block">
ValueError:
('Missing distribution spec', '==')
</pre>
<p>This is how you accomplish that:</p>
<pre class="literal-block">
[versions]
plone.locking = 1.0.5
plone.app.i18n = 1.0.2

[plone]
recipe = plone.recipe.plone
eggs =
    plone.locking
    plone.app.i18n
</pre>
<p>To start at the bottom: these lines basically erase the version
pinning of those two packages that is in the recipe.  After that, the
pinning in the <tt class="docutils literal"><span class="pre">[versions]</span></tt> section can take effect.</p>
<p>But in fact, nothing happens just yet.  This is because we are running
buildout in non-newest mode (<tt class="docutils literal"><span class="pre">newest</span> <span class="pre">=</span> <span class="pre">false</span></tt> in the <tt class="docutils literal"><span class="pre">[buildout]</span></tt>
section).  But here we actually do not want stability: we want newer
versions!  So we run buildout in the newest mode, either by
temporarily setting <tt class="docutils literal"><span class="pre">newest</span> <span class="pre">=</span> <span class="pre">true</span></tt> or by calling <tt class="docutils literal"><span class="pre">bin/buildout</span>
<span class="pre">-n</span></tt> once.  Now we get the new packages that we want.  Since we have
pinned almost everything else, this should be quite safe.</p>
</div>
<div class="section" id="the-final-version">
<h3><a name="the-final-version">The final version</a></h3>
<p>Let's end with showing what our <tt class="docutils literal"><span class="pre">buildout.cfg</span></tt> now looks like.  Note
here that the mention of <tt class="docutils literal"><span class="pre">setuptools</span></tt>, <tt class="docutils literal"><span class="pre">zc.buildout</span></tt> and
<tt class="docutils literal"><span class="pre">python-openid</span></tt> in <tt class="docutils literal"><span class="pre">[versions]</span></tt> or <tt class="docutils literal"><span class="pre">[dummy-for-pinning]</span></tt> may not
be too useful.  And I will not fault you if you skip that
<tt class="docutils literal"><span class="pre">[dummy-for-pinning]</span></tt> section entirely.  The reported picked
versions are now:</p>
<pre class="literal-block">
plone.app.i18n = 1.0.2
plone.locking = 1.0.5
python-openid = 2.0.1
setuptools = 0.6c7
</pre>
<p>And here is the file itself:</p>
<pre class="literal-block">
[buildout]
newest = false
index = http://download.zope.org/ppix
parts =
    dummy-for-pinning
    productdistros
    plone
    zope2
    instance
    zopepy

find-links =
    http://dist.plone.org
    http://download.zope.org/ppix/
    http://download.zope.org/distribution/
    http://effbot.org/downloads

# Add additional eggs here
# elementtree is required by Plone
eggs =
    elementtree == 1.2.7-20070827-preview

[dummy-for-pinning]
recipe = zc.recipe.egg == 1.0.0
eggs =
    python-openid == 2.0.1
    setuptools == 0.6c7
    zc.buildout == 1.0.0
    zc.recipe.egg == 1.0.0

[versions]
setuptools = 0.6c7
zc.buildout = 1.0.0
plone.locking = 1.0.5
plone.app.i18n = 1.0.2

[plone]
recipe = plone.recipe.plone == 3.0.5
eggs =
    plone.locking
    plone.app.i18n

[zope2]
recipe = plone.recipe.zope2install == 1.2
url = ${plone:zope2-url}

[productdistros]
recipe = plone.recipe.distros == 1.3
urls =
nested-packages =
version-suffix-packages = 

[instance]
recipe = plone.recipe.zope2instance == 1.3
zope2-location = ${zope2:location}
user = admin:
http-address = 8080
#debug-mode = on
#verbose-security = on

# If you want Zope to know about any additional eggs, list them here.
# This should include any development eggs you listed in develop-eggs above,
# e.g. eggs = ${buildout:eggs} ${plone:eggs} my.package
eggs =
    ${buildout:eggs}
    ${plone:eggs}

# If you want to register ZCML slugs for any packages, list them here.
# e.g. zcml = my.package my.other.package
zcml = 

products =
    ${buildout:directory}/products
    ${productdistros:location}
    ${plone:products}

[zopepy]
recipe = zc.recipe.egg == 1.0.0
eggs = ${instance:eggs}
interpreter = zopepy
extra-paths = ${zope2:location}/lib/python
scripts = zopepy
</pre>
</div>

          ]]>
        </content:encoded>        

        <dc:date>2008-01-19T02:23:11+01:00</dc:date>

        <dcterms:modified>2008-01-30T23:19:54+01:00</dcterms:modified>

        <dc:creator>Maurits van Rees</dc:creator>

        

        
            <dc:subject>plone</dc:subject>
        
        
            <dc:subject>zest</dc:subject>
        

    </rss:item>

    
    

    <rss:item rdf:about="http://maurits.vanrees.org/weblog/archive/2007/11/search-forms-with-zope-formlib-and-batching">

        <rss:title>Search forms with zope formlib and batching</rss:title>

        <rss:link>http://maurits.vanrees.org/weblog/archive/2007/11/search-forms-with-zope-formlib-and-batching</rss:link>       

        <rss:description>Combine a search form and a results page by using zope.formlib and plone.app.content.batching.</rss:description>

        <content:encoded>
          <![CDATA[
          <p>In this tutorial we want to have a search form on our web site.  After
a visitor fills in the form he should see a page with results.  But on
that same page he should see the search form again, with his previous
values filled in.  On top of that, the results should be batched,
displaying only the first ten results and having links to the next
pages.  On Plone 3.0 you can do this by combining zope.formlib and
plone.app.content.batching.</p>
<p>Some details are left out, like explaining how files and classes are
called and where they are located (most are in the browser/
directory), or not showing some methods whose goal and code are
hopefully clear enough from their name.  The idea is not to make this
too long and I am failing at that already. :-) If I omitted too much
for your taste and you have a specific question, just ask.</p>
<div class="section" id="building-search-forms">
<h3><a name="building-search-forms">Building search forms</a></h3>
<p>We start with a browser view.  On the top we need some imports:</p>
<pre class="literal-block">
from zope import schema
from zope.interface import Interface
from zope.interface import implements
from zope.formlib import form
from Products.Five.formlib import formbase
</pre>
<p>With our search form we want to search for some searchable text and
for Products of a specific Brand.  Brand is a content type we (<a class="reference" href="http://zestsoftware.nl">Zest
Software</a>) made for a customer.  A Product is another content type,
which is added to a Brand.  We made a vocabulary for this which maps
the title of a Brand (shown in the form) to the path where this Brand
is found.</p>
<p>We define an Interface for our search form.  Very important: let the
parameters match the names of the catalog indices that you want to
search on:</p>
<pre class="literal-block">
class ISearchForm(Interface):
    &quot;&quot;&quot;These are the fields of our search form.
    &quot;&quot;&quot;
    path = schema.Choice(title = _(u'Brand'),
        vocabulary=u&quot;customer.brand&quot;,
        description = _(u'Brand, mark, formula.'),
        required = False,
    )
    SearchableText = schema.TextLine(title = _(u'Search word'),
        description = _(u'Search for specific words.'),
        required = False,
    )
</pre>
<p>For schema.Choice the default widget is a SelectWidget or
RadioWidget.  As empty value it displays &quot;(no value)&quot; in the drop down
box.  At least for a Dutch web site this is not very nice, as there is
no translation.  You can provide an own version of that message by
doing something like this:</p>
<pre class="literal-block">
from customer.product import customerMessageFactory as _
from zope.app.form.browser.itemswidgets import SelectWidget
SelectWidget._messageNoValue = _(&quot;vocabulary-missing-single-value-for-edit&quot;,
                      &quot;Selecteer indien gewenst een waarde.&quot;)
</pre>
<p>Or do this in English and use i18ndude of course.</p>
<p>Now write a class that inherits from:</p>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">Products.Five.formlib.formbase.PageForm</span></tt> to have a complete page.</li>
<li><tt class="docutils literal"><span class="pre">Products.Five.formlib.formbase.SubPageForm</span></tt> to get a partial page.</li>
</ul>
<p>In our case the search form will be only part of a page, so we choose
the second option:</p>
<pre class="literal-block">
class Search(formbase.SubPageForm):
    implements(ISearchForm)
    form_fields = form.FormFields(ISearchForm)
    label = _(u&quot;Working independently&quot;)
    description = _(u&quot;You are looking for a product for:&quot;)
</pre>
<p>Add an action button to that class:</p>
<pre class="literal-block">
&#64;form.action(_(u&quot;Search&quot;))
def action_search(self, action, data):
    &quot;&quot;&quot;Perform search.
    &quot;&quot;&quot;
</pre>
<p>On a SubFormPage this can actually be empty (<tt class="docutils literal"><span class="pre">pass</span></tt>): the
surrounding form tag that you have to supply yourself takes care of
redirecting.  For a complete FormPage you would at least need
something like this:</p>
<pre class="literal-block">
self.request.response.redirect(target)
</pre>
<p>where target should be a page with search results.</p>
</div>
<div class="section" id="search-form-and-results-on-one-page">
<h3><a name="search-form-and-results-on-one-page">Search form and results on one page</a></h3>
<p>Hook up your browser view in configure.zcml.  We only register this
view for the Site Root in this case:</p>
<pre class="literal-block">
&lt;page
    name=&quot;product-search&quot;
    class=&quot;.search.Search&quot;
    for=&quot;Products.CMFCore.interfaces.ISiteRoot&quot;
    permission=&quot;zope.Public&quot;
    allowed_interface=&quot;.search.ISearchForm&quot;
    /&gt;
</pre>
<p>Same for a results page:</p>
<pre class="literal-block">
&lt;page
    name=&quot;results&quot;
    class=&quot;.results.Results&quot;
    template=&quot;products.pt&quot;
    for=&quot;*&quot;
    permission=&quot;zope.Public&quot;
    allowed_interface=&quot;.results.IResults&quot;
    /&gt;
</pre>
<p>And the main page showing search plus results:</p>
<pre class="literal-block">
&lt;page
    name=&quot;main-search&quot;
    template=&quot;searchpage.pt&quot;
    for=&quot;Products.CMFCore.interfaces.ISiteRoot&quot;
    permission=&quot;zope.Public&quot;
    allowed_interface=&quot;.search.ISearchForm&quot;
    /&gt;
</pre>
<p>Use something like <tt class="docutils literal"><span class="pre">CMFPlone/skins/plone_content/document_view.pt</span></tt>
as base and add the structure of the search and results subpages:</p>
<pre class="literal-block">
&lt;html ...
      metal:use-macro=&quot;here/main_template/macros/master&quot;&gt;
&lt;body&gt;

&lt;metal:main fill-slot=&quot;main&quot;&gt;
...

        &lt;div tal:replace=&quot;structure provider:plone.belowcontenttitle&quot; /&gt;

        &lt;form action=&quot;&quot; method=&quot;get&quot;&gt;
          &lt;div tal:replace=&quot;structure context/product-search&quot; /&gt;
        &lt;/form&gt;

        &lt;div tal:replace=&quot;structure context/results&quot; /&gt;

        &lt;div tal:replace=&quot;structure provider:plone.belowcontentbody&quot; /&gt;
...
&lt;/metal:main&gt;

&lt;/body&gt;
&lt;/html&gt;
</pre>
</div>
<div class="section" id="overwriting-the-search-form-template">
<h3><a name="overwriting-the-search-form-template">Overwriting the search form template</a></h3>
<p>If the default template from zope.formlib does not give you what you
want, you overwrite it.  Configure some named adapters in zcml:</p>
<pre class="literal-block">
&lt;adapter
    factory=&quot;zope.formlib.form.default_subpage_template&quot;
    name=&quot;default.subform&quot; /&gt;
&lt;adapter
    factory=&quot;.search.subpage_template&quot;
    name=&quot;customer.search&quot; /&gt;
</pre>
<p>The factory for the first adapter is in zope.formlib.  Our own
alternative factory is this:</p>
<pre class="literal-block">
from zope.formlib import interfaces, namedtemplate
from zope.app.pagetemplate import ViewPageTemplateFile
subpage_template = namedtemplate.NamedTemplateImplementation(
    ViewPageTemplateFile('searchform.pt'), interfaces.ISubPageForm)
</pre>
<p>Let your class know it should use the new template:</p>
<pre class="literal-block">
class Search(formbase.SubPageForm):
    ...
    original_template = namedtemplate.NamedTemplate('default.subform')
    template = namedtemplate.NamedTemplate('customer.search')
</pre>
<p>Now write the template, using the original template via the
<tt class="docutils literal"><span class="pre">original_template</span></tt> attribute from the view.  In this case we add
the form description in a slot:</p>
<pre class="literal-block">
&lt;metal:form use-macro=&quot;view/original_template/macros/form&quot;&gt;
  &lt;div metal:fill-slot=&quot;extra_info&quot;&gt;
    &lt;h2 tal:content=&quot;view/description&quot;&gt;A nice description&lt;/h2&gt;
  &lt;/div&gt;
&lt;/metal:form&gt;
</pre>
</div>
<div class="section" id="remembering-form-values">
<h3><a name="remembering-form-values">Remembering form values</a></h3>
<p>The form now submits to itself.  Currently its values are forgotten.
So we fix that:</p>
<pre class="literal-block">
from zope.formlib.form import setUpWidgets

class Search(formbase.SubPageForm):
    ...
    # We set an empty prefix, otherwise we would end up with
    # 'form.SearchableText', etc, in the request while the code here and in
    # results.py expects 'SearchableText'.
    prefix = ''

  def setUpWidgets(self, ignore_request=False):
      &quot;&quot;&quot;From zope.formlib.form.Formbase.
      
      Difference: pass extra data=self.request.form.
      &quot;&quot;&quot;
      self.adapters = {}
      self.widgets = setUpWidgets(
          self.form_fields, self.prefix, self.context, self.request,
          form=self, adapters=self.adapters, ignore_request=ignore_request,
          data=data)
</pre>
<p>While we are here, let's fix a possible unicode error.  There is a
difference between getting a value from the request or from
request.form when unicode is involved:</p>
<pre class="literal-block">
&gt;&gt;&gt; request.form.get('SearchableText')
u'\xff'
&gt;&gt;&gt; request.get('SearchableText')
'\xc3\xbf'
</pre>
<p>In the method
<tt class="docutils literal"><span class="pre">zope.app.form.browser.textwidgets.TextWidget._getFormInput()</span></tt> the value
is fetched from the request and not request.form.  So you get a
UnicodeDecodeError.  We need to guard against that:</p>
<pre class="literal-block">
def setUpWidgets(self, ignore_request=False):
    &quot;&quot;&quot;From zope.formlib.form.Formbase.
    &quot;&quot;&quot;
    self.adapters = {}
    fieldnames = [x.__name__ for x in self.form_fields]
    data = {}
    for key in fieldnames:
        value = self.request.form.get(key)
        if value is not None and not value == u'':
            data[key] = value
            self.request[key] = value
    
    self.widgets = setUpWidgets(
        self.form_fields, self.prefix, self.context, self.request,
        form=self, adapters=self.adapters, ignore_request=ignore_request,
        data=data)
</pre>
</div>
<div class="section" id="batching-on-the-results-page">
<h3><a name="batching-on-the-results-page">Batching on the results page</a></h3>
<p>The search form is working fine now.  So we move on the the search
results.  The results template can be quite simple: a <tt class="docutils literal"><span class="pre">ul</span></tt> with an
<tt class="docutils literal"><span class="pre">li</span></tt> for every search result if that is enough for you.  The only
interesting part is batching:</p>
<pre class="literal-block">
&lt;div
    tal:condition=&quot;view/has_results&quot;&gt;
  &lt;table class=&quot;listing&quot;&gt;
  ...
  &lt;/table&gt;
  &lt;tal:batch replace=&quot;structure view/batching&quot; /&gt;
&lt;/div&gt;
</pre>
<p>So we need a view with attributes <tt class="docutils literal"><span class="pre">has_results</span></tt> and <tt class="docutils literal"><span class="pre">batching</span></tt>.
This is the base of the browser view:</p>
<pre class="literal-block">
from plone.app.content.batching import Batch
class IResults(Interface):
    &quot;&quot;&quot;List of Products.
    &quot;&quot;&quot;

    has_results = Attribute(&quot;The search has matching results.&quot;)
    items = Attribute(&quot;List of Products&quot;)
    batch = Attribute(&quot;Batch of brains&quot;)
    url = Attribute(&quot;URL for this context&quot;)


class Results(BrowserView):
    implements(IResults)

    # We want to use the batching.pt file from plone.app.content, but
    # that has a few drawbacks so we copied it ourselves.
    batching = ViewPageTemplateFile('batching.pt')
</pre>
<p>We overwrite it because it has one flaw.  It has a question mark where
we want an ampersand, so we can add more options in the url.  It was:</p>
<pre class="literal-block">
tal:attributes=&quot;href string:${view/url}?pagenumber=${batch/previouspage}&amp;sort_on=${request/sort_on|string:getObjPositionInParent}&quot;&gt;
</pre>
<p>and we change that to:</p>
<pre class="literal-block">
tal:attributes=&quot;href string:${view/url}&amp;pagenumber=${batch/previouspage}&amp;sort_on=${request/sort_on|string:getObjPositionInParent}&quot;&gt;
</pre>
<p>This change means we can add our filled in search terms (path,
SearchableText) to the url method of the view:</p>
<pre class="literal-block">
&#64;property
def url(self):
    &quot;&quot;&quot;Base url, needed by the batching template.&quot;&quot;&quot;
    url = self.context.absolute_url()
    terms = [&quot;%s=%s&quot; % (key, value) for key, value in self.search_filter.items()]
    query = '&amp;'.join(terms)
    return url + '?' + query
</pre>
<p>We add a search_filter to our view that gets the filled in values from
our search form:</p>
<pre class="literal-block">
&#64;property
&#64;memoize
def search_filter(self):
    &quot;&quot;&quot;Construct search filter.

    Only add valid search terms from the request.
    &quot;&quot;&quot;
    context = aq_inner(self.context)
    form = self.request.form
    search_filter = {}
    for key in ['path', 'SearchableText']:
        value = form.get(key)
        if value is not None and not value == u'':
            search_filter[key] = value
    # When viewing a Brand, add its path to the filter.
    if search_filter.get('path') is None:
        if IBrand.providedBy(context):
            search_filter['path'] = '/'.join(context.getPhysicalPath())
    return search_filter
</pre>
<p>Incidentally, our search form and results will also be used on the
view of a Brand, which is why the last few lines were added.</p>
<p>Our view needs a batch property:</p>
<pre class="literal-block">
&#64;property
def batch(self):
    &quot;&quot;&quot;Batch of Products (brains).
    &quot;&quot;&quot;
    context = aq_inner(self.context)
    # We only search for Products.  We need to copy the
    # search_filter as we need it original contents somewhere
    # else, without the portal_type.
    search_filter = self.search_filter.copy()
    search_filter['portal_type'] = 'Product'
    catalog = getToolByName(context, 'portal_catalog')
    brains = catalog.searchResults(search_filter)
    batch = Batch(items=brains, pagesize=10,
                  pagenumber=self.pagenumber, navlistsize=5)
    return batch
</pre>
<p>We use that batch in the shown <tt class="docutils literal"><span class="pre">batching.pt</span></tt> template, but also in
our own view, as we do not want to pass brains to our template, but a
nice list of dictionaries:</p>
<pre class="literal-block">
def items(self):
    &quot;&quot;&quot;List of Products.

    Here we get some info for all the Products that are in the
    current page of the batch.
    &quot;&quot;&quot;

    batch = self.batch
    items = []
    for brain in batch:
        product = brain.getObject()
        info = dict(
            url=product.absolute_url(),
            title=product.Title(),
            isbn=product.getIsbn(),
            )
        items.append(info)        
    return items
</pre>
<p>There you have it: a search form with batched results on the same
page.  And all thanks to the authors of zope.formlib and
plone.app.content.batching!</p>
</div>

          ]]>
        </content:encoded>        

        <dc:date>2007-11-23T19:24:33+01:00</dc:date>

        <dcterms:modified>2008-01-30T23:19:02+01:00</dcterms:modified>

        <dc:creator>Maurits van Rees</dc:creator>

        

        
            <dc:subject>plone</dc:subject>
        
        
            <dc:subject>zest</dc:subject>
        

    </rss:item>

    
    

    <rss:item rdf:about="http://maurits.vanrees.org/weblog/archive/2007/11/american-oil-consumption">

        <rss:title>American oil consumption</rss:title>

        <rss:link>http://maurits.vanrees.org/weblog/archive/2007/11/american-oil-consumption</rss:link>       

        <rss:description>HOW much oil do the Americans consume???</rss:description>

        <content:encoded>
          <![CDATA[
          
<p>I was struck by the text accompanying today's <a href="http://photography.nationalgeographic.com/photography/photo-of-the-day/monster-truck-jump-pennsylvania.html">Photo of the Day</a> by National Geographic:</p>
<blockquote class="pullquote">
<p>The U.S. slurps up to a quarter of the world's oil—about three gallons
(11 liters) a person every day—even though it has just 5 percent of the
world's population.</p>
</blockquote>
<p>Pretty bizarre numbers...<br /></p>

          ]]>
        </content:encoded>        

        <dc:date>2007-11-17T02:58:29+01:00</dc:date>

        <dcterms:modified>2008-01-30T23:18:40+01:00</dcterms:modified>

        <dc:creator>Maurits van Rees</dc:creator>

        


    </rss:item>

    
    

    <rss:item rdf:about="http://maurits.vanrees.org/weblog/archive/2007/10/plone-3-0-and-instancemanager">

        <rss:title>Plone 3.0 and instancemanager</rss:title>

        <rss:link>http://maurits.vanrees.org/weblog/archive/2007/10/plone-3-0-and-instancemanager</rss:link>       

        <rss:description>Two quick instancemanager configs for using Plone 3.0</rss:description>

        <content:encoded>
          <![CDATA[
          <p>Buildout is all the rage now in Zope and Plone land.  I am using it more and more myself.  But instancemanager still works fine for me too.   I heard someone having problems getting instancemanager working with 3.0, so here are two config files for that.</p>
<p>First with the official Plone 3.0 tar file:</p>
<pre class="literal-block">
zope_version = '2.10.4'
archivebundle_sources = [
    dict(url='http://plone.googlecode.com/files/Plone-3.0.tar.gz',
         internalBundles=['Products', 'lib']),
    ]
</pre>
<p><tt class="docutils literal"><span class="pre">internalBundles</span></tt> is the key here.  It tells instancemanager that the tar ball has two directories that have products in them.  Not those directories but only their contents should be put in the correct directories in the instance.  Since one of those directories is called <tt class="docutils literal"><span class="pre">lib</span></tt> instancemanager knows that it has to put its contents in the <tt class="docutils literal"><span class="pre">lib</span></tt> directory of the instance instead of in Products.</p>
<p>And here is a version using svn checkouts, also showing an alternative way to specifying the dictionaries:</p>
<pre class="literal-block">
zope_version = '2.10.4'
symlinkbundle_sources = [
    {'url': 'https://svn.plone.org/svn/plone/bundles/3.0'},
    {'url': 'https://svn.plone.org/svn/plone/bundles/3.0-lib',
     'pylib': True},
    ]
</pre>
<p>Here <tt class="docutils literal"><span class="pre">pylib</span></tt> tells instancemanager to link the contents into the <tt class="docutils literal"><span class="pre">lib/python</span></tt> directory.</p>

          ]]>
        </content:encoded>        

        <dc:date>2007-10-16T11:12:38+02:00</dc:date>

        <dcterms:modified>2008-01-30T23:19:41+01:00</dcterms:modified>

        <dc:creator>Maurits van Rees</dc:creator>

        

        
            <dc:subject>instancemanager</dc:subject>
        
        
            <dc:subject>plone</dc:subject>
        

    </rss:item>

    
    

    <rss:item rdf:about="http://maurits.vanrees.org/weblog/archive/2007/10/getpaid-making-money-with-plone">

        <rss:title>GetPaid - Making money with Plone</rss:title>

        <rss:link>http://maurits.vanrees.org/weblog/archive/2007/10/getpaid-making-money-with-plone</rss:link>       

        <rss:description>Plone conference 2007, Naples.
Speaker: John Lenton
Company: Except</rss:description>

        <content:encoded>
          <![CDATA[
          <p>Plone conference 2007, Naples.
Speaker: John Lenton
Company: Except</p>
<p>(with many thanks to Kapil Thangavelu (who helped prepare but could
not give this presentation) and Chris Johnson)</p>
<p>Show of hands: about half of the people attending are integrators and
the other half developers.</p>
<p>E-commerce is hard.  There is astounding complexity: payment
processing, shipping, discounts, taxes, etcetera.  Every one of those
items is essential to somebody.  So if you want to please everyone you
need to have all of that in your system.</p>
<p>Getpaid does not do that.  It tries to be a minimal framework.  It
uses zope 3 style python packages on one side and plone content
integration and UI on the other.  It has no content types of its own,
so you are not forced to use say GetPaidBook or GetPaidDVD because
they do not exist.  You can use the zope 3 adapters of getpaid on your
own content types or the core Plone content types.  This means it is
pretty small and clean.</p>
<p>Getpaid is currently in production on a few sites.  There is:</p>
<ul class="simple">
<li>Content integration (like mentioned above), you can make content
items payable.</li>
<li>a shopping cart</li>
<li>pluggable order workflows.  It uses the hurry.workflow package.  It
adds an adapter and parallel workflow.</li>
<li>order history</li>
<li>order types: shipable, donation orders.  Classify and introspect
orders.</li>
<li>order management: you can tracks workflow changes, searching,
reports, import and export.</li>
<li>payment processors:<ul>
<li>authorize.net: synchronous payment, for US-only merchant accounts</li>
<li>ogone.com: asynchronous, for EU-only merchant accounts probably.</li>
<li>more to come</li>
</ul>
</li>
<li>order payments: workflow driven.  Synchronous, asynchronous, and
someone wants to do offline payment to (that would be me :), <em>ed.</em>)</li>
<li>admin interface: very simple, needs more UI love</li>
<li>internationalisation and localisation.  getpaid.core and
PloneGetPaid are mostly i18n, for about five languages now.</li>
</ul>
<p>5 examples of best technologies that we use:</p>
<ul class="simple">
<li>multistep wizard views</li>
<li>using formlib and viewlets all round</li>
<li>custom indexing and querying</li>
<li>zope3 workflow engine (hurry.workflow) which is unbelievably simple</li>
<li>doctests, event subscibers and more</li>
</ul>
<p>Work in progress:</p>
<ul class="simple">
<li>We currently support any currency, but only one at the same time, so
we want to do something there.</li>
<li>product catalog</li>
<li>UPS shipping</li>
<li>Plone 3</li>
<li>etc</li>
</ul>
<p>Wishlist: pure zope 3 UI, as that is the only part that is Plone
dependent now.</p>
<p>We have a sprint here this weekend, so join us to finish version 1.0.</p>
<div class="section" id="customizing">
<h3><a name="customizing">Customizing</a></h3>
<ul class="simple">
<li>Use a policy; see Martin Aspeli's talk.</li>
<li>Come to the sprint and learn by <em>writing</em> an example. :)</li>
<li>Wait until after the sprint and learn from <em>reading</em> the example.</li>
</ul>
<p>Everything is pluggable, as it is pure zope 3, which helps a lot in
customizing.</p>
</div>
<div class="section" id="questions">
<h3><a name="questions">Questions?</a></h3>
<p>Is there SQL database integration?  No, but you could use sqlalchemy.</p>
<p>What do you mean with a product catalog?  I mean that you can query
for all products in a category.  Could be done by querying the
portal_catalog, but that would tie it to Plone, which we want to
avoid.</p>
<p>Is there a demosite?  Yes: <a class="reference" href="http://dev.plonegetpaid.com">http://dev.plonegetpaid.com</a></p>
</div>

          ]]>
        </content:encoded>        

        <dc:date>2007-10-12T14:42:47+02:00</dc:date>

        <dcterms:modified>2008-01-30T23:23:59+01:00</dcterms:modified>

        <dc:creator>Maurits van Rees</dc:creator>

        

        
            <dc:subject>getpaid</dc:subject>
        
        
            <dc:subject>plone</dc:subject>
        
        
            <dc:subject>ploneconf2007</dc:subject>
        

    </rss:item>

    
    

    <rss:item rdf:about="http://maurits.vanrees.org/weblog/archive/2007/10/untested-code-is-broken-code">

        <rss:title>Untested code is broken code</rss:title>

        <rss:link>http://maurits.vanrees.org/weblog/archive/2007/10/untested-code-is-broken-code</rss:link>       

        <rss:description>Plone conference 2007, Naples.
Speakers: Philipp von Weitershausen and Martin Aspeli
</rss:description>

        <content:encoded>
          <![CDATA[
          
<p>Plone conference 2007, Naples.
Speakers: Philipp von Weitershausen and Martin Aspeli</p>
<p>"I know I should write tests, but I will just let my customer or the
community do that for me.  They should just report bugs."  Not a good
idea, especially if your app only fails in some code that only gets
executed by your boss.  He will not be happy if it fails.</p>
<p>So first write a test, then start coding.  That is Test Driven
Development (TDD).  Core developers should know that and should not
need to follow this talk. :)</p>
<p>With TDD you catch design mistakes early on.  It can keep your code
simple: if the tests all pass, why would you add more code because you
<em>think</em> you might need it in the future, complicating the code?</p>
<p>Tests should exercise API.  Demonstrate how to use them.  Other
developers are happy with this kind of tested documentation.  You do
this with doctests.  They look like a python interpreter session with
some paragraphs in between.  We use restructured text, so it can be
turned into html and pdf and is still readable on its own.</p>
<p>We also have Documentation Driven Development (DDD).  You write
doctests first.  You write a science fiction story.  You tell it to an
imaginary user.  Just use the words "we" and "you".  You can put that
story on the product homepage (plone.org, PyPI).  It helps you keep in
mind who you are actually talking to, instead of making documentation
that only you or some core developers can understand.</p>
Now Martin Aspeli gave a demo. He just wrote to the attendees list giving some links. I am sure he will not mind if I quote him here so others can read it too:<br /><br />
<blockquote class="pullquote">I've checked in the examples to my two talks in the collective:<br /><br />  - <a href="http://svn.plone.org/svn/collective/examples/policy-buildout/">http://svn.plone.org/svn/collective/examples/policy-buildout/</a> contains the sample code for the "Extending and customising Plone 3" talk. The slides are there too, in PDF format.<br /><br />  - <a href="http://svn.plone.org/svn/collective/examples/example.tests/">http://svn.plone.org/svn/collective/examples/example.tests/</a> contains boilerplate examples for the different types of tests covered in the "Untested code is broken code" talk, which I gave with Philipp von Weitershausen this morning. This may be useful as it has well-commented test setup examples. I always copy and paste this stuff between my products, so now hopefully we can keep this in one place.</blockquote>
<br />
<p></p>
<br />
          ]]>
        </content:encoded>        

        <dc:date>2007-10-12T12:25:00+02:00</dc:date>

        <dcterms:modified>2008-01-30T23:23:47+01:00</dcterms:modified>

        <dc:creator>Maurits van Rees</dc:creator>

        

        
            <dc:subject>plone</dc:subject>
        
        
            <dc:subject>ploneconf2007</dc:subject>
        

    </rss:item>

    

</rdf:RDF>
