Skip to content

Announcing zope.fixers

April 7, 2009

I’ve created a package, zope.fixers, that will contain the 2to3 fixers needed to port Zope and Zope Component Architecture code to Python 3. If you want the gritty details, read on.

I want the Component Architecture to be available under Python 3, so I have tried porting it. To do that I needed setuptools, which is why I have ported setuptools to Python 3. But when it came to looking into porting zope.interface again, I noticed that the normal build process uses zc.buildout and zope.testing. Both of which depends on zope.interfaces. So there was a bit of a chicken and egg problem there.

So I decided to look into this more deeply during the PyCon sprint, as Jim Fulton was there and could help me set up a build environment that could work. However, when I looked more deeply into it, I realized I could set up a way to run the zope.interfaces tests with setuptools instead of with zope.testing and thereby bypass the need for both zope.testing and zc.buildout. Said and done. There is now a regebro-python3 branch of zope.interface where I have commenced doing Python 3 support.

The big problem with zope.interface

Currently you mark a class as implementing an interface with the implements() method.

class Foo:

This syntax works by hacking the locals namespace that gets passed into the class construction, by inserting a __metaclass__ variable that uses a so called “meta class advisor”. This way zope.interface gets a hook into the class construction and can during the class construction mark the class ass implementing the interface.

Yeah, that’s some serious Python-internal magic there. And this magic does not work under Python 3, since the __metaclass__ is now ignored. However, there is a new and much cleaner way of modifying and annotating classes, and that’s class decorators. So, for Python 3, zope.interfaces will use class decorators instead of the class body function calls currently used.

class Foo:

This will also work under Python 2.6 and 2.7, allowing smooth transitions.

However, most people will need this to be changed automatically when they port their software to Python 3. Therefore, we need a fixer to move from the old syntax to the new. And I needed a place to put those fixers. That place is zope.fixers, which currently only contain one fixer, the fix_implements, that does the above change. zope.fixers will be released in v1.0 as soon as I get all zope.interface tests to run. This will probably take some time, as the sprint is long over, and my free time has ran out. People are very welcome to help port zope.interface and write more fixers (I think some more will be needed).

Writing fixers that actually move code around like this turns out to be damn hard, which is why it took me so long. But that’s another blogpost.

  1. Hmm. I’ve been wondering if Python 3 warrants rethinking the CA from a slightly different perspective, given the existence of Abstract Base Classes.

    • The use cases overlap, but ABC’s doesn’t do all that interfaces does, and apparently there are reasons why they can’t be used as a base for interfaces, although I don’t know exactly what those reasons are.

  2. ABCs are unsuitable as replacements for interfaces for at least two reasons:

    – They can’t be applied to instances as markers. *Lots* of ZCA-based code uses this incredibly-useful feature.

    – They can’t be introspected, at least in the general case: you can ask if a given instance has an ABC, but you *cannot* enumerate its ABCs, which makes component lookup / dispatch flat impossible.

Leave a Reply

Please log in using one of these methods to post your comment: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: