Friday, January 3, 2003

Big Alpha Releases for Zope and Python

Two big alpha releases were made for the new year: Python 2.3a1 and Zope 3X a1.

Python 2.3 doesn't make any major changes to the language (unlike previous Python 2 series releases, which brought things like list comprehensions, generators, nested scopes, iterators, etc). Andrew Kuchling, as always, covers the changes extensively. Of interest are - ability to import from .zip files, universal newline support!, a new logging package, a new Set datatype and default Boolean datatype.

Zope 3X (x for "experimental" - a final Zope 3 release without the 'X' is expected to have some Zope 2 migration features) is a completely different beast from its ancestors. Its primary focus is still the Object Publishing mission that's been in place since the days of Bobo, but beneath the covers it is shockingly different from Zope's 1 and 2 before it.

Zope 3 is also dubbed the component architecture project. Its design focuses on many interacting components with well-defined interfaces. It's an aggregation heavy design, as opposed to the inheritance heavy design of Zope 2. Adapters exist to take the burden off of objects for out-of-scope elements such as text indexing or sorting-by-size. As the author of a particular object, you can implement those interfaces (ISearchableText, ISized) on the class itself, or as separate classes. Code that requires searchable text or sizing information asks for an ISearchableText implementation for your class, and since that's the only interface that it's expecting to use, it doesn't matter if it gets an adapter or your class - it only matters that the ISearchableText interface is implemented correctly. Design by Contract finally makes a strong appearance in the Zope world.

Zope 3 should also score big on the packaging and deployment front. Zope 3 uses a new configuration language called ZCML. ZCML is used to register new components at load time, and to load in still further components. It wrests control away from Python's import statements and need for special functions in __init__.py such as the common Zope 2 initialize(context). As such, it can be not only more expressive, but allows control over the order in which items get initialized. Under the mantra of explicit is better than implicit, all new components have to be explicitly added (usually in the products.zcml file). A side effect of this is that heavily customized Zope distributions can be made. Some such distributions exist now with Plone installers and BizarShop. Zope 3's customization and configuration capabilities should allow similar distributions to be made that don't look like Zope at all, while still tying in to all of the available features of Zope.

The combination of heavy Interface use combined with rich configuration options should mean that any part of the system could be kicked out in place of a new one, as long as the expected interfaces are implemented. This is a fundamental feature of component systems, and Zope 3 looks like it will live up to this feature.

Another big feature of Zope 3 is the proliferation of View Components. Views can be individual ZPT pages, attached to a particular content interface via ZCML. But they can also be full-on components in their own right, usually as Python classes. And they're not limited to HTML. Other views may be written to correspond with the other publishing channels (ftp, xml-rpc, and others in the future). I wrote a post back in September about my early experiments augmenting other Zope 3 components, in which I include some example code making an XML-RPC view onto a Job Board component written by someone else. My final paragraph in that post reads:

And finally, Zope 3 should yield a usable scalable means of adapting the works of other developers into new solutions by providing better control of product/service/view configuration and overrides, such as adding a new XML-RPC API to someone elses bug tracking system without having to alter that bug tracking system, or use secret Python hacks to alter behaviour.

A few other positive notes about Zope 3X a1. The "grand renaming" went into effect during the final weeks of the beta. This involved cleaning up the Python package hierarchy. It also involved case-normalization of package and module names. They are now all lowercase, like most other well-written Python packages/frameworks (distutils, docutils, etc), which makes it easy to distinguish classes and other module exports from the modules themselves. Zope 3 also uses Python 2.2 "new-style-classes" and gets rid of ExtensionClasses, since now you can write new extension types for Python in C and subclass them (which was the big point of ExtensionClasses). Zope 3 also (finally) makes use of other long-standing Python technologies such as distutils.

Now for the negative aspects. Since this is an alpha of the Zope 3 "experimental" line, it's not surprising that there is little or no documentation. The code structure is significantly different from that of Zope 2. It takes some time to find ones way around the code layout. Most things are pretty clear though (a benefit of having Interfaces) when you do find them, but there's so much new technology and terminology here that even when you grasp the terminology, it's not obvious to an outsider how to put it all to work.

Zope 3 is heavily reliant on Services, which is a good thing. Services are like Tools in the CMF - well known objects that provide a service to a global or local region. Examples of services are Event Channels (yay! Events!), or something like the Error Log that showed up in Zope 2.6. Other examples of Services are Database Adapters. In Zope 2, most service objects existed in the same namespace as all other objects. Zope 3 manages them in special namespaces. This allows content objects to be managed separately from service objects while still retaining placefulness. There are numerous upsides to a service based architecture. What's the downside? The downside is there's significant "what the...?!" effect when first encountering Services and Configuration objects. I'm sure it will all make more sense as future Zope 3X development releases are made, but right now it's a proverbial kick in the head.

There are some other aspects of Zope 3 that I'm likewarm to right now, mostly because they're difficult to fully comprehend how/when/where to use at the moment. Zope 3 allows for automatic user interface generation to occur. This was a feature of OS/2 (2.0+), and the defining motive of Naked Objects. Zope 2 has a subset of this feature in its use of properties. What Zope 3 seems to have done is to marry Interfaces (software, not user) and Formulator together. In essence, this allows easy edit forms to be generated off of the objects interface description. From the 'src/zope/app/browser/content/configure.zcml' file, here's an example of how an editform is configured for a ZPT Page:

  <browser:editform
      schema="zope.app.content.zpt.IZPTPage"
      name="edit.html"
      menu="zmi_views" 
      label="Edit a ZPT page"
      permission="zope.ManageContent"
      />
And from the IZPTPage interface:
    source = zope.schema.Text(
        title=u"Source",
        description=u"""The source of the page template.""",
        required=True)
  
    expand = zope.schema.Bool(
        title=u"Expand macros",
        )

Whew! That's about all I can cover for right now. If I have time this weekend, I intend to write a new Content Component (probably a reStructuredText Document) to see how different it really is from developing a similar product for Zope 2 or the CMF. I have no promises right now that it will get done this weekend, but it is something I've been wanting to do. Now that Zope 3X is at alpha1 stage, the fundamental structure should be fairly stable.


3:22:33 PM  blips[]