Example #1
0
def _convert(egginfo_dir, distinfo_dir=None, handlers=egginfo_handlers):
    """Converts an .egg-info directory structure to a .dist-info structure.
    """
    pkginfo = os.path.join(egginfo_dir, PKGINFO)
    metadata = Metadata(pkginfo)
    #: Define a .dist-info directory location if one wasn't given
    if distinfo_dir is None:
        # Name the directory based on the metadata and PEP 376 naming:
        # http://www.python.org/dev/peps/pep-0376/#one-dist-info-directory-per-installed-distribution
        container = os.path.abspath(egginfo_dir).split(os.sep)[:-1]
        container = os.path.join(*container)
        dirname = "{0}-{1}.dist-info"\
                  .format(metadata['Name'], metadata['Version'])
        distinfo_dir = os.path.join(container, dirname)
    #: Create the .dist-info directory if it doesn't exits
    if not os.path.exists(distinfo_dir):
        os.makedirs(distinfo_dir)
    distinfo_metadata = os.path.join(distinfo_dir, METADATA)
    shutil.copy2(pkginfo, distinfo_metadata)
    #: Pave over the exist metadata variable and use the .dist-info one
    metadata = Metadata(distinfo_metadata)

    fields, version = up_convert(metadata._fields)
    #: Update the fileds and metadata version
    metadata.update(fields)

    if not isinstance(handlers, Registry):
        raise TypeError("Expected a Registry objects recieved a {0}"\
                        .format(type(handlers)))
    handlers.init_handlers(metadata, egginfo_dir)

    for name in handlers:
        handlers[name]()

    metadata.write(distinfo_metadata)
    return distinfo_dir
Example #2
0
    def test_mapping_api(self):
        PKG_INFO = os.path.join(os.path.dirname(__file__), 'PKG-INFO')
        with open(PKG_INFO, 'r', encoding='utf-8') as f:
            content = f.read() % sys.platform
        metadata = Metadata(fileobj=StringIO(content))
        self.assertIn('Version', metadata.keys())
        self.assertIn('0.5', metadata.values())
        self.assertIn(('Version', '0.5'), metadata.items())

        metadata.update({'version': '0.6'})
        self.assertEqual(metadata['Version'], '0.6')
        metadata.update([('version', '0.7')])
        self.assertEqual(metadata['Version'], '0.7')

        # make sure update method checks values like the set method does
        metadata.update({'version': '1--2'})
        self.assertEqual(len(self.get_logs()), 1)

        # XXX caveat: the keys method and friends are not 3.x-style views
        # should be changed or documented
        self.assertEqual(list(metadata), metadata.keys())
Example #3
0
class ReleaseInfo(IndexReference):
    """Represent a release of a project (a project with a specific version).
    The release contain the _metadata informations related to this specific
    version, and is also a container for distribution related informations.

    See the DistInfo class for more information about distributions.
    """

    def __init__(self, name, version, metadata=None, hidden=False,
                 index=None, **kwargs):
        """
        :param name: the name of the distribution
        :param version: the version of the distribution
        :param metadata: the metadata fields of the release.
        :type metadata: dict
        :param kwargs: optional arguments for a new distribution.
        """
        self.set_index(index)
        self.name = name
        self._version = None
        self.version = version
        if metadata:
            self.metadata = Metadata(mapping=metadata)
        else:
            self.metadata = None
        self.dists = {}
        self.hidden = hidden

        if 'dist_type' in kwargs:
            dist_type = kwargs.pop('dist_type')
            self.add_distribution(dist_type, **kwargs)

    def set_version(self, version):
        try:
            self._version = NormalizedVersion(version)
        except IrrationalVersionError:
            suggestion = suggest_normalized_version(version)
            if suggestion:
                self.version = suggestion
            else:
                raise IrrationalVersionError(version)

    def get_version(self):
        return self._version

    version = property(get_version, set_version)

    def fetch_metadata(self):
        """If the metadata is not set, use the indexes to get it"""
        if not self.metadata:
            self._index.get_metadata(self.name, str(self.version))
        return self.metadata

    @property
    def is_final(self):
        """proxy to version.is_final"""
        return self.version.is_final

    def fetch_distributions(self):
        if self.dists is None:
            self._index.get_distributions(self.name, str(self.version))
            if self.dists is None:
                self.dists = {}
        return self.dists

    def add_distribution(self, dist_type='sdist', python_version=None,
                         **params):
        """Add distribution informations to this release.
        If distribution information is already set for this distribution type,
        add the given url paths to the distribution. This can be useful while
        some of them fails to download.

        :param dist_type: the distribution type (eg. "sdist", "bdist", etc.)
        :param params: the fields to be passed to the distribution object
                       (see the :class:DistInfo constructor).
        """
        if dist_type not in DIST_TYPES:
            raise ValueError(dist_type)
        if dist_type in self.dists:
            self.dists[dist_type].add_url(**params)
        else:
            self.dists[dist_type] = DistInfo(self, dist_type,
                                             index=self._index, **params)
        if python_version:
            self.dists[dist_type].python_version = python_version

    def get_distribution(self, dist_type=None, prefer_source=True):
        """Return a distribution.

        If dist_type is set, find first for this distribution type, and just
        act as an alias of __get_item__.

        If prefer_source is True, search first for source distribution, and if
        not return one existing distribution.
        """
        if len(self.dists) == 0:
            raise LookupError
        if dist_type:
            return self[dist_type]
        if prefer_source:
            if "sdist" in self.dists:
                dist = self["sdist"]
            else:
                dist = next(self.dists.values())
            return dist

    def unpack(self, path=None, prefer_source=True):
        """Unpack the distribution to the given path.

        If not destination is given, creates a temporary location.

        Returns the location of the extracted files (root).
        """
        return self.get_distribution(prefer_source=prefer_source)\
                   .unpack(path=path)

    def download(self, temp_path=None, prefer_source=True):
        """Download the distribution, using the requirements.

        If more than one distribution match the requirements, use the last
        version.
        Download the distribution, and put it in the temp_path. If no temp_path
        is given, creates and return one.

        Returns the complete absolute path to the downloaded archive.
        """
        return self.get_distribution(prefer_source=prefer_source)\
                   .download(path=temp_path)

    def set_metadata(self, metadata):
        if not self.metadata:
            self.metadata = Metadata()
        self.metadata.update(metadata)

    def __getitem__(self, item):
        """distributions are available using release["sdist"]"""
        return self.dists[item]

    def _check_is_comparable(self, other):
        if not isinstance(other, ReleaseInfo):
            raise TypeError("cannot compare %s and %s"
                % (type(self).__name__, type(other).__name__))
        elif self.name != other.name:
            raise TypeError("cannot compare %s and %s"
                % (self.name, other.name))

    def __repr__(self):
        return "<%s %s>" % (self.name, self.version)

    def __eq__(self, other):
        self._check_is_comparable(other)
        return self.version == other.version

    def __lt__(self, other):
        self._check_is_comparable(other)
        return self.version < other.version

    def __ne__(self, other):
        return not self.__eq__(other)

    def __gt__(self, other):
        return not (self.__lt__(other) or self.__eq__(other))

    def __le__(self, other):
        return self.__eq__(other) or self.__lt__(other)

    def __ge__(self, other):
        return self.__eq__(other) or self.__gt__(other)

    # See http://docs.python.org/reference/datamodel#object.__hash__
    __hash__ = object.__hash__