Example #1
0
 def get_release(self, requirements, prefer_final=None):
     """Return only one release that fulfill the given requirements"""
     predicate = get_version_predicate(requirements)
     release = self.get_releases(predicate, prefer_final)\
                   .get_last(predicate)
     if not release:
         raise ReleaseNotFound("No release matches the given criterias")
     return release
Example #2
0
 def get_release(self, requirements, prefer_final=False):
     """Return a release with all complete metadata and distribution
     related informations.
     """
     prefer_final = self._get_prefer_final(prefer_final)
     predicate = get_version_predicate(requirements)
     releases = self.get_releases(predicate.name)
     release = releases.get_last(predicate, prefer_final)
     self.get_metadata(release.name, str(release.version))
     self.get_distributions(release.name, str(release.version))
     return release
Example #3
0
    def get_last(self, requirements, prefer_final=None):
        """Return the "last" release, that satisfy the given predicates.

        "last" is defined by the version number of the releases, you also could
        set prefer_final parameter to True or False to change the order results
        """
        predicate = get_version_predicate(requirements)
        releases = self.filter(predicate)
        if len(releases) == 0:
            return None
        releases.sort_releases(prefer_final, reverse=True)
        return releases[0]
Example #4
0
    def get_releases(self, requirements, prefer_final=None, show_hidden=True,
                     force_update=False):
        """Return the list of existing releases for a specific project.

        Cache the results from one call to another.

        If show_hidden is True, return the hidden releases too.
        If force_update is True, reprocess the index to update the
        informations (eg. make a new XML-RPC call).
        ::

            >>> client = Client()
            >>> client.get_releases('Foo')
            ['1.1', '1.2', '1.3']

        If no such project exists, raise a ProjectNotFound exception::

            >>> client.get_project_versions('UnexistingProject')
            ProjectNotFound: UnexistingProject

        """
        def get_versions(project_name, show_hidden):
            return self.proxy.package_releases(project_name, show_hidden)

        predicate = get_version_predicate(requirements)
        prefer_final = self._get_prefer_final(prefer_final)
        project_name = predicate.name
        if not force_update and (project_name.lower() in self._projects):
            project = self._projects[project_name.lower()]
            if not project.contains_hidden and show_hidden:
                # if hidden releases are requested, and have an existing
                # list of releases that does not contains hidden ones
                all_versions = get_versions(project_name, show_hidden)
                existing_versions = project.get_versions()
                hidden_versions = set(all_versions) - set(existing_versions)
                for version in hidden_versions:
                    project.add_release(release=ReleaseInfo(project_name,
                                            version, index=self._index))
        else:
            versions = get_versions(project_name, show_hidden)
            if not versions:
                raise ProjectNotFound(project_name)
            project = self._get_project(project_name)
            project.add_releases([ReleaseInfo(project_name, version,
                                              index=self._index)
                                  for version in versions])
        project = project.filter(predicate)
        if len(project) == 0:
            raise ReleaseNotFound("%s" % predicate)
        project.sort_releases(prefer_final)
        return project
Example #5
0
    def get_releases(self, requirements, prefer_final=None,
                     force_update=False):
        """Search for releases and return a ReleasesList object containing
        the results.
        """
        predicate = get_version_predicate(requirements)
        if predicate.name.lower() in self._projects and not force_update:
            return self._projects.get(predicate.name.lower())
        prefer_final = self._get_prefer_final(prefer_final)
        logger.debug('Reading info on PyPI about %s', predicate.name)
        self._process_index_page(predicate.name)

        if predicate.name.lower() not in self._projects:
            raise ProjectNotFound

        releases = self._projects.get(predicate.name.lower())
        releases.sort_releases(prefer_final=prefer_final)
        return releases
Example #6
0
def get_infos(requirements, index=None, installed=None, prefer_final=True):
    """Return the informations on what's going to be installed and upgraded.

    :param requirements: is a *string* containing the requirements for this
                         project (for instance "FooBar 1.1" or "BarBaz (<1.2)")
    :param index: If an index is specified, use this one, otherwise, use
                  :class index.ClientWrapper: to get project metadatas.
    :param installed: a list of already installed distributions.
    :param prefer_final: when picking up the releases, prefer a "final" one
                         over a beta/alpha/etc one.

    The results are returned in a dict, containing all the operations
    needed to install the given requirements::

        >>> get_install_info("FooBar (<=1.2)")
        {'install': [<FooBar 1.1>], 'remove': [], 'conflict': []}

    Conflict contains all the conflicting distributions, if there is a
    conflict.
    """
    # this function does several things:
    # 1. get a release specified by the requirements
    # 2. gather its metadata, using setuptools compatibility if needed
    # 3. compare this tree with what is currently installed on the system,
    #    return the requirements of what is missing
    # 4. do that recursively and merge back the results
    # 5. return a dict containing information about what is needed to install
    #    or remove

    if not installed:
        logger.debug('Reading installed distributions')
        installed = list(get_distributions(use_egg_info=True))

    infos = {'install': [], 'remove': [], 'conflict': []}
    # Is a compatible version of the project already installed ?
    predicate = get_version_predicate(requirements)
    found = False

    # check that the project isn't already installed
    for installed_project in installed:
        # is it a compatible project ?
        if predicate.name.lower() != installed_project.name.lower():
            continue
        found = True
        logger.info('Found %r %s', installed_project.name,
                    installed_project.version)

        # if we already have something installed, check it matches the
        # requirements
        if predicate.match(installed_project.version):
            return infos
        break

    if not found:
        logger.debug('Project not installed')

    if not index:
        index = wrapper.ClientWrapper()

    if not installed:
        installed = get_distributions(use_egg_info=True)

    # Get all the releases that match the requirements
    try:
        release = index.get_release(requirements)
    except (ReleaseNotFound, ProjectNotFound):
        raise InstallationException('Release not found: %r' % requirements)

    if release is None:
        logger.info('Could not find a matching project')
        return infos

    metadata = release.fetch_metadata()

    # we need to build setuptools deps if any
    if 'requires_dist' not in metadata:
        metadata['requires_dist'] = _get_setuptools_deps(release)

    # build the dependency graph with local and required dependencies
    dists = list(installed)
    dists.append(release)
    depgraph = generate_graph(dists)

    # Get what the missing deps are
    dists = depgraph.missing[release]
    if dists:
        logger.info("Missing dependencies found, retrieving metadata")
        # we have missing deps
        for dist in dists:
            _update_infos(infos, get_infos(dist, index, installed))

    # Fill in the infos
    existing = [d for d in installed if d.name == release.name]
    if existing:
        infos['remove'].append(existing[0])
        infos['conflict'].extend(depgraph.reverse_list[existing[0]])
    infos['install'].append(release)
    return infos