Europython 2006

Posted by Graham Stratton Thu, 13 Jul 2006 21:56:00 GMT

I wrote most of this pretty much the day after I returned from Europython, but I haven't gotten round to posting it until now.

<sidenote>

I don't like markdown. Apparently it's meant to be as much like plain text as possible, but which do you do:

Heading
=======

or

###Heading###

?

Hashes being so much effort to type on Mac doesn't make them any more endearing, either. We need a Zope 3 blog application!

</sidenote>

Introduction

Notes from Europython 2006, at CERN in Switzerland. As last year, the conference was great fun, really interesting and left my brain crammed with ideas. I hope I got most of them written down!

I think that there were slightly fewer people there this year, but the enthusiam and number of interesting projects seemed to still be very high. I'm happy python's still en route to taking over the world. Not quickly, but it's getting there. Ironically the IT industry seems to be one of the slowest moving out there.

Web Frameworks

In a stark contrast to last year, when there were oodles of Zope talks and no other Python web frameworks, this year most of the talk was about the three new Python web frameworks: Django, TurboGears and Pylons.

Zope

Europython definitely left me with the impression that Zope is losing momentum. This doesn't necessarily the end for Zope; firstly, it could just be an illusion, as people were too busy being enthusiastic about other frameworks. But more importantly, there never have been that many sites built with raw Zope; Zope's success has been with the use of Plone and other CMSs built on it.

However, I do feel that the Zope 3 project is losing momentum. Most of the ideas have been experimented with, and what remains is the hard slog to make existing applications reasonably compatible with it. There's a limit to how many more major architectural changes people will put up with once major projects start to be built with it.

Zope 3 in general feels too complex to me at the moment. There were few major changes in the last release; most of them were removals of 'convenience ZCML' directives, which, whilst I agree with Philipp that the changes make Zope 3 a bit easier to understand, don't really make life any easier. The component architecture is wonderful, but there's a big step between that and a working web application.

I think that either Zope 3 is too complex, and most people will never understand it well enough to use it, or there's just far too big a gap from the books to what you need to know and understand to write an application. Maybe not on the implementation side, but in terms of data structuring and things like that. There have been a lot of discussions on the mailing lists about how to do many to many relations, whether one should do a direct object reference, and things like that. Most users could probably manage to do one way or another, but get stuck on trying to work out which one to do.

Tarek's talk on zope-cookbook.org was quite interesting for me. I had assumed that it was just a place people could upload random docs, but it's actually very carefully planned and structured. If it gets a lot more recipes in it, it should become a very valuable resource. I think it probably needs a lot more design guides. Working out how to do things is hard, but nowhere near as hard as working out what should be done in the first place.

The new boys

I attended talks on TurboGears, Django and Pylons, but didn't really take in too much, and I can't entirely remember which is which. Maybe someone will draw up a comparison table showing which ORM, templating engine, etc, each of them use. I was impressed by the number of things Pylons does using WSGI; adding functionality using WSGI demonstrates that components are genuinely easily pluggable.

Ajax

For some reason it is customary to write Ajax rather than AJAX. A year ago, Ajax was pretty new, with Google maps and Gmail being the main users. Today no framework will succeed without Ajax support. Tarek Ziade of Nuxeo gave a talk on the state of the art. He covered a number of approaches.

Firstly, CrackAjax is a tool to convert python into Ajax. I guess the number of constructs is quite limited, unlike an Ajax backend for pypy, which was apparently demonstrated at the conference. CrackAjax has not been developed for about 8 months.

Azax allows you to describe the JS behaviour in an XML file, though the number of possible behaviours is currently quite limited.

Tarek's recommended solution is a client-side framework, the two examples he suggested being Scriptaculous with Prototype, and MochiKit. Tarek has been good and uploaded his slides; they're certainly worth a look if you need to do Ajax in python web apps.

WSGI

The Weally Simple Gateway Interface, defined in PEP 333, is gathering pace rapidly as people realise just how powerful it is. James Gardner's talk on WSGI covers the topic nicely, and he has also uploaded slides, so I refer the reader to them. Also look at Pylons, a web framework where most of the components are integrated using WSGI.

CPSSkins

This is a very impressive technology allowing through-the-web development of web designs using a very cunning bit of Ajax on top of Zope 3. Just drag and drop your portlets and data widgets, and you're done. How cool is that going to be? There are demos at www.z3lab.org http://www.z3lab.org/sections/front-page/design-features/news-portlet-widget

Language

Python 3000

Guido's keynote on Python 3000 was, for me, very encouraging for the future of the language. At present there are not too many new and complex features coming into the language; the major changes will be getting rid of bug-inducing features.

The announcement that print will become a function instead of a statement prompted a synchronised intake of breath through the whole lecture theatre. The argument is that, well, it should be, and it makes it much easier to replace printing with logging during application development.

Relative imports will have to be explicit. Hooray!

PyPy

Unfortunately I didn't get to attend many of the pypy talks. However, the lightning talk on the features of pypy 3000 was encouraging; the core team are still highly enthusiastic about the project and its potential. There are still plenty of ridiculous sounding ideas going rounds, such as being able to change the interpreter being used at runtime, which gives me great faith in the project. It hasn't got too serious yet, and is continuing to be the research project it set out to be.

Of course, pypy isn't really a python compiler, it's really a generic compiler. Obviously the first thing you want to compile is the compiler itself, just because it's cool, but now that's done, the options are pretty much unlimited. Whether pypy ever makes python interpretation as fast as C remains to be seen!

Libraries

zc.buildout

Jim Fulton introduced zc.buildout, a tool for setting up environments with many software packages. It's not Zope specific; it builds on eggs, adding the flexibility required to be able to guarantee the correct versions of different packages and databases for development and deployment. Well worth a look, IMO. Jim has also been nice and uploaded slides.

Applications

Mercurial

Mercurial is yet another source control management tool. But it's written in python, and applies patches much faster than subversion, whilst using less memory and having a smaller repository. Apparently it doesn't deal with conflicts as well as darcs does. Mercurial has been selected as the SCM tool for OpenSolaris; it's ideally suited to this, as it's an environment where people may regularly want to apply hundreds of patches to customise a standard source tree.

MailManager

MailManager has been around for quite a long while. LogicalWare were one of the first Open Source companies in the UK to secure funding. MailManager allows companies to distribute mail to enquiry and support helplines internally, and to track messages.

LogicalWare sell this software as a service, or as support, or as pre-installed boxes. Sadly they do not receive that many contributions to the project from the open source community. It is always hard for a company to get such contributions, and it is interesting seeing which companies succeed. I think Zope corporation does better because other people are using the software for their own projects continually, so are more likely to improve it that a system like MailManager which is installed and left, probably not by a developer.

Business

A discussion on the last afternoon concluded that to support customers, a good model may be to have a connected issue tracker, for customer use, and a bug tracker for developer use. This is the model used by Launchpad. It seems a good model, so I'd be surprised if there isn't already a product which offers this solution.

Summary

Well, thanks for reading. I'd be keen to hear other opinions!

Posted in , , ,  | 3 comments

Formlib edit forms

Posted by Graham Stratton Wed, 17 May 2006 20:51:00 GMT

There seems to be a bit of a shortage of simple documentation for formlib, so I’ll attempt to do my bit. This one’s just a custom edit form. Replacing the standard edit form allows you to put text around the form, and to change what actions can be executed on submit. In this case, we extend the render method to redirect to the object’s default view after editing, instead of returning to the edit view.

from zope.app.pagetemplate import ViewPageTemplateFile
from zope.formlib import form
from interfaces import ITextPage

class EditView(form.EditForm):
    form_fields = form.Fields(ITextPage)

    base_template = form.EditForm.template
    template = ViewPageTemplateFile('textpageedit.pt')

    def render(self):
        if self.errors is None or self.errors:
            return super(EditView, self).render()
        self.request.response.redirect('.')

As you can see, the default template is replaced, but is made available under the name ‘base_template’. This means that it can be accessed from the replacement page template like this:

<html xmlns="http://www.w3.org/1999/xhtml" 
      xmlns:tal="http://xml.zope.org/namespaces/tal" 
      xmlns:metal="http://xml.zope.org/namespaces/metal" 
      metal:use-macro="view/base_template/macros/main">

<body>
<div class="section" metal:fill-slot="extra_info">
<h3>Edit this page</h3>
<p>Here you can put some instructions about editing the page.</p>
</div>
</body>
</html>

Take a look at the base template at formlib/pageform.pt to see what other METAL slots are available.

Posted in  | 1 comment

Named templates

Posted by Graham Stratton Fri, 12 May 2006 12:34:00 GMT

Named templates are a feature I hear mentioned a bit, but haven’t understood whether I want to use or not. So here’s a little investigation into how to use them and some thoughts about what they might be used for.

Named templates are part of the formlib package, and a suggested use is for forms which might want to have different appearance at different times, though using the same view. Named templates are looked up by view and template name only.

One use for named templates might be in a CMS where you wish to have a couple of default page layouts; say, for example, one type which has a right-side bar for latest news, and one which doesn’t. For each page, you might want the user to be able to select which template to use.

Or you might the top page of your site to have a different template. All the page view would need to do is to check for whether the page implements ISite, and if so use the home page template instead of the default template.

Posted in  | no comments

Views

Posted by Graham Stratton Fri, 12 May 2006 09:26:00 GMT

One thing that got me for a while with Zope3 is how view lookups work. A view is looked up by the object, the request and the view name. What does that mean? Surely the object comes from the request anyway?

Yes, but the lookup is done by interfaces. So the object is likely to provide IMyObject, the request IBrowserRequest, and the view name something like index.html. When you defined your object, your will probably have also defined a browser view for index.html, and this is what will be found.

A view for ”*” will be registered for Interface, so the lookup will match any object type, since all interfaces inherit from Interface. So interface lookup climbs the inheritance tree. I don’t know how it deals with multiple inheritance, though. Probably in the same way as Python (which changed in version 2.2).

So what is a view? Well, it’s a class which adapts an object and a request. That means that what you instantiate the class, you pass in an object and a request. Okay, but then what? Well, when you call that instance, it should return the HTML for that view.

Okay, that’s that sorted then. Let’s more on to content providers. A content provider adapts an object, a request and a view to IContentProvider. IContentProvider requires that the object have attributes request, context (the object), and _parent_ (the view). It should also provide an update() method, and a render() method, which returns the HTML.

So, a content provider lookup discriminates against the view. What does that do for us? Well, we might have a content provider contains the CSS loading code. We might want a different stylesheet for our management and non-management screens. So if all our views either implement IMyManagementView or IMyNonManagementView, then by looking up a content provider called, say cssimport, then we could get the appropriate one for our view, assuming that we had registered content providers for both Interfaces.

Posted in  | 2 comments

Views, viewlets and content providers

Posted by Graham Stratton Thu, 11 May 2006 10:58:00 GMT

I’ve always had the feeling that understanding the fundamentals of Zope3 won’t take too much longer. Hopefully I’m now one step nearer. In this article I hope to explain how views, viewlets and content providers fit together.

Views have been around in Zope3 since the beginning, whereas viewlets and content providers appeared with formlib in 3.2.

Let’s deal with content providers first. The contentprovider module is very simple. It merely defines an interface for a content provider, which requires an object providing it to have an update() and a render() method. The update() method will be called first so that object can be modified in light of the request (eg form data). Then the render() method is called which should return the final HTML.

The second thing that the contentprovider module does is to enable the ‘provider’ attribute in TAL, which facilitates the use of content providers in templates. Note, though, that when many content providers exist in the same template, the two-stage rendering process is not honoured across providers. Viz., the update() and render() methods will be called on the first provider, then on the second, and so on, instead of all the update() calls preceding all the render() calls.

So, how about a minimal code example? Well, here we go… create a new package called boring, and install a slug in etc/package-includes to load it. Now create a _init_.py like this:

from zope.interface import implements, Interface
from zope.component import adapts, provideAdapter
from persistent import Persistent
from zope.contentprovider.interfaces import IContentProvider
from zope.publisher.interfaces.browser import IDefaultBrowserLayer

class MyContentProvider:
    implements(IContentProvider)
    adapts(Interface, IDefaultBrowserLayer, Interface)

    def __init__(self, context, request, view):
        self.context = context
        self.request = request
        self.__parent__ = view

    def update(self):
        pass

    def render(self):
        return u'<h1>Look Ma, I rendered something!</h1>'

provideAdapter(MyContentProvider, name="boring.MyContentProvider")

class IBoring(Interface):
    """Interface for a really boring content object""" 

class Boring(Persistent):
    implements(IBoring)

Create a page template called contentprovider.pt like this:

<html xmlns="http://www.w3.org/1999/xhtml" 
      xmlns:tal="http://xml.zope.org/namespaces/tal" 
      xmlns:metal="http://xml.zope.org/namespaces/metal" 
      metal:use-macro="context/@@standard_macros/page">

<head>
  <title metal:fill-slot="title">Test page</title>
</head>
<body>
<metal:slot fill-slot="body">
  <tal:block replace="structure provider:boring.MyContentProvider" />
</metal:slot>
</html>

And finally create the configure.zcml file to tie it all together like this:

<configure
    xmlns="http://namespaces.zope.org/zope" 
    xmlns:browser="http://namespaces.zope.org/browser" 
    i18n_domain="zope" 
    >

  <class class=".Boring">

    <factory
        id="boring.Boring" 
        description="Boring factory" 
        />

  </class>

  <browser:page
      for=".IBoring" 
      template="contentprovider.pt" 
      name="contentprovider.html" 
      permission="zope.View" 
      />

  <browser:addMenuItem
      class=".Boring" 
      title="Boring object" 
      permission="zope.View" 
      />

</configure>

Then start zope, log in to the ZMI, create a Boring object called boring, and go to /boring/@@contentprovider.html, and should should see the page provided by our content provider. That’s about as simple as it gets.

So what can we do with our content provider now we have one? Well, one thing we can do is to use a viewlet manager as a content provider, so in my next article I’m going to show how to set up viewlets and register them with a viewlet manager.

Posted in  | 2 comments

Zope 3.2 install

Posted by Graham Stratton Fri, 20 Jan 2006 11:10:00 GMT

Installed Zope3 3.2 this morning, as a replacement to 3.1c3 which I’d been running before. The major change, which should be transparent, is that 3.2 is based on Twisted instead of Zope’s own Zserver.

Apparently there’s also a test browser built in, so I’ll have to have a look at that.

I thought the install would be trivial. Then I discovered that Ubuntu doesn’t even contain make as part of its default installation. I seem to spend a lot of time installing things which aren’t part of the default Ubuntu, but which were included in Knoppix.

Then I got
unable to execute gcc: no such file or directory
Excellent. Now, gcc-4.0 is installed, so do I symlink to that, or do I install 3.4? Or 3.3? I go for the symlink. I try to run make. I get a stream of errors resembling the Mississippi in flood, starting with something about not being able to find limits.h Now, I guess that’s either a kernel header or a python header. Let’s try installing python-dev. Nope, still drowning in error messages. There’s also stdlib.h and assert.h missing, so I retract my earlier statement, and try installing libc-dev. I’m getting more nervous every time I type make now.

This time I get lots of

warning: pointer targets in passing argument 1 of 'PyString_FromStringAndSize' differ in signedness

I read it a few times, but it still doesn’t make any sense to me. I decide to ignore it and continue. ‘make install’, and all seems fine. Now what do I do? I think I have to ‘mkzopeinstance’ using the new Zope, and then copy the bits I’d developed (and hopefully the existing ZODB) into the new instance.

I start Zope3.2. It takes a little longer than 3.1 had. It also seems to use 63MB of memory. Now 63MB per instance seems rather excessive to me. Especially since my virtual server only has 128MB RAM.

Posted in  | no comments