[Import-SIG] Do we really need to read .pth files in PEP 382?

P.J. Eby pje at telecommunity.com
Sat Jun 25 00:24:41 CEST 2011


At 05:18 PM 6/24/2011 -0400, Barry Warsaw wrote:
>On Jun 24, 2011, at 05:15 PM, P.J. Eby wrote:
> >I'm fine with another name. (namespace_subpath(), perhaps?)
>
>Done!  Bikeshed painted! :)
>
> >I've coded up a sketch of a 2.x implementation (enabled via "from pep382
> >import meta_importer; meta_importer.install()") using that basic API
> >approach, and it's pretty clean.
>
>I would love to be able to back port this to Python 3.2.

Well, my sketch is probably forward-portable, but my brain hasn't 
been ported to 3.x yet, so you'll have to translate it yourself.  ;-)


>Supporting clean namespace packages in Python 2.{6,7} would be double win.

I guess supporting it for 2.3, 2.4, and 2.5 would be triple win, then.  ;-)


>Do you want to push the code to Cheeseshop, or make a branch available
>somewhere?

When I say "sketch", I mean it's just some code typed into a file 
where I sketch bits of Python code - it's not been tested or even 
compiled, let alone run.  ;-)

I'll stick it in a pastebin for you, though; it's barely more than 150 lines:

    http://pastebin.com/uFQ9iwXQ

Some bits of the code are a little hairy, since they're basically 
dynamically adding namespace_subpath() to existing importer objects, 
or working around the fact that existing loaders expect that *they* 
will set the module __path__.  There's then some further hairiness 
created by the need to set __loader__ and __file__ correctly when the 
workaround for the preceding problem is applied.  ;-)

For Python 2.5+, this code can stand alone, but for 2.3 and 2.4 it 
uses pkg_resources from setuptools, as those versions of the Python 
stdlib don't include pkgutil.ImpImporter and pkgutil.get_importer.

Finally, note that the code is designed to be used with explicit 
registration by default: unless you call meta_importer.install(), 
namespace packages have to be registered with 
'pep382.register_namespace()'.  This is a compromise for import 
performance reasons, as the search for '.ns'-containing 
subdirectories adds extra stat() calls per sys.path entry per import, 
which can be hugely slow on a network.

Explicit registration avoids this overhead for anything that's not 
already known ahead of time to be a namespace package, and 
pkg_resources already uses explicit registration, so it's no big deal 
to hook it up there.  The plan would be for setuptools 0.7 to write 
.pth files that "import pep382; 
pep382.register_namespace('whatever')" in place of its existing 
__path__-hackery, as well as for setuptools' declare_namespace() et 
al to use pep382 code behind-the-scenes.

However, for non-setuptools uses, a simple "meta_importer.install()" 
suffices to enable the module in a fully PEP-compatible mode, at the 
cost of added stat() calls.  (The official PEP 382 implementation can 
avoid the extra stat() calls because it'll be directly modifying the 
stdlib importers, rather than working around them.)

Anyway... reminder: this code is an UNTESTED SKETCH with LIMITED 
DOCUMENTATION, and it might contain errors ranging from simple typos 
to subtle-yet-awful design flaws that won't surface for months or 
years.  You have been warned.  ;-)

(Hm, actually, I just thought of a possible bug/oversight -- this 
code doesn't either check or ensure that parent packages of a 
namespace package are registered as namespaces.  That's okay for 
setuptools' purposes, but might lead to incompatibilities between 
third-party code registering packages and third-party code inspecting 
namespace packages and expecting the "parent of a namespace is also a 
namespace" invariant to apply.)



More information about the Import-SIG mailing list