Skip to content. | Skip to navigation

Sections
Personal tools
You are here: Home News & views Stop abusing namespace packages

Posted Jun 08, 2009

Stop abusing namespace packages

by Erik Rose

Plone has been in a nosedive toward unchecked complexity lately. Here's one easy, high-yield problem we can solve.

For about the past two years, Plone has been in a nosedive toward a development complexity asymptote that, if unchecked, will put a halt to new developer interest. I hate this. Every time I see a developer give up and start over, I mourn his or her inevitable reinvention of the tens of years of real-world-tested knowledge embodied in Plone's codebase.

To be sure, complexity is sometimes the price for solving a genuine problem, but today I'm going to hammer on one instance that's been almost purely a reckless running after shiny new toys. In particular, we have acquired an unhealthy habit of abusing namespace packages. How and why? Here's a primer on when we should use them and when they just make things more complicated.

What's a namespace package?

Namespace packages are those things like collective in collective.tagcloud or plone and app in plone.app.portlets. They are prefixes on the pathname of a Python module, implemented by wrapping an empty folder (called say, "collective") around it and plopping a short, magical __init__.py inside. The result is that you can distribute collective.foo and collective.bar as separate packages but still import them via import collective.foo and import collective.bar.

A much hairier and more comprehensive explanation is available in the documentation of setuptools, out of which namespace packages spring.

Good namespace packages: breaking up is easy to do

Namespace packages are great for breaking enormous legacy packages into smaller parts that can be maintained and distributed separately, without breaking people's imports. They were likely motivated by the gigantic PEAK framework which is by the same author as setuptools, Phillip Eby. As PEAK grew, Eby wanted a way to update subpackages like peak.config or peak.storage without having to ship an entire new 50MB tarball. However, he couldn't just change over to separately distributed modules called peak_config and peak_storage without breaking all the client code that said things like…

import peak.config

So, he made peak a namespace package and had the best of both worlds, the only cost being some occasional weird lines in an __init__.py.

Zope has a similar story. I'm guessing at the archeology, but it should be safe to say that zope started out manageably small and only later grew into a 68MB behemoth that was inconvenient to distribute as one gigantic tarball. Of course, by that point, enough people depended on it that they couldn't just change all the import paths around, so the zope package became a namespace package, too, giving us today's zope.index, zope.event, and so on. All well and good.

Bad namespace packages. Bad. Go sit in the corner.

However, for a variety of reasons, the Plone community has gone absolutely bonkers with namespace packages. We use them for branding, like the Simplon company did with simplon.plone.ldap. We use them for categorization, like plonetheme.nautica05. We even use them for no apparent reason at all, like the 315 products called collective.something. We've caused a lot of noise for no technical or usability benefit.

Filesystem paths: ouch!

Out of the box, if I want to get to the source code of Plone's redirection machinery, I have to go into plone.app.redirector-1.0.10-py2.4.egg, then into plone, then into app, then, finally, into the redirector folder, where all the code lives. The extra traversals are a waste of time. David Glick even got mad enough to cook up the omelette buildout extension to patch around the problem. Am I missing some reason we didn't simply go with plone_app_redirector and save 3 levels of folders and weird __init__.pys? It's not like we had legacy imports to placate.

Subversion hide and seek: ouch and a half!

In svn, the problem repeats itself with an additional twist. People eggifying classic products (our own FacultyStaffDirectory is guilty of this) often move their source to a new folder with "Products" prepended: Products.FacultyStaffDirectory. I can understand the use of a Products namespace package for compatibility with Zope's old import magic, but is it really necessary for 50% of the stuff in a repository to start with "Products"? This kills typeahead, and, more importantly, makes developers look in two places for the code: "Hmm, let's look in FacultyStaffDirectory. No trunk folder! Ah, a README-trunk.txt: 'Your princess is in another castle.' Okay, I'll back out of here and try Products.FacultyStaffDirectory. Those are 2 minutes I'll never get back." Sure, use the Products namespace if you must, but let's keep our svn directory names unsullied.

Branding: double ouch!

When namespace packages are used for branding, everything has to change when the company divests itself of the product. When Simplon donated simplon.plone.ldap to the community at large, it had to rename it to plone.app.ldap, thus breaking everybody's buildouts and imports. Let's keep company names out of package names.

Description: ouch a third time!

Namespaces are often misused to describe functionality, like in plonetheme.*. This is just as wrong as when I named AutoMemberMakerPasPlugin (which I've remedied in WebServerAuth) and is nothing more than a repetition of the horrors of file extensions. Actually, it's worse: at least extensions are postfix and don't impede type-to-select. We have perfectly good egg metadata where we can declare that a package is a Plone theme. In fact, the plone3_theme ZopeSkel/paster template spits out the keywords "web zope plone theme" by default. The plonetheme prefix is redundant right out of the box!

Let's fix this

A lot of the excess namespaces come from some bad ZopeSkel/paster templates which make it really hard to create an egg-based product without a namespace package. I certainly don't blame newbies for getting led down the wrong road, but a lot of us should know better. Let's clean up our act:

  • Reserve namespace packages for their intended use: breaking up enormous legacy packages. I see a world market for maybe five namespace packages.
  • Stop using the collective namespace. It conveys no useful information. It's just noise.
  • When you use the Products namespace to eggify an old-style product, don't move your trunk. You're going to break people's checkouts when you delete the old trunk anyway, so you might as well just change it in place.
  • Scribble your company name all over your readme and egg metadata, not in your package name. Learn from Apple, who is now stuck with an API full of NSThis and NSThat.
  • Fix the ZopeSkel templates that spit out things like plonetheme.*. We can't expect themers to be Python import machinery wizards and fight it themselves.

Those of us with an understanding of namespace packages have a responsibility to use them properly—everyone else will follow, for better or worse. This is a battle in the complexity war that's technically easy to win and one that new users and developers see early in their Plone experiences. Let's swat this piece of low-hanging fruit down.

After you read the excellent comments below, check out my summary and response in Namespace packages: replies to replies.

Document Actions

+1

Posted by Jan Ulrich Hasecke at Jun 08, 2009 08:54 AM
Yes, the namespace orgy is confusing.

Respectfully, I disagree :)

Posted by Martin Aspeli at Jun 08, 2009 09:03 AM
* Namespaces are useful to avoid collisions and logically group related functionality, both in packages and as a general programming principle. Splitting up large codebases is just one use case, and probably an uncommon one at that.

* If I didn't use a namespace and I released a package called 'foo' to PyPI, I'd stand that much more of a chance of colliding with another package called 'foo', in which case whoever got there first would rule PyPI and it'd be impossible to use those two together.

* Namespaces also communicates ownership. For example, we've been able to formulate useful policy around the licensing of packages in the plone.* (soon to allow BSD licensing) and plone.app.* (to stay GPL licensed) namespaces.

* For this reason, I also rather like the collective.* namespace, to convey packages written by and for the Plone community, but not intended to be part of Plone or owned by the Plone Foundation.

* With Plone 3.3, by the way, there's no longer much of a reason to use Products.*, since you can add a z3c.autoinclude.plugin entry point and have your package auto-configured anyway.

* I agree that renaming simplon.plone.ldap to plone.app.ldap was silly. There was no good reason for this. I don't think such renaming has happened very often, though.

* I think in general, double nesting should be avoided unless there's a good reason, so most people now prefer foo.bar instead of foo.bar.baz. That's why we have plonetheme.* instead of plone.theme.*, for example. But it is useful to be able to look at your list of packages and understand that these five are all Plone themes and those are all part of Plone core.

* You could clearly achieve the same thing with underscores, but that's just inventing your own namespacing qualifier, which is silly.

* I agree that it's annoying that setuptools requires you to replicate the package structure, but it's a minor nuisance and we have lots of bigger fish to fry :)

* The 'omelette' concept is very useful because it helps you understand exactly what code Zope is running. When you have a shared egg cache, or even if you have a per-project egg cache that's been going for a while, it's cumbersome to find the actual code used at runtime otherwise.

Martin

agree

Posted by thet at Jun 08, 2009 10:20 AM
i agree with martin and add to the list my points of view:

+ namespace packages make it possible to easily write plugins for other packages. for example (fictious):
audioplayer.converter.core ... core api for audio conversion
audioplayer.converter.ogg ... ogg plugin
audioplayer.converter.mp3 ... mp3 plugin
...
other developers can easily write mode plugins without beeing involved in audioplayer core development.

+ prefixing packages with some a name which describes the functionality groups together similar packages. your plonetheme.* example is a very good one. i love to find what i need where i expect it to be.

agree2

Posted by thet at Jun 08, 2009 10:22 AM
but i agree with point 2 and 3 of erik's "Let's fix this" suggestion..

I think you're missing the point

Posted by Chris Rossi at Jun 08, 2009 09:05 AM
The basis for your argument seems to hinge on one assertion: that the intended use for namespaces is the "breaking up of enormous legacy packages." While that is certainly a side effect which falls out from namespaces, if you think that is why they were invented, then I really think you're missing the point. Most modern programming languages these days have some idea of namespaces and/or a hierarchical package structure. In every case the reason to use them is to: 1) disambiguate otherwise similarly named packages, 2) prevent name collisions.

Consider that Python now has programmers producing reusable modules worldwide--there is a massive pool of programmers, globally, generating a massive pool of libraries. The idea that these could all be kept organized and disambiguated without some namespace concept is absurd. When there might be 5 different libraries out there in the wild for XYZ, you want to be able to disambiguate *which* package you actually want. If you write an rssfeed package that is intended to work with a particular product, like, say, Plone, someone else who's not interested in Plone, but is interested in rss, will thank you for naming your package plone.rssfeed. You get the idea. There are more Python programmers out there than Plone programmers.

If you ask me, actually, the only packages that should live in the "root" namespace are the ones in Python's standard library. Everyone else's third party package *should* have a namespace. The complaint that the developer then has to cd though a directory or two to get to the code is trivial--a little extra folder nesting is a small price to pay for a globally sane package structure that prevents far flung developers from clobbering each other with name collisions.

Now, that's not to say there aren't some problems with how Plone uses namespaces. Root namespaces like "Products" and "collective" give the casual observer no hint that the packages are intended for use with Zope or Plone. This is actually pretty ugly practice. Of course, dumping the children of these names into the global, root namespace would just pollute the global namespace used by the entire Python community. Other Python programmers would make fun of you and justifiably so. Remember, you're sharing a global namespace with every single other Python programmer on the planet. Some consideration for others goes a long way here. If anything, the real answer is probably to add yet another level: zope.Products, plone.collective.

YMMV.

avoiding name collisions

Posted by Martijn Faassen at Jun 08, 2009 09:33 AM
I want to add my voice to the chorus pointing out namespaces packages are useful to avoid name collisions. Everything else is secondary. If I call my package 'xml', I'll be competing with a ton of other people who may want to call their package 'xml' too. I'd be rather presumptuous to call my packages 'query', 'custom', 'workflow' instead of 'hurry.query', 'hurry.custom' and 'hurry.workflow'.

All the other stuff is secondary: branding and splitting up things and signaling may be motivations to decide on the *name* of a namespace package, or to decide to place a whole range of packages under the same namespace package, but they're not the primary reason for the existence of namsepace packages.

I believe there are reasons to create top-level packages that aren't in a namespace package if this package performs some very general functionality accessible to most Python programmers, if the package name is one that is fairly unique and unlikely to clash. There are no hard-and-fast rules for this.

Arguing against complexity is fine and necessary, but I think there are better targets to argue against than against namespace packages.

For those Relatively New to this Issue

Posted by Rose Pruyne at Jun 08, 2009 10:41 AM
It's easy to unwittingly step into this naming convention when you're attempting to figure out what precisely is the best practice and are relying on various examples, tools, and information for guidance. To this end, I added a few lines to the WebLion wiki: https://weblion.psu.edu/[…]/SubversionBasics#AWordaboutNamingConventions to help out fellow WebLion partners. This topic should probably have its own wiki page, however, if it doesn't already have one.

ZopeSkel

Posted by jjmojojjmojo at Jun 08, 2009 11:40 AM
For the record, plonethme.* is just a suggested default, at least for the plone3_theme template. What do you think would be a better default?

I'm not sure if we can avoid having two namespaces given the underlying architecture of ZopeSkel, do you think that's the heart of the problem?

Also, this touches on something that's always bothered me about Plone. There's a massive assumption that people who work on layouts 1. shouldn't have to program, and 2. are incapable of programming. They're expected to write page templates, viewlets sometimes, pyhon scripts, not to mention javascript and more advanced HTML and css, but a little python is considered beyond their comprehension. I think that's ridiculous.

Themers *are* doing python development and eggs are how themes are distributed. Not expecting them to understand that is a huge problem. Granted, it's a problem with the theming story in Plone, but I don't think it's reasonable to expect complete protection from python import machinery for people who make themes. /rant :P

Themers and Python

Posted by Rose Pruyne at Jun 08, 2009 12:10 PM
I think it is reasonable to expect themers to deal with Python. The key is good documentation.

"Branding" is a charged word

Posted by ke1g at Jun 08, 2009 12:35 PM
I agree that the killer app for namespace packages is name collision avoidance. And what you see as branding may simple be a means of choosing a name unlikely to be chosen by others.
When I develop a theme or custom content package for a customer, I have to call it something. These aren't packages of general interest to the community, so registering them with Pypi doesn't seem like the right thing. But I would be most unhappy to take some future Plone (or even Python) upgrade to discover my customer product now collides with something new and global.
In fact, I'm so enamored of namespace packages for this purpose that I considered a campaign for getting the python community to reserve a few top level package names, corresponding to TLDs, for use in a Java-like reversed domain name package naming scheme. The idea didn't seem to inspire my local Python SIG, however, so I'm settling for a top level namespace of "com_apsol" for our products (apsol.com being a relatively short DNS name that we own, even if we don't use it for anything at the moment).

Descriptive Naming and feeds

Posted by Ian F. Hood at Jun 08, 2009 02:01 PM
I watch the feed of news/releases daily in hopes of seeing something I might need or find interesting (or important updates). Typically all I see are the various product names and the versioning information. There's no meta data and even the title (tooltip) is just release notes.
Most of the time I have no idea what a product is or does. I do perk up when I see Products.xyz or collective.xyz because I know those are Plone related.
I find it annoying that I have to click through the release page to get to the product description (as I am still trying to learn about the many different add ons available)... and I can't (or won't) do that for every one of them.
It's also annoying having to click through to something only discover if it's a theme or a product.
I want to know about the products you all build, but it can't be a full time job or even too time consuming.
If package namespaces aren't the solution then please find another way.
This 'orgy' may be thwe result of a real need that found a way to express itself.
At a glance I want the product name to give me an idea of:
 - what it is (theme, product, etc)
 - where it's usable (z3, plone, python)
 - what it's about or for
If those apply to me in some way I will gladly click in to read more about it. If it's a package I already use or know then I will recognize that there is an update.
Just my opinion.
Ian

afterthought

Posted by Ian F. Hood at Jun 08, 2009 02:19 PM
I agree that the pater templates are partly to blame - at first I found it confusing to answer the inputs because I really didn't know what the terminology was. After a few (failed) tries I got things sorted in my own mind. I've had to help others with that too.
I don't at all object to branding, I think name conflicts are a valid concern when I try to name my add ons.
When I first started using paster I had to guess my way through it until I came up with my own methodology on how to use it.
If there's going to be a naming convention then apply it from the very start in paster...
Ask me my Brand, is it a theme, etc... then apply the namespace(s) however you see fit. At the very least make the questions clearer to the newbie (who may not know what you know)- what I learn first is what I repeat.

original problem

Posted by Chris McDonough at Jun 08, 2009 02:17 PM
I think one original problem stemmed from the (rather late) addition to Zope of being able to use packages that were *not* in the Products namespace as Zope products. As non-self-describing as the Products namespace was, it *was* describing: a package in the Products namespace is always a Zope product. Period. There was no temptation to treat Zope products as "normal" Python packages, with all the attendant naming decisions, as there is now. If it had been impossible to use any other namespace than Products as a Zope product name, I suspect there wouldn't be as much of a problem today. Zope Products are *not* normal Python packages; they require extra hair in __init__.py to be useful as a Product. The Products name was a great signifier. It's completely, totally useless to have Products outside the Products namespace.

Of course, some plone.* packages are not Zope products, and the problem would have reared its head there, but it would be much more limited.

SVN moving

Posted by Joel Burton at Jun 08, 2009 03:28 PM
Erik suggests that when "eggifying a classic Product" (JoelsBlog -> Products.JoelsBlog) that you keep the svn location the same.

I disagree here.

First, the intended benefit, doesn't exist. Your buildout wouldn't still work if it expected a classic product at /svn/JoelsBlog--there isn't a classic product there, but a nested egg namespace. So, your buildout would -still- break, and in a much less newbie-understandable way.

Second, having watched hundreds of people confront eggs/packages/buildout in classes, one of the things that really confuses people is when the egg name or svn name is different than the actual namespaced results. Having a egg with a name like "JoelsBlog" that ends up being namespaced into "joelburton.joelsblog" is confusing. (Yes, it is prettier, I agree--but trust me, many people make a wired assumption that namspaced-names=egg-name, and it's a werid leap when they don't). Similarly, having the svn name not much is another miswire.

I think, while it's a small pain to switch to a different svn path, it's actually much easier for people to understand than the replace-in-place alternatives.

- j.

company names in egg names

Posted by Joel Burton at Jun 08, 2009 03:34 PM
I'm more divided about company names in egg names.

One of the nice things about open source is the willingness for everyone to jump in and add, of course. But I'm guessing that fewer people want to cooperate on a product called "ourcompany.blog" than "collective.blog"--you're spending your time building the brand of your competitor (even if in a small way). Having products be branded by the first company that worked on them can be annoying in this small way--and may, IMHO, lead us to the nest of extremely-similar buildout recipes + products that differ mostly in the company names that prefix them. Credit is good; permanent-credit toward first-mover may not be.

On the other hand, it does keep us from having clashing names, like "blog" and "blog".

Are there other Python projects that typical put packages into company-specific namespaces?

company namespaces

Posted by Encolpe Degoute at Jun 08, 2009 06:38 PM
Take the example of the 'iw' namespace. First there was only plone eggs, then comes recipes that can be applied outside plone and pure zope recipe like iw.rotatezlogs and development environment with iw.releaser/iw.dist that move to the collective namespace.
All packages can be listed here:
http://ingeniweb.svn.sourceforge.net/viewvc/ingeniweb/

Then ingeniweb became alterway. Did we need to move our namespace to alter.* or aw.*?
There was also a team working on pylons and creating eggs...
It's difficult to anticipate where a small company will go in few years and a company namespace can be polluted in the same way that the root namespace.

Do we need rules and a board to be sure they are respected ?
A discussion like this one should be on a mailing list, not in a blog.

Partially disagree

Posted by Keul at Jun 08, 2009 04:48 PM
I don't know... I came (years and years ago) from Java world, where all was com.sun.*, com.microsoft.* and com.oracle.*, and were the java.* is like out plone.*

This is feelings that the current namespaces give to me (a very-distant-to-be-core developer):

* I really fear to develop something like plone.xxx - the Plone namespace is for me something I really fear to use! I'm sure that is the same for every other that release in the collective! What if tomorrow some core developer wanna use the same name, to do the same thing in a better way? Panic!
* The old Products.* has been dropped because was a only, huge namespace and I agree that this must not be used again. For me Is good every time I need to keep compatibility with Plone 2.5 (luckily this is every day more rare :-)
* The "collective" namespace is the new way product. During a P4A sprint Nate said us that this must be used for something like "I release this, but probably I will not maintain this". I know that this is not true for all collective.* eggs, but the idea is someway good. I never use collective.* and probably I will never it.
* Don't using a company namespace... mhhh. To be honest the usage of company.* for eggs name is natural. Is the best way to avoid collision... like hostnames, and again like the choice of Java. For sure I will not like a collective were products like "frank.portlet" begin to raise, but company name is different!

It's to difficult to find a right package name sometime... Maybe what is missing is a guide? Some "collective usage namespace convention"?

For example: say that tomorrow I will release a new product: a new newsletter system for Plone, and I developed it in my free time, so I will not use the company.xxx namespace (bad company, you'll not steal my work!). Like said above: I don't wanna use "collective" and neither "Products"...

I really like to know what is your suggestion is those cases, I'm sure that this choice is taken every day by namy developers!

A nightmare

Posted by nutjob at Jun 09, 2009 08:55 AM
I had a horrible dream last night.

I logged in and typed `ls -R src` ... and this is what I got:

src:
com org

src/com:
__init__.py sun

src/com/sun:
__init__.py java

src/com/sun/java:
__init__.py io exceptions threading

...

org:
__init__.py gnu

org/gnu:
__init__.py regex

org/gnu/regex:
__init__.py parser searcher

...

Please say it didn't happen!
Need help now?

Immediate assistance is available during university work hours:

News & views…
Posted Oct 13, 2009 Portlets gone wild with ContentWellPortlets 2.0.1 This new release adds the ability to add portlets to the footer area. It also has 6 portlet managers per area. This means 20 total portlet managers including the 2 on the sides that ship with plone.
Posted Sep 17, 2009 Plone 4 – An interview with Zope News Jan Ulrich Hasecke interviews me for Zope News.
Posted Aug 31, 2009 Web Services API for Plone Alpha 3 Release Details the release of the wsapi4plone.core package and the plans for future releases. The final report of the AtomPub for Plone Google Summer of Code project.
Posted Aug 28, 2009 Content editing and creation in Plone is faster with archetypes.schematuning Some bench marks of content editing and creation in Plone with and without archetypes.schematuning installed.
More news & views…