31.10.06. Namespace Packages in Python

Ian Bicking wrote a Zope 3 Critique a couple of weeks or so ago, partially in response to a critique by Jean-Marc Orliaguet. I’ve wanted to write a response of my own, but time has not allowed it. Now, I’d like to use a few posts to post my own responses to a few items.

The first point I’d like to address comes under headline 3, The importance of standards:

I personally don’t care much about namespaces. Is zope.formlib any more “right” than zope_formlib? Is it any more hierarchical? I don’t think so. I have one namespace package, but it’s kind of a historical accident. I wouldn’t (and don’t) put any more libraries under that namespace. Each library should stand on its own, so why create these hierarchies? People read too much into those namespaces, which is happening right here.

Ugh. zope.formlib is far more “right” than zope_formlib. Granted, this is largely opinion. But man, do I love namespaces. zope_formlib looks like one of those crap-ass hacks and tricks used by the litany of languages who have no namespaces and have to fake it.

First off - I hate the underscore, and believe it should never enter package / module names. Mixed case package/module names are also evil. PEP 8 recommends this:

Modules should have short, lowercase names, without underscores. … Like modules, Python packages should have short, all-lowercase names, without underscores.

While I don’t follow PEP 8 too religiously, I’ve found my life to be generally better by trying to stay close to it. I believe that short lowercase names without underscores are a nice constraint, requiring one to think a little bit about what a module/package will entail and how it will be used. If it’s a module that will be reused frequently, it’s good to have a name that’s easy to remember and type.

At least we don’t see as much of the following any more:

from DocumentTemplate.DocumentTemplate import DocumentTemplate

ugh.

Finally, Zope 3 is a large system. I make fairly large systems using many of its pieces, some more than others. Some of those are quite nice to use from an import standpoint when one just imports the sub-package:

from zope import component, interface

from interfaces import IBar

class IFoo(interface.Interface):
    def newbar():
        """ returns 'ha!' """

class BarAdapter(object):
    interface.implements(IFoo)
    component.adapts(IBar)

    ...

That’s a trivial and nearly pointless example, but it’s a pattern I find myself using more and more. I’d be a much less happy mac if I had to do the following:

import zope_component
import zope_interface
import sqlalchemy_sql

Ugh. Why not just introduce crap like ‘require’ and ‘use’ and leave this modularism behind?

There has been one problem, historically, with Python’s packages: unlike Perl, Ruby, Java, etc, the namespaces in Python are based exclusively on filenames and file system hierarchies. That has meant that a “namespace package” like zope.* would have to include everything. It couldn’t be distributed and used as smaller chunks easily, whereas if this were Java the packages/modules would use the ‘package’ keyword:

package org.zope.component;

But now SetupTools allows one to break these pieces up and distribute them separately while still getting the organizational and conceptual benefits of big hierarchical namespaces.