def test_candidate_inconsistent_error():
    requirement = "foo"
    candidate = "bar"

    class Provider(AbstractProvider):
        def identify(self, d):
            assert d is requirement or d is candidate
            return d

        def get_preference(self, *_):
            return 0

        def get_dependencies(self, _):
            return []

        def find_matches(self, rs):
            assert len(rs) == 1 and rs[0] is requirement
            return [candidate]

        def is_satisfied_by(self, r, c):
            assert r is requirement
            assert c is candidate
            return False

    resolver = Resolver(Provider(), BaseReporter())

    with pytest.raises(InconsistentCandidate) as ctx:
        resolver.resolve([requirement])

    assert str(ctx.value) == "Provided candidate 'bar' does not satisfy 'foo'"
    assert ctx.value.candidate is candidate
    assert list(ctx.value.criterion.iter_requirement()) == [requirement]
Exemple #2
0
 def run_resolver(*args):
     reporter = Reporter()
     resolver = Resolver(Provider(), reporter)
     try:
         resolver.resolve(*args)
         return reporter.backtracking_causes
     except ResolutionImpossible as e:
         return e.causes
def test_resolver(provider, base_reporter):
    resolver = Resolver(provider, base_reporter)

    if provider.expected_conflicts:
        with pytest.raises(ResolutionImpossible) as ctx:
            result = resolver.resolve(provider.root_requirements)
            print(_format_resolution(result))  # Provide some debugging hints.
        assert _format_conflicts(ctx.value) == provider.expected_conflicts
    else:
        result = resolver.resolve(provider.root_requirements)
        assert _format_resolution(result) == provider.expected_resolution
Exemple #4
0
def main(reqs):
    # Things I want to resolve.
    requirements = [Requirement(r) for r in reqs]

    provider = Provider()
    reporter = Reporter()

    # Create the (reusable) resolver.
    resolver = Resolver(provider, reporter)

    # Kick off the resolution process, and get the final result.
    result = resolver.resolve(requirements)

    display_resolution(result)
Exemple #5
0
def test_candidate_depends_on_requirements_of_same_identifier(specifiers):
    # This test ensures if a candidate has multiple dependencies under the same
    # identifier, all dependencies of that identifier are correctly pulled in.
    # The parametrization ensures both requirement ordering work.

    # Parent depends on child twice, one allows v2, the other does not.
    # Each candidate is a 3-tuple (name, version, dependencies).
    # Each requirement is a 2-tuple (name, allowed_versions).
    # Candidate v2 is in from so it is preferred when both are allowed.
    all_candidates = {
        "parent": [("parent", "1", [("child", s) for s in specifiers])],
        "child": [("child", "2", []), ("child", "1", [])],
    }

    class Provider(AbstractProvider):
        def identify(self, requirement_or_candidate):
            return requirement_or_candidate[0]

        def get_preference(self, **_):
            return 0

        def get_dependencies(self, candidate):
            return candidate[2]

        def find_matches(self, identifier, requirements, incompatibilities):
            assert not list(incompatibilities[identifier])
            return (candidate for candidate in all_candidates[identifier]
                    if all(candidate[1] in r[1]
                           for r in requirements[identifier]))

        def is_satisfied_by(self, requirement, candidate):
            return candidate[1] in requirement[1]

    # Now when resolved, both requirements to child specified by parent should
    # be pulled, and the resolver should choose v1, not v2 (happens if the
    # v1-only requirement is dropped).
    resolver = Resolver(Provider(), BaseReporter())
    result = resolver.resolve([("parent", {"1"})])

    assert set(result.mapping) == {"parent", "child"}
    assert result.mapping["child"] == ("child", "1", [])
def main():
    """Resolve requirements as project names on PyPI.

    The requirements are taken as command-line arguments
    and the resolution result will be printed to stdout.
    """
    if len(sys.argv) == 1:
        print("Usage:", sys.argv[0], "<PyPI project name(s)>")
        return
    # Things I want to resolve.
    reqs = sys.argv[1:]
    requirements = [Requirement(r) for r in reqs]

    # Create the (reusable) resolver.
    provider = PyPIProvider()
    reporter = BaseReporter()
    resolver = Resolver(provider, reporter)

    # Kick off the resolution process, and get the final result.
    print("Resolving", ", ".join(reqs))
    result = resolver.resolve(requirements)
    display_resolution(result)
def test_candidate_inconsistent_error():
    requirement = "foo"
    candidate = "bar"

    class Provider(AbstractProvider):
        def __init__(self, requirement, candidate):
            self.requirement = requirement
            self.candidate = candidate

        def identify(self, requirement_or_candidate):
            assert requirement_or_candidate is self.requirement
            return requirement_or_candidate

        def get_preference(self, **_):
            return 0

        def get_dependencies(self, **_):
            return []

        def find_matches(self, identifier, requirements, incompatibilities):
            assert list(requirements[identifier]) == [self.requirement]
            assert next(incompatibilities[identifier], None) is None
            return [self.candidate]

        def is_satisfied_by(self, requirement, candidate):
            assert requirement is self.requirement
            assert candidate is self.candidate
            return False

    resolver = Resolver(Provider(requirement, candidate), BaseReporter())

    with pytest.raises(InconsistentCandidate) as ctx:
        resolver.resolve([requirement])

    assert str(ctx.value) == "Provided candidate 'bar' does not satisfy 'foo'"
    assert ctx.value.candidate is candidate
    assert list(ctx.value.criterion.iter_requirement()) == [requirement]
Exemple #8
0
from pypi_wheel_provider import PyPIProvider, Requirement
from visualization.generate import generate_html
from visualization.reporter import GraphGeneratingReporter

from resolvelib import Resolver

if __name__ == "__main__":
    provider = PyPIProvider()
    reporter = GraphGeneratingReporter()

    resolver = Resolver(provider, reporter)

    reqs = [Requirement("oslo.utils==1.4.0")]
    try:
        resolver.resolve(reqs)
    finally:
        with open("out2.html", "w") as f:
            generate_html(reporter.evolution, f)
Exemple #9
0
#collection_requirements = [Requirement('amazon.aws', '1.2.0', None, None)]
#collection_requirements = [Requirement('amazon.aws', '1.2.1-dev3', None, None)]
print()
print('Given collection requirements:')
#print(f'{collection_requirements=}')
for abstract_req in collection_requirements:
    print(f'\t* {abstract_req.fqcn}\t"{abstract_req.ver}"')
print()

context.CLIARGS = {  # patch a value normally populated by the CLI
    'ignore_certs': False,
    'type': 'collection',
}
galaxy_api = GalaxyAPI(Galaxy(), 'default_galaxy', C.GALAXY_SERVER)
resolver = Resolver(
    AnsibleGalaxyProvider(api=galaxy_api),
    BaseReporter(),
)
print()
print('Computing the dependency tree...')
print()
concrete_requirements = resolver.resolve(
    collection_requirements,
    max_rounds=2_000_000,  # avoid too deep backtracking; taken from pip
)
print()
print('Resolved concrete transitive dependencies:')
#print(f'{concrete_requirements=}')
#print(f'{concrete_requirements.mapping=}')
for coll_name, concrete_pin in concrete_requirements.mapping.items():
    print(f'\t* {coll_name}\t"{concrete_pin.ver}"')
print()