← Back to team overview

launchpad-dev team mailing list archive

Huge success! No more globs in canonical/launchpad/interfaces/__init__.py

 

Hello Launchpadders,

The Horsemen of the Launchpad Apocalypse have just landed a branch
that removes all of the glob imports from
canonical.launchpad.interfaces.  This means:


Far fewer circular import issues
--------------------------------

c.l.i was a massive factory for generating circular import warnings:
it imported everything, and practically everything imported it.  Now,
all it has is a docstring, so you can safely import c.l.i.foo without
importing the
entirety of Launchpad


Circular import errors are now your problem
-------------------------------------------

If you get a circular import error now, it's probably due to an actual
circular dependency between two modules.  Consider restructuring your
code (e.g. combining the two modules), as well as the usual circular
import avoidance tricks.


Explicit listing of new webservice classes
------------------------------------------

We used to have a webservice:register declaration pointed at
canonical.launchpad.interfaces that would happily snarf up all of the
classes in Launchpad and figure out which ones to expose.  Not any
more.

These days, to expose a new class in the webservice you will have to
manually import it into lp.foo.interfaces.webservice.  Note that
lp.code and lp.translations already did this.


Some circular import work-arounds may no longer be necessary
------------------------------------------------------------

Quite a few places in Launchpad "inline" imports in order to avoid
circular importing. e.g.

  def someMethod(self, name):
      from lp.foo.interfaces.blah import IBlahSet
      return IBlahSet.get(name)

A lot of these are probably unnecessary now.  When you see something
like this, please try to move the import to the top of the module.  If
it doesn't work, you've only lost a minute.


make harness isn't what it used to be
-------------------------------------

As part of this process, the namespace that's created by 'make
harness' has been gutted.  Specifically, you will *not* have all of
the interfaces declared in c.l.i automagically available in your
harness's scope.

If you feel very strongly about this, then I encourage you to
*manually*, *explicitly* import the names you care about into
harness.py.  Please fix bug 673095 while you're at it.


Slightly more conflicts over the short term
-------------------------------------------

This is a big change that touches lots of files.  We've broken it up
as much as we could, but the last step had to be done atomically.  As
such, you'll probably get a few more conflicts than you might
otherwise have.  Sorry.  The pain will go away as your current
branches are landed.


New glob re-exports from an __init__ are a bad idea
---------------------------------------------------

Glob re-exports from __init__ (e.g. what c.l.i used to do) are a bad
idea. Although they may sound tempting ("less typing at import
time!"), the gain in convenience is far outweighed by the tedious,
unnecessary work they cause.

They create spurious circular imports, they make dependencies between
modules harder to read, they make code more difficult to move around,
they add an extra layer of indirection when trying to find code and
they often lead to implicit registration, which in turn makes
registration issues harder to debug.

It is in your interest as a Launchpad hacker to never write an
__init__.py that just imports a bunch of stuff using globs.


We'll be following up with a branch that kills
canonical.launchpad.database in much the same way.

Thanks very much to the many people who helped make this happen.
Special thanks have to go to Curtis Hovey for his heroic heavy
lifting.  Thanks also to everyone who saw "from
canonical.launchpad.interfaces import IFoo" somewhere in the code and
then took the time to fix it -- we couldn't have done it without you.

jml



Follow ups