import io import os import tarfile import zipfile from .distribution import Distribution class SDist(Distribution): def __init__(self, filename, metadata_version=None): self.filename = filename self.metadata_version = metadata_version self.extractMetadata() @classmethod def _get_archive(cls, fqn): if not os.path.exists(fqn): raise ValueError('No such file: %s' % fqn) if fqn.endswith('.zip'): archive = zipfile.ZipFile(fqn) names = archive.namelist() def read_file(name): return archive.read(name) elif fqn.endswith('gz') or fqn.endswith('bz2'): archive = tarfile.TarFile.open(fqn) names = archive.getnames() def read_file(name): return archive.extractfile(name).read() else: raise ValueError('Not a known archive format: %s' % fqn) return archive, names, read_file def read(self): fqn = os.path.abspath( os.path.normpath(self.filename)) archive, names, read_file = self._get_archive(fqn) try: tuples = [x.split('/') for x in names if 'PKG-INFO' in x] schwarz = sorted([(len(x), x) for x in tuples]) for path in [x[1] for x in schwarz]: candidate = '/'.join(path) data = read_file(candidate) if b'Metadata-Version' in data: return data finally: archive.close() raise ValueError('No PKG-INFO in archive: %s' % fqn) class UnpackedSDist(SDist): def __init__(self, filename, metadata_version=None): if os.path.isdir(filename): pass elif os.path.isfile(filename): filename = os.path.dirname(filename) else: raise ValueError('No such file: %s' % filename) super(UnpackedSDist, self).__init__( filename, metadata_version=metadata_version) def read(self): try: pkg_info = os.path.join(self.filename, 'PKG-INFO') with io.open(pkg_info, errors='ignore') as f: return f.read() except Exception as e: raise ValueError('Could not load %s as an unpacked sdist: %s' % (self.filename, e))