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 PackagingError("distribution %r has ill-formed obsoletes field: " "%r" % (dist.name, obs)) if name == o_components[0] and predicate.match(version): yield dist break
def provides_distribution(name, version=None, use_egg_info=False): """ 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
def test_micro_predicate(): predicate = VersionPredicate("zope.event (3.4.0)") assert predicate.match("3.4.0") assert not predicate.match("3.4.1")
def generate_graph(dists): """Generates a dependency graph from the given distributions. :parameter dists: a list of distributions :type dists: list of :class:`packaging.database.Distribution` and :class:`packaging.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
(validators.metadata_platforms, ["ObscureUnix", "RareDOS" ], ["ObscureUnix", "RareDOS"]), # metadata/supported-platforms (validators.metadata_supported_platforms, ["RedHat 7.2", "i386-win32-2791"], ["RedHat 7.2", "i386-win32-2791"]), # dependencies/python (validators.dependencies_python, ">=2.6", ">=2.6"), # dependencies/extras (validators.dependencies_extras, ["tests", "docs"], ["tests", "docs"]), # dependencies/setup-requires (validators.dependencies_setup_requires, ["custom_setup_command"], [VersionPredicate("custom_setup_command")]), # dependencies/requires (validators.dependencies_requires, ["pkginfo", "PasteDeploy", "zope.interface (>3.5.0)"], [ VersionPredicate("pkginfo"), VersionPredicate("PasteDeploy"), VersionPredicate("zope.interface (>3.5.0)") ]), # dependencies/provides (validators.dependencies_provides, ["packaging (0.1)"], [VersionPredicate("packaging (0.1)")]), # dependencies/obsoletes (validators.dependencies_obsoletes, ["distutils"],
def test_predicate_name(predicate, expected): assert VersionPredicate(predicate).name == expected
def test_predicates_match(predicate, target, matches): assert VersionPredicate(predicate).match(target) == matches
def test_invalid_predicate_raises(): with pytest.raises(ValueError): VersionPredicate("")
def test_str_predicate(predicate): assert str(VersionPredicate(predicate)) == predicate
def test_repr_predicate(predicate): assert repr( VersionPredicate(predicate)) == "VersionPredicate('%s')" % predicate
def test_basic_predicate(predicate, name, predicates): pred = VersionPredicate(predicate) assert pred.name == name assert pred.predicates == predicates