Esempio n. 1
0
def obsoletes_distribution(name, version=None, use_egg_info=False):
    """
    Iterates over all distributions to find which distributions obsolete
    *name*.

    If a *version* is provided, it will be used to filter the results.
    If the argument *use_egg_info* is set to ``True``, then ``.egg-info``
    distributions will be considered as well.

    :type name: string
    :type version: string
    :parameter name:
    """
    for dist in get_distributions(use_egg_info):
        obsoleted = (dist.metadata['Obsoletes-Dist'] +
                     dist.metadata['Obsoletes'])
        for obs in obsoleted:
            o_components = obs.split(' ', 1)
            if len(o_components) == 1 or version is None:
                if name == o_components[0]:
                    yield dist
                    break
            else:
                try:
                    predicate = VersionPredicate(obs)
                except ValueError:
                    raise DistutilsError(('Distribution %s has ill formed' +
                                          ' obsoletes field') % (dist.name,))
                if name == o_components[0] and predicate.match(version):
                    yield dist
                    break
Esempio n. 2
0
def generate_graph(dists):
    """Generates a dependency graph from the given distributions.

    :parameter dists: a list of distributions
    :type dists: list of :class:`pkgutil.Distribution` and
                         :class:`pkgutil.EggInfoDistribution` instances
    :rtype: an :class:`DependencyGraph` instance
    """
    graph = DependencyGraph()
    provided = {} # maps names to lists of (version, dist) tuples
    dists = list(dists) # maybe use generator_tools in future

    # first, build the graph and find out the provides
    for dist in dists:
        graph.add_distribution(dist)
        provides = dist.metadata['Provides-Dist'] + dist.metadata['Provides']

        for p in provides:
            comps = p.strip().rsplit(" ", 1)
            name = comps[0]
            version = None
            if len(comps) == 2:
                version = comps[1]
                if len(version) < 3 or version[0] != '(' or version[-1] != ')':
                    raise DistutilsError('Distribution %s has ill formed' \
                                         'provides field: %s' % (dist.name, p))
                version = version[1:-1] # trim off parenthesis
            if not name in provided:
                provided[name] = []
            provided[name].append((version, dist))

    # now make the edges
    for dist in dists:
        requires = dist.metadata['Requires-Dist'] + dist.metadata['Requires']
        for req in requires:
            predicate = VersionPredicate(req)
            name = predicate.name

            if not name in provided:
                graph.add_missing(dist, req)
            else:
                matched = False
                for version, provider in provided[name]:
                    try:
                        match = predicate.match(version)
                    except IrrationalVersionError:
                        # XXX small compat-mode
                        if version.split(' ' ) == 1:
                            match = True
                        else:
                            match = False

                    if match:
                        graph.add_edge(dist, provider, req)
                        matched = True
                        break
                if not matched:
                    graph.add_missing(dist, req)

    return graph
Esempio n. 3
0
def obsoletes_distribution(name, version=None, use_egg_info=True):
    """
    Iterates over all distributions to find which distributions obsolete
    *name*.

    If a *version* is provided, it will be used to filter the results.
    If the argument *use_egg_info* is set to ``True``, then ``.egg-info``
    distributions will be considered as well.

    :type name: string
    :type version: string
    :parameter name:
    """
    for dist in get_distributions(use_egg_info):
        obsoleted = (dist.metadata['Obsoletes-Dist'] +
                     dist.metadata['Obsoletes'])
        for obs in obsoleted:
            o_components = obs.split(' ', 1)
            if len(o_components) == 1 or version is None:
                if name == o_components[0]:
                    yield dist
                    break
            else:
                try:
                    predicate = VersionPredicate(obs)
                except ValueError:
                    raise PackagingError(
                        'distribution %r has ill-formed obsoletes field: '
                        '%r' % (dist.name, obs))
                if name == o_components[0] and predicate.match(version):
                    yield dist
                    break
Esempio n. 4
0
def provides_distribution(name, version=None, use_egg_info=True):
    """
    Iterates over all distributions to find which distributions provide *name*.
    If a *version* is provided, it will be used to filter the results. Scans
    all elements in ``sys.path``  and looks for all directories ending with
    ``.dist-info``. Returns a :class:`Distribution`  corresponding to the
    ``.dist-info`` directory that contains a ``METADATA`` that matches *name*
    for the name metadata. If the argument *use_egg_info* is set to ``True``,
    then all files and directories ending with ``.egg-info`` are considered
    as well and returns an :class:`EggInfoDistribution` instance.

    This function only returns the first result found, since no more than
    one values are expected. If the directory is not found, returns ``None``.

    :parameter version: a version specifier that indicates the version
                        required, conforming to the format in ``PEP-345``

    :type name: string
    :type version: string
    """
    predicate = None
    if not version is None:
        try:
            predicate = VersionPredicate(name + ' (' + version + ')')
        except ValueError:
            raise PackagingError('invalid name or version: %r, %r' %
                                 (name, version))

    for dist in get_distributions(use_egg_info):
        provided = dist.metadata['Provides-Dist'] + dist.metadata['Provides']

        for p in provided:
            p_components = p.rsplit(' ', 1)
            if len(p_components) == 1 or predicate is None:
                if name == p_components[0]:
                    yield dist
                    break
            else:
                p_name, p_ver = p_components
                if len(p_ver) < 2 or p_ver[0] != '(' or p_ver[-1] != ')':
                    raise PackagingError(
                        'distribution %r has invalid Provides field: %r' %
                        (dist.name, p))
                p_ver = p_ver[1:-1]  # trim off the parenthesis
                if p_name == name and predicate.match(p_ver):
                    yield dist
                    break
Esempio n. 5
0
def provides_distribution(name, version=None, use_egg_info=True):
    """
    Iterates over all distributions to find which distributions provide *name*.
    If a *version* is provided, it will be used to filter the results. Scans
    all elements in ``sys.path``  and looks for all directories ending with
    ``.dist-info``. Returns a :class:`Distribution`  corresponding to the
    ``.dist-info`` directory that contains a ``METADATA`` that matches *name*
    for the name metadata. If the argument *use_egg_info* is set to ``True``,
    then all files and directories ending with ``.egg-info`` are considered
    as well and returns an :class:`EggInfoDistribution` instance.

    This function only returns the first result found, since no more than
    one values are expected. If the directory is not found, returns ``None``.

    :parameter version: a version specifier that indicates the version
                        required, conforming to the format in ``PEP-345``

    :type name: string
    :type version: string
    """
    predicate = None
    if not version is None:
        try:
            predicate = VersionPredicate(name + ' (' + version + ')')
        except ValueError:
            raise PackagingError('invalid name or version: %r, %r' %
                                 (name, version))

    for dist in get_distributions(use_egg_info):
        provided = dist.metadata['Provides-Dist'] + dist.metadata['Provides']

        for p in provided:
            p_components = p.rsplit(' ', 1)
            if len(p_components) == 1 or predicate is None:
                if name == p_components[0]:
                    yield dist
                    break
            else:
                p_name, p_ver = p_components
                if len(p_ver) < 2 or p_ver[0] != '(' or p_ver[-1] != ')':
                    raise PackagingError(
                        'distribution %r has invalid Provides field: %r' %
                        (dist.name, p))
                p_ver = p_ver[1:-1]  # trim off the parenthesis
                if p_name == name and predicate.match(p_ver):
                    yield dist
                    break
Esempio n. 6
0
 def test_filter(self):
     # Test we filter the distributions the right way, using version
     # predicate match method
     releases = ReleasesList('FooBar', (
         ReleaseInfo("FooBar", "1.1"),
         ReleaseInfo("FooBar", "1.1.1"),
         ReleaseInfo("FooBar", "1.2"),
         ReleaseInfo("FooBar", "1.2.1"),
     ))
     filtered = releases.filter(VersionPredicate("FooBar (<1.2)"))
     self.assertNotIn(releases[2], filtered)
     self.assertNotIn(releases[3], filtered)
     self.assertIn(releases[0], filtered)
     self.assertIn(releases[1], filtered)
Esempio n. 7
0
 def test_micro_predicate(self):
     self.assertNotEqual(V('3.4.0'), V('3.4'))
     predicate = VersionPredicate('zope.event (3.4.0)')
     self.assertTrue(predicate.match('3.4.0'))
     self.assertFalse(predicate.match('3.4.1'))
Esempio n. 8
0
    def test_predicate_name(self):
        # Test that names are parsed the right way

        self.assertEqual('Hey', VersionPredicate('Hey (<1.1)').name)
        self.assertEqual('Foo-Bar', VersionPredicate('Foo-Bar (1.1)').name)
        self.assertEqual('Foo Bar', VersionPredicate('Foo Bar (1.1)').name)
Esempio n. 9
0
    def test_predicate(self):
        # VersionPredicate knows how to parse stuff like:
        #
        #   Project (>=version, ver2)

        predicates = ('zope.interface (>3.5.0)',
                      'AnotherProject (3.4)',
                      'OtherProject (<3.0)',
                      'NoVersion',
                      'Hey (>=2.5,<2.7)')

        for predicate in predicates:
            VersionPredicate(predicate)

        self.assertTrue(VersionPredicate('Hey (>=2.5,<2.7)').match('2.6'))
        self.assertTrue(VersionPredicate('Ho').match('2.6'))
        self.assertFalse(VersionPredicate('Hey (>=2.5,!=2.6,<2.7)').match('2.6'))
        self.assertTrue(VersionPredicate('Ho (<3.0)').match('2.6'))
        self.assertTrue(VersionPredicate('Ho (<3.0,!=2.5)').match('2.6.0'))
        self.assertFalse(VersionPredicate('Ho (<3.0,!=2.6)').match('2.6.0'))
        self.assertTrue(VersionPredicate('Ho (2.5)').match('2.5.4'))
        self.assertFalse(VersionPredicate('Ho (!=2.5)').match('2.5.2'))
        self.assertTrue(VersionPredicate('Hey (<=2.5)').match('2.5.9'))
        self.assertFalse(VersionPredicate('Hey (<=2.5)').match('2.6.0'))
        self.assertTrue(VersionPredicate('Hey (>=2.5)').match('2.5.1'))

        self.assertRaises(ValueError, VersionPredicate, '')

        self.assertTrue(VersionPredicate('Hey 2.5').match('2.5.1'))

        # XXX need to silent the micro version in this case
        self.assertFalse(VersionPredicate('Ho (<3.0,!=2.6)').match('2.6.3'))

        # Make sure a predicate that ends with a number works
        self.assertTrue(VersionPredicate('virtualenv5 (1.0)').match('1.0'))
        self.assertTrue(VersionPredicate('virtualenv5').match('1.0'))
        self.assertTrue(VersionPredicate('vi5two').match('1.0'))
        self.assertTrue(VersionPredicate('5two').match('1.0'))
        self.assertTrue(VersionPredicate('vi5two 1.0').match('1.0'))
        self.assertTrue(VersionPredicate('5two 1.0').match('1.0'))

        # test repr
        for predicate in predicates:
            self.assertEqual(str(VersionPredicate(predicate)), predicate)
Esempio n. 10
0
def generate_graph(dists):
    """Generates a dependency graph from the given distributions.

    :parameter dists: a list of distributions
    :type dists: list of :class:`distutils2.database.Distribution` and
                 :class:`distutils2.database.EggInfoDistribution` instances
    :rtype: a :class:`DependencyGraph` instance
    """
    graph = DependencyGraph()
    provided = {}  # maps names to lists of (version, dist) tuples

    # first, build the graph and find out the provides
    for dist in dists:
        graph.add_distribution(dist)
        provides = (dist.metadata['Provides-Dist'] +
                    dist.metadata['Provides'] +
                    ['%s (%s)' % (dist.name, dist.version)])

        for p in provides:
            comps = p.strip().rsplit(" ", 1)
            name = comps[0]
            version = None
            if len(comps) == 2:
                version = comps[1]
                if len(version) < 3 or version[0] != '(' or version[-1] != ')':
                    raise PackagingError('distribution %r has ill-formed'
                                         'provides field: %r' % (dist.name, p))
                version = version[1:-1]  # trim off parenthesis
            if name not in provided:
                provided[name] = []
            provided[name].append((version, dist))

    # now make the edges
    for dist in dists:
        requires = dist.metadata['Requires-Dist'] + dist.metadata['Requires']
        for req in requires:
            try:
                predicate = VersionPredicate(req)
            except IrrationalVersionError:
                # XXX compat-mode if cannot read the version
                name = req.split()[0]
                predicate = VersionPredicate(name)

            name = predicate.name

            if name not in provided:
                graph.add_missing(dist, req)
            else:
                matched = False
                for version, provider in provided[name]:
                    try:
                        match = predicate.match(version)
                    except IrrationalVersionError:
                        # XXX small compat-mode
                        if version.split(' ') == 1:
                            match = True
                        else:
                            match = False

                    if match:
                        graph.add_edge(dist, provider, req)
                        matched = True
                        break
                if not matched:
                    graph.add_missing(dist, req)
    return graph