Пример #1
0
def test_circular_dependency(source):
    source.root_dep("foo", "1.0.0")

    source.add("foo", "1.0.0", deps={"bar": "1.0.0"})
    source.add("bar", "1.0.0", deps={"foo": "1.0.0"})

    check_solver_result(source, {"foo": "1.0.0", "bar": "1.0.0"})
Пример #2
0
def test_circular_dependency_on_older_version(source):
    source.root_dep("a", ">=1.0.0")

    source.add("a", "1.0.0")
    source.add("a", "2.0.0", deps={"b": "1.0.0"})
    source.add("b", "1.0.0", deps={"a": "1.0.0"})

    check_solver_result(source, {"a": "1.0.0"}, tries=2)
Пример #3
0
def test_no_version_matching_constraint(source):
    source.root_dep("foo", "^1.0")

    source.add("foo", "2.0.0")
    source.add("foo", "2.1.3")

    check_solver_result(
        source,
        error=("Because root depends on foo (^1.0) "
               "which doesn't match any versions, version solving failed."),
    )
Пример #4
0
def test_disjoint_root_constraints(source):
    source.root_dep("foo", "1.0.0")
    source.root_dep("foo", "2.0.0")

    source.add("foo", "1.0.0")
    source.add("foo", "2.0.0")

    error = """\
Because root depends on both foo (1.0.0) and foo (2.0.0), version solving failed."""

    check_solver_result(source, error=error)
Пример #5
0
def test_shared_dependencies_with_overlapping_constraints(source):
    source.root_dep("a", "1.0.0")
    source.root_dep("b", "1.0.0")

    source.add("a", "1.0.0", deps={"shared": ">=2.0.0 <4.0.0"})
    source.add("b", "1.0.0", deps={"shared": ">=3.0.0 <5.0.0"})
    source.add("shared", "2.0.0")
    source.add("shared", "3.0.0")
    source.add("shared", "3.6.9")
    source.add("shared", "4.0.0")
    source.add("shared", "5.0.0")

    check_solver_result(source, {"a": "1.0.0", "b": "1.0.0", "shared": "3.6.9"})
Пример #6
0
def test_shared_dependency_where_dependent_version_affects_other_dependencies(source):
    source.root_dep("foo", "<=1.0.2")
    source.root_dep("bar", "1.0.0")

    source.add("foo", "1.0.0")
    source.add("foo", "1.0.1", deps={"bang": "1.0.0"})
    source.add("foo", "1.0.2", deps={"whoop": "1.0.0"})
    source.add("foo", "1.0.3", deps={"zoop": "1.0.0"})
    source.add("bar", "1.0.0", deps={"foo": "<=1.0.1"})
    source.add("bang", "1.0.0")
    source.add("whoop", "1.0.0")
    source.add("zoop", "1.0.0")

    check_solver_result(source, {"foo": "1.0.1", "bar": "1.0.0", "bang": "1.0.0"})
Пример #7
0
def test_rolls_back_leaf_versions_first(source):
    # The latest versions of a and b disagree on c. An older version of either
    # will resolve the problem. This test validates that b, which is farther
    # in the dependency graph from myapp is downgraded first.
    source.root_dep("a", "*")

    source.add("a", "1.0.0", deps={"b": "*"})
    source.add("a", "2.0.0", deps={"b": "*", "c": "2.0.0"})
    source.add("b", "1.0.0")
    source.add("b", "2.0.0", deps={"c": "1.0.0"})
    source.add("c", "1.0.0")
    source.add("c", "2.0.0")

    check_solver_result(source, {"a": "2.0.0", "b": "1.0.0", "c": "2.0.0"})
Пример #8
0
def test_disjoint_constraints(source):
    source.root_dep("foo", "1.0.0")
    source.root_dep("bar", "1.0.0")

    source.add("foo", "1.0.0", deps={"shared": "<=2.0.0"})
    source.add("bar", "1.0.0", deps={"shared": ">3.0.0"})
    source.add("shared", "2.0.0")
    source.add("shared", "4.0.0")

    error = """\
Because bar (1.0.0) depends on shared (>3.0.0)
 and foo (1.0.0) depends on shared (<=2.0.0), bar (1.0.0) is incompatible with foo (1.0.0).
So, because root depends on both foo (1.0.0) and bar (1.0.0), version solving failed."""

    check_solver_result(source, error=error)
Пример #9
0
def test_diamond_dependency_graph(source):
    source.root_dep("a", "*")
    source.root_dep("b", "*")

    source.add("a", "2.0.0", deps={"c": "^1.0.0"})
    source.add("a", "1.0.0")

    source.add("b", "2.0.0", deps={"c": "^3.0.0"})
    source.add("b", "1.0.0", deps={"c": "^2.0.0"})

    source.add("c", "3.0.0")
    source.add("c", "2.0.0")
    source.add("c", "1.0.0")

    check_solver_result(source, {"a": "1.0.0", "b": "2.0.0", "c": "3.0.0"})
Пример #10
0
def test_backjump_to_nearer_unsatisfied_package(source):
    # This ensures it doesn't exhaustively search all versions of b when it's
    # a-2.0.0 whose dependency on c-2.0.0-nonexistent led to the problem. We
    # make sure b has more versions than a so that the solver tries a first
    # since it sorts sibling dependencies by number of versions.
    source.root_dep("a", "*")
    source.root_dep("b", "*")

    source.add("a", "1.0.0", deps={"c": "1.0.0"})
    source.add("a", "2.0.0", deps={"c": "2.0.0-nonexistent"})
    source.add("b", "1.0.0")
    source.add("b", "2.0.0")
    source.add("b", "3.0.0")
    source.add("c", "1.0.0")

    check_solver_result(source, {"a": "1.0.0", "b": "3.0.0", "c": "1.0.0"}, tries=2)
Пример #11
0
def test_backjump_past_failed_package_on_disjoint_constraint(source):
    source.root_dep("a", "*")
    source.root_dep("foo", ">2.0.0")

    source.add("a", "1.0.0", deps={"foo": "*"})  # ok
    source.add(
        "a", "2.0.0", deps={"foo": "<1.0.0"}
    )  # disjoint with myapp's constraint on foo

    source.add("foo", "2.0.0")
    source.add("foo", "2.0.1")
    source.add("foo", "2.0.2")
    source.add("foo", "2.0.3")
    source.add("foo", "2.0.4")

    check_solver_result(source, {"a": "1.0.0", "foo": "2.0.4"})
Пример #12
0
def test_no_version_that_matches_combined_constraints(source):
    source.root_dep("foo", "1.0.0")
    source.root_dep("bar", "1.0.0")

    source.add("foo", "1.0.0", deps={"shared": ">=2.0.0 <3.0.0"})
    source.add("bar", "1.0.0", deps={"shared": ">=2.9.0 <4.0.0"})
    source.add("shared", "2.5.0")
    source.add("shared", "3.5.0")

    error = """\
Because no versions of shared match >=2.9.0,<3.0.0
 and bar (1.0.0) depends on shared (>=2.9.0 <4.0.0), bar (1.0.0) requires shared (>=3.0.0,<4.0.0).
And because foo (1.0.0) depends on shared (>=2.0.0 <3.0.0), bar (1.0.0) is incompatible with foo (1.0.0).
So, because root depends on both foo (1.0.0) and bar (1.0.0), version solving failed."""

    check_solver_result(source, error=error)
Пример #13
0
def test_simple_transitive(source):
    # Only one version of baz, so foo and bar will have to downgrade
    # until they reach it
    source.root_dep("foo", "*")

    source.add("foo", "1.0.0", deps={"bar": "1.0.0"})
    source.add("foo", "2.0.0", deps={"bar": "2.0.0"})
    source.add("foo", "3.0.0", deps={"bar": "3.0.0"})

    source.add("bar", "1.0.0", deps={"baz": "*"})
    source.add("bar", "2.0.0", deps={"baz": "2.0.0"})
    source.add("bar", "3.0.0", deps={"baz": "3.0.0"})

    source.add("baz", "1.0.0")

    check_solver_result(
        source, {"foo": "1.0.0", "bar": "1.0.0", "baz": "1.0.0"}, tries=3
    )
Пример #14
0
def test_no_valid_solution(source):
    source.root_dep("a", "*")
    source.root_dep("b", "*")

    source.add("a", "1.0.0", deps={"b": "1.0.0"})
    source.add("a", "2.0.0", deps={"b": "2.0.0"})

    source.add("b", "1.0.0", deps={"a": "2.0.0"})
    source.add("b", "2.0.0", deps={"a": "1.0.0"})

    error = """\
Because no versions of b match <1.0.0 || >1.0.0,<2.0.0 || >2.0.0
 and b (1.0.0) depends on a (2.0.0), b (<2.0.0 || >2.0.0) requires a (2.0.0).
And because a (2.0.0) depends on b (2.0.0), b is forbidden.
Because b (2.0.0) depends on a (1.0.0) which depends on b (1.0.0), b is forbidden.
Thus, b is forbidden.
So, because root depends on b (*), version solving failed."""

    check_solver_result(source, error=error, tries=2)
Пример #15
0
def test_backjumps_after_partial_satisfier(source):
    # c 2.0.0 is incompatible with y 2.0.0 because it requires x 1.0.0, but that
    # requirement only exists because of both a and b. The solver should be able
    # to deduce c 2.0.0's incompatibility and select c 1.0.0 instead.
    source.root_dep("c", "*")
    source.root_dep("y", "^2.0.0")

    source.add("a", "1.0.0", deps={"x": ">=1.0.0"})
    source.add("b", "1.0.0", deps={"x": "<2.0.0"})

    source.add("c", "1.0.0")
    source.add("c", "2.0.0", deps={"a": "*", "b": "*"})

    source.add("x", "0.0.0")
    source.add("x", "1.0.0", deps={"y": "1.0.0"})
    source.add("x", "2.0.0")

    source.add("y", "1.0.0")
    source.add("y", "2.0.0")

    check_solver_result(source, {"c": "1.0.0", "y": "2.0.0"}, tries=2)
Пример #16
0
def test_simple_dependencies(source):
    source.root_dep("a", "1.0.0")
    source.root_dep("b", "1.0.0")

    source.add("a", "1.0.0", deps={"aa": "1.0.0", "ab": "1.0.0"})
    source.add("b", "1.0.0", deps={"ba": "1.0.0", "bb": "1.0.0"})
    source.add("aa", "1.0.0")
    source.add("ab", "1.0.0")
    source.add("ba", "1.0.0")
    source.add("bb", "1.0.0")

    check_solver_result(
        source,
        {
            "a": "1.0.0",
            "aa": "1.0.0",
            "ab": "1.0.0",
            "b": "1.0.0",
            "ba": "1.0.0",
            "bb": "1.0.0",
        },
    )
Пример #17
0
def test_traverse_into_package_with_fewer_versions_first(source):
    # Dependencies are ordered so that packages with fewer versions are tried
    # first. Here, there are two valid solutions (either a or b must be
    # downgraded once). The chosen one depends on which dep is traversed first.
    # Since b has fewer versions, it will be traversed first, which means a will
    # come later. Since later selections are revised first, a gets downgraded.
    source.root_dep("a", "*")
    source.root_dep("b", "*")

    source.add("a", "1.0.0", deps={"c": "*"})
    source.add("a", "2.0.0", deps={"c": "*"})
    source.add("a", "3.0.0", deps={"c": "*"})
    source.add("a", "4.0.0", deps={"c": "*"})
    source.add("a", "5.0.0", deps={"c": "1.0.0"})
    source.add("b", "1.0.0", deps={"c": "*"})
    source.add("b", "2.0.0", deps={"c": "*"})
    source.add("b", "3.0.0", deps={"c": "*"})
    source.add("b", "4.0.0", deps={"c": "2.0.0"})
    source.add("c", "1.0.0")
    source.add("c", "2.0.0")

    check_solver_result(source, {"a": "4.0.0", "b": "4.0.0", "c": "2.0.0"})