[Distutils] Experimental non-empty namespace package support
Phillip J. Eby
pje at telecommunity.com
Sun Aug 14 23:35:51 CEST 2005
I've just checked in experimental support for lazy, non-empty namespace
packages. And what is that?, you might well ask.
Well, it seems that livinglogic.de distributes certain Python packages
using a distutils kludge that allows a kind of crude namespace package to
exist, without using pkg_resources. Specifically, their 'll-core' project
distributes the 'll' package, and various other projects such as 'll-color'
distribute modules for the 'll' package, but *without including an
__init__.py*. This allows the distutils to install the modules without
overwriting or duplicating the single __init__.py file.
This is an interesting approach to addressing namespace packages in a
pre-setuptools world, but until now it hasn't been really usable with
setuptools, for several reasons:
* pkg_resources only loaded one __init__ file for a given package
* pkg_resources couldn't import modules from a zipfile or directory with
no __init__.py
* pkg_resources automatically imports registered namespace packages as
soon as they're discovered, which is not a big deal for empty namespace
packages, but could easily become quite problematic for ones like 'll' that
contain actual code.
So, here's the solution:
* pkg_resources now loads all __init__.py's from all the distributions
that provide contents for the module.
* the bdist_egg command automatically generates a dummy __init__.py for
packages that don't have them. The __init__.py file contains the single line:
__import__('pkg_resources').declare_namespace(__name__)
This ensures that the other package contents are importable, and that
as soon as an import of the package occurs, it gets registered as a
namespace package.
* projects that use this approach to namespace packaging must *NOT*
pass a 'namespace_packages' argument to setup(), because that would cause
the package to be imported even when it isn't necessary. They must also
put a 'declare_namespace()' call in all of their __init__.py's, to ensure
that the package will become a namespace no matter what the order of
distributions on sys.path is.
Because of the complexity of this approach, I do not recommend it for new
projects. Namespace packages should not have code in any of their
__init__.py files, as it eliminates all of these headaches. So, this is an
experimental feature intended to facilitate backward compatibility
only. Don't expect it to show up in the documentation any time soon!
Anyway, I was able to get this to work for ll-core and ll-color, as long as
I added a 'declare_namespace()' call like the one shown above to ll-core's
__init__.py, and made them both use setuptools. I would appreciate any
feedback that folks have on this.
By the way, because SourceForge CVS updating is slow, it may be a few hours
before you can check out the version of setuptools that supports
this. Make sure you have pkg_resources.py revision 1.69 or higher, and
setuptools/command/bdist_egg.py revision 1.28 or higher, if you want to
experiment. Thanks.
More information about the Distutils-SIG
mailing list