[Distutils] pkg_resources get_distribution - zipfile support?

PJ Eby pje at telecommunity.com
Wed Oct 2 01:52:20 CEST 2013


On Tue, Oct 1, 2013 at 5:11 PM, Paul Moore <p.f.moore at gmail.com> wrote:
> On 1 October 2013 21:32, PJ Eby <pje at telecommunity.com> wrote:
>> On Tue, Oct 1, 2013 at 1:51 PM, Daniel Holth <dholth at gmail.com> wrote:
>>> pkg_resources only finds distributions inside .egg and inside sys.path
>>> entries that are filesystem directories.
>>
>> Actually it looks in zipfiles (or subdirectory paths thereof) or
>> filesystem directories, and can spot zipfile subdirectories named
>> '.egg' inside zipfiles (or subdirectories thereof).
>
> But not dist-info? I thought setuptools supported dist-info formats
> these days. Is this somewhere that got missed? Or is it more subtle
> than that?

The person or persons who implemented dist-info either didn't know
where to put in the support, or didn't consider it a priority to also
support zipped dist-info.

A cursory glance at the DistinfoDistribution class, however, suggests
that it should work fine as long as it's paired with an appropriate
metadata provider.  Something like:

    class WheelMetadata(EggMetadata):
        def _setup_prefix(self):
            # like EggProvider._setup_prefix, except w/".whl" and
            # ".dist-info" instead of ".egg" and "EGG-INFO"
            # ... or refactor EggProvider to parameterize these as
            # class attrs and override here

and then make find_in_zip look more like:

def find_in_zip(importer, path_item, only=False):
    for (meta_factory, fn, dist_factory) in [
        (EggMetadata, 'PKG-INFO', Distribution),
        (WheelMetadata, 'METADATA', DistInfoDistribution),
    ]:
        metadata = meta_factory(importer)
        if metadata.has_metadata(fn):
            yield dist_factory.from_filename(path_item, metadata=metadata)
    if only:
        return  # don't yield nested distros
    for subitem in metadata.resource_listdir('/'):
        if subitem.endswith('.egg') or subitem.endswith('.whl'):
            subpath = os.path.join(path_item, subitem)
            for dist in find_in_zip(zipimport.zipimporter(subpath), subpath):
                yield dist

So it's not a huge deal to implement, just a bit of tedium.  Under the
hood, there's little difference between wheels and eggs besides naming
conventions.


More information about the Distutils-SIG mailing list