[Distutils] Adding egg support (Resource API) to existing packages
Phillip J. Eby
pje at telecommunity.com
Thu Jul 14 18:14:58 CEST 2005
At 11:56 AM 7/14/2005 -0400, Kevin Dangoor wrote:
>On 7/14/05, Paul Moore <p.f.moore at gmail.com> wrote:
> > You don't care about eggs (yet). Your users (one of whom is me) do,
> > and would like to package your code in an egg via python setup.py
> > --compiler-package=setuptools.command bdist_egg. This works fine, with
> > no source changes, but the resulting egg isn't zip-safe because of
> > resource usage issues.
>
>While I agree with Phillip on this one, I do know what you're saying.
>I've wondered that about some of the packages I'm putting into eggs.
>
>I'm pretty certain this situation will arise where a project
>maintainer won't go for a setuptools dependency. Here's one way to
>deal with it:
>
>Let's say the project's code is in the package:
>
>pythonfoobar
>
>What if you toss pkg_resources into pythonfoobar. Then, in all of the
>modules you touch, you just do:
>
>from pythonfoobar import pkg_resources
*shudder*. Please don't. pkg_resources needs to be a singleton, partly
because sys.path is a singleton, and partly because there needs to be a
single place to register adapters for PEP 302 loaders and importers, and in
the future, egg listeners.
If you guys *really* want to do this, what we need to do is create a
super-simple "mini-Me" form of pkg_resources, that provides exactly two
functions: resource_string and resource_stream.
The code for these will be very short and relatively simple to do, and will
not impact any other part of the egg runtime system; it will just allow
portable resource access.
We can call it 'pkg_resources_lite', or something similar, and I can change
the safety analysis to ignore the fact it uses __file__ (i.e. if the
module's named pkg_resources_lite).
>2) in pythonfoobar/__init__ just import pkg_resources (this is
>assuming you're not using the fancy setuptools namespaces... not many
>projects need that, though.)
Namespaces...? Do you mean namespace packages?
>Ideally, people will go along with setuptools. But, at least this
>workaround won't break people's systems.
Um, yeah. I think, after all this discussion, that the simple way to fix
this is going to be for somebody to produce and maintain a
pkg_resources_lite that people can bundle inside their distributions like
this. It'll even be smaller than ez_setup, although it won't come in the
convenient svn:externals format of ez_setup.
Hm. You know, if pkg_resources_lite is written so that it tries to import
from pkg_resources, then I can make it "step aside and let the professional
handle it" if the user has the full pkg_resources package. This would let
it take advantage of any support for registered import hooks, etc. that the
full package was doing. Something like this:
import sys, os
def _get_path_and_loader(package_name, resource_name):
try:
module = sys.modules[moduleName]
except KeyError:
__import__(moduleName)
module = sys.modules[moduleName]
loader = getattr(module, '__loader__', None)
parts = resource_name.split('/')
path = os.path.join(os.path.dirname(module.__file__),*parts)
return path, loader
def resource_string(package_name, resource_name):
path,loader = _get_path_and_loader(package_name, resource_name)
if loader is None:
f = open(path,'rb')
try:
return f.read()
finally:
f.close()
else:
return loader.get_data(path)
def resource_stream(package_name, resource_name):
path,loader = _get_path_and_loader(package_name, resource_name)
if loader is None:
return open(path,'rb')
else:
from cStringIO import StringIO
return StringIO(loader.get_data(path))
try:
from pkg_resources import resource_string, resource_stream
except ImportError:
pass
Only with some docstrings and comments added. :) Anyway, this thing would
work with eggs or py2exe or just plain zipfiles. It won't necessarily work
with other PEP 302 loader objects, but neither does pkg_resources unless
you register suitable adapters for the functionality needed.
More information about the Distutils-SIG
mailing list