Thursday, April 19, 2007
The book Web Component Development with Zope 3, 2nd Ed. by Philipp von Weitershausen has been on my wishlist for a while now and I finally got around to ordering it. I only got it last night and already I've made it half way through, though certainly I will re-read it all several times. The book offers very excellent descriptions of the component architecture and its applications throughout the rest of the Zope 3 framework. The progression of chapters in the book shows the reuse of the basic building blocks of interfaces, adapters & utilities. And one of the things I also liked was the "Rocky says" section where the relevant technologies of J2EE were constrasted with those of Zope. The explanation of ZCML in the book finally made it clear to me. ZCML is on purpose ;) It forces a separation of roles and make sure that things that would be considered 'configuration' are easily accessible to a non-programmer like a system administrator or integrator. My impression so far the from the book is one that really showcases Zope 3 as a enterprise-grade framework that is solidly Pythonic. For more info you can check' the website for Web Component Development with Zope 3, 2nd Ed.
Monday, April 16, 2007
How annoying is it to deploy an application? How prone to errors due to the sheer repetitiveness of the common deployment? Buildouts to the rescue! What is a buildout? It's a automated set of steps for creating a deployment environment. This could mean one little application, or it could be several and they would setup to talk to each other. zc.buildout came out sometime last year and I've had my eye on it since then. I'd wanted to do Jim Fulton's tutorial on it at Pycon this year but wasn't able to schedule it in! I've had the opportunity in the last couple weeks to start using a bit more and I really appreciate the conceptual basis for this framework. The idea that a deployment consists of parts is something you can explain to anyone, for example. A web app needs a webserver, some kind of storage backend, the application code and some preexisting data: parts=apache mysql application-data application or full Zope-based solution: parts=apache zope zeo plone mywebsite mywebsite-data What I've noticed so far is that for a particular application even though someone might have already wrote a recipe for it actually getting it configured the way you want usually requires extending that recipe slightly. If the recipe was written with this in mind its easy enough to extend. I did have a bit of problems extending some of the plone.recipe.* recipes because they were old style classes and so I couldn't use super() to extend the default behaviour. Easy to fix though!
ZOPE / ZEO buildout recipe with multiple database supportI created a branch that adds the ability to configure multiple databases in your configuration files which I needed for a project, so this should be a fairly decent example for anyone else needed to something similar. See the jbb666-multiple-dbs branch for zeo instance and the corresponding branch for the zope recipe. For a lot of the Zope recipes the config knobs that need to be exposed will be determined and you won't need to touch the underlying recipe except in well exceptional circumstances.
Thursday, April 12, 2007
Copying sites has recently gotten a lot better since 2.5.2 fixed some bugs with modification times getting reset but still you generally can't use copy & paste to copy sites as I have found it doesn't retain the review state of your documents (and this is by design actually I think). Another approach is to import/export. This actually works great so I put together a script that will automate this process. You need to call this from either an External Method or from zopectl debug (or ipython). That's an exercise up to the reader... # moveSites.py
# Move a Plone site without losing the modification times and workflow status # we rely on export/import to do this # You need to provide a valid REQUEST so that the import doesn't fail # if running from zopectl debug you can use makerequest to wrap your app object # with a fake request # Author: Jordan Baker (jbbNOASPM@scryent.com) import tempfile import os def moveSite(portal, new_location): # export the site to a tempfile f = tempfile.NamedTemporaryFile() portal._p_jar.exportFile(portal._p_oid, f) # re-import in the correct location f.seek(0) new_location._importObjectFromFile(f, verify=False, set_owner=False) # delete the old site oid = portal.id portal.aq_parent.manage_delObjects(ids=[oid]) # update the catalog in the new site new_location[oid].portal_catalog.refreshCatalog(clear=True) # NamedTemporaryFile should delete the underlying temporary file # when its object is garbage collected