def sample_build_commands():
    retval = networkx.DiGraph()
    node1 = build_tree.DependencyNode(packages=["package1a", "package1b"],
                                      build_command=build_tree.BuildCommand(
                                          "recipe1",
                                          "repo1", ["package1a", "package1b"],
                                          python="2.6",
                                          build_type="cuda",
                                          mpi_type="openmpi",
                                          cudatoolkit="10.2"))
    node2 = build_tree.DependencyNode(packages=["package2a"],
                                      build_command=build_tree.BuildCommand(
                                          "recipe2",
                                          "repo2", ["package2a"],
                                          python="2.6",
                                          build_type="cpu",
                                          mpi_type="openmpi",
                                          cudatoolkit="10.2"))
    node3 = build_tree.DependencyNode(packages=["package3a", "package3b"],
                                      build_command=build_tree.BuildCommand(
                                          "recipe3", "repo3",
                                          ["package3a", "package3b"]))

    retval.add_node(node1)
    retval.add_node(node2)
    retval.add_node(node3)
    retval.add_edge(node1, node2)
    retval.add_edge(node1, node3)
    retval.add_edge(node3, node2)

    return retval
Esempio n. 2
0
def test_get_installable_package_with_no_duplicates():
    '''
    This test verifies that get_installable_package doesn't return duplicate dependencies.
    '''
    build_commands = graph.OpenCEGraph()
    node1 = build_tree.DependencyNode(
        packages=["package1a"],
        build_command=build_tree.BuildCommand(
            "recipe1",
            "repo1", ["package1a"],
            runtime_package=False,
            output_files=["package1a-1.0-py37_4.tar.bz2"],
            run_dependencies=["python 3.7", "pack1a==1.0"]))
    node2 = build_tree.DependencyNode(
        packages=["package2a"],
        build_command=build_tree.BuildCommand(
            "recipe2",
            "repo2", ["package2a"],
            output_files=["package2a-2.0-py37.tar.bz2"],
            run_dependencies=[
                "python 3.7", "pack1 ==1.0", "pack1", "pack2 <=2.0",
                "pack2 2.0", "pack3   3.0.*", "pack2"
            ]))
    node3 = build_tree.DependencyNode(packages=["package3a", "package3b"],
                                      build_command=build_tree.BuildCommand(
                                          "recipe3",
                                          "repo3", ["package3a", "package3b"],
                                          output_files=[
                                              "package3a-1.5-cpu.tar.bz2",
                                              "package3b-1.5-cpu.tar.bz2"
                                          ],
                                          run_dependencies=[
                                              "pack1 >=1.0", "pack1",
                                              "pack4 <=2.0", "pack2 2.0",
                                              "pack3   3.0.*", "pack4"
                                          ]))

    build_commands.add_node(node1)
    build_commands.add_node(node2)
    build_commands.add_node(node3)

    external_deps = ["external_pac1    1.2"]
    for dep in external_deps:
        build_commands.add_node(build_tree.DependencyNode({dep}))
    packages = build_tree.get_installable_packages(build_commands,
                                                   external_deps)
    assert not "package1a" in str(packages)
    assert not "pack1a" in str(packages)

    print("Packages: ", packages)

    expected_packages = [
        "package2a 2.0.* py37", "python 3.7.*", "pack1 ==1.0.*", "pack2 <=2.0",
        "pack3 3.0.*", "package3a 1.5.* cpu", "package3b 1.5.* cpu",
        "pack4 <=2.0", "external_pac1 1.2.*"
    ]
    assert Counter(packages) == Counter(expected_packages)
def test_build_tree_cycle_fail():
    '''
    Tests that a cycle is detected in a build_tree.
    '''
    cycle_build_commands = networkx.DiGraph()
    node1 = build_tree.DependencyNode(packages=["package1a", "package1b"],
                                      build_command=build_tree.BuildCommand(
                                          "recipe1",
                                          "repo1", ["package1a", "package1b"],
                                          python="2.6",
                                          build_type="cuda",
                                          mpi_type="openmpi",
                                          cudatoolkit="10.2"))
    node2 = build_tree.DependencyNode(packages=["package2a"],
                                      build_command=build_tree.BuildCommand(
                                          "recipe2",
                                          "repo2", ["package2a"],
                                          python="2.6",
                                          build_type="cpu",
                                          mpi_type="openmpi",
                                          cudatoolkit="10.2"))
    node3 = build_tree.DependencyNode(packages=["package3a", "package3b"],
                                      build_command=build_tree.BuildCommand(
                                          "recipe3", "repo3",
                                          ["package3a", "package3b"]))

    cycle_build_commands.add_node(node1)
    cycle_build_commands.add_node(node2)
    cycle_build_commands.add_node(node3)
    cycle_build_commands.add_edge(node1, node2)
    cycle_build_commands.add_edge(node1, node3)
    cycle_build_commands.add_edge(node2, node1)
    cycle_build_commands.add_edge(node3, node2)

    mock_build_tree = TestBuildTree([], "3.6", "cpu", "openmpi", "10.2")
    mock_build_tree._tree = sample_build_commands()

    mock_build_tree._detect_cycle()  #Make sure there isn't a false positive.

    mock_build_tree._tree = cycle_build_commands

    with pytest.raises(OpenCEError) as exc:
        mock_build_tree._detect_cycle()

    assert "Build dependencies should form a Directed Acyclic Graph." in str(
        exc.value)
    assert any([
        "recipe1 -> recipe2 -> recipe1" in str(exc.value),
        "recipe2 -> recipe1 -> recipe2" in str(exc.value),
        "recipe1 -> recipe3 -> recipe2 -> recipe1" in str(exc.value),
        "recipe2 -> recipe1 -> recipe3 -> recipe2" in str(exc.value),
        "recipe3 -> recipe2 -> recipe1 -> recipe2" in str(exc.value)
    ])
Esempio n. 4
0
def test_search_package_priority(mocker):
    '''
    Test remote package priority.
    '''
    mock_build_tree = TestBuildTree([],
                                    "3.6",
                                    "cpu",
                                    "openmpi",
                                    "10.2",
                                    channels=["defaults"])
    dep_graph = sample_build_commands()

    external_node = build_tree.DependencyNode(packages=["external_package"])
    nodes = list(dep_graph.nodes())
    parent_node = nodes[0]
    #defaults is the highest priority conda channel, a package should only come from conda_forge if there are none in defaults, regardless of version.
    parent_node.build_command.channels = ["defaults", "conda_forge"]
    dep_graph.add_node(external_node)
    dep_graph.add_edge(parent_node, external_node)

    def mocked_search(*arguments, **_):
        search_results = {
            ("external_package", "conda_forge"):
            make_search_result(package_name="external_package",
                               package_version="2.0",
                               deps=["conda_forge_dep"]),
            ("external_package", "defaults"):
            make_search_result(package_name="external_package",
                               package_version="1.0",
                               deps=["defaults_dep"]),
            ("defaults_dep", "conda_forge"):
            make_search_result(package_name="defaults_dep",
                               deps=["defaults_dep_conda_forge_dep"]),
            ("defaults_dep", "defaults"):
            empty_search_result("defaults_dep")
        }
        package = arguments[1][1]
        channel = arguments[1][4] if "-c" in arguments[1] else ""
        if (package, channel) in search_results:
            return search_results[(package, channel)]
        else:
            return make_search_result(package_name=package)

    mocker.patch('conda.cli.python_api.run_command', side_effect=mocked_search)

    dep_graph = mock_build_tree._create_remote_deps(dep_graph)

    assert build_tree.DependencyNode(packages={"defaults_dep"}) in list(dep_graph.successors(external_node)), \
           "defaults_dep should be found, even though the conda_forge package is a newer version"

    assert build_tree.DependencyNode(packages={"defaults_dep_conda_forge_dep"}) in list(dep_graph.successors(build_tree.DependencyNode(packages={"defaults_dep"}))), \
           "There is no defaults_dep package in the defaults channel, so conda_forge should be used."
Esempio n. 5
0
def sample_build_commands():
    retval = graph.OpenCEGraph()
    node1 = build_tree.DependencyNode(packages=["package1a", "package1b"],
                                      build_command=build_tree.BuildCommand(
                                          "recipe1",
                                          "repo1", ["package1a", "package1b"],
                                          python="2.6",
                                          build_type="cuda",
                                          mpi_type="openmpi",
                                          cudatoolkit="10.2",
                                          output_files=[
                                              "package1a-py26-cuda-openmpi",
                                              "package1b-py26-cuda-openmpi"
                                          ]))
    node2 = build_tree.DependencyNode(packages=["package2a"],
                                      build_command=build_tree.BuildCommand(
                                          "recipe2",
                                          "repo2", ["package2a"],
                                          python="2.6",
                                          build_type="cpu",
                                          mpi_type="openmpi",
                                          cudatoolkit="10.2",
                                          output_files=["package2a-noarch"]))
    node3 = build_tree.DependencyNode(packages=["package3a", "package3b"],
                                      build_command=build_tree.BuildCommand(
                                          "recipe3",
                                          "repo3", ["package3a", "package3b"],
                                          output_files=[
                                              "package3a-py26-cpu-openmpi",
                                              "package3b-py26-cpu-openmpi"
                                          ]))
    # This node is a duplicate and nothing should happen when it's added.
    node4 = build_tree.DependencyNode(packages=["package2a"],
                                      build_command=build_tree.BuildCommand(
                                          "recipe2",
                                          "repo2", ["package2a"],
                                          python="3.6",
                                          build_type="cuda",
                                          mpi_type="system",
                                          cudatoolkit="10.2",
                                          output_files=["package2a-noarch"]))

    retval.add_node(node1)
    retval.add_node(node2)
    retval.add_node(node3)
    retval.add_node(node4)
    retval.add_edge(node1, node4)
    retval.add_edge(node1, node3)
    retval.add_edge(node3, node2)

    return retval
Esempio n. 6
0
def test_search_channels(mocker):
    '''
    Test that recipe specific channels are used for remote dependency discovery.
    '''
    mock_build_tree = TestBuildTree([],
                                    "3.6",
                                    "cpu",
                                    "openmpi",
                                    "10.2",
                                    channels=["defaults"])
    dep_graph = sample_build_commands()

    external_node = build_tree.DependencyNode(packages=["external_package"])
    nodes = list(dep_graph.nodes())
    parent_node = nodes[0]
    parent_node.build_command.channels = ["conda_forge"]
    dep_graph.add_node(external_node)
    dep_graph.add_edge(parent_node, external_node)

    def validate_channels(channels, package):
        assert "defaults" in channels
        if package == "external_package":
            assert "conda_forge" in channels, \
                   "The conda_forge channel should come from the parent node."

            assert channels.index("conda_forge") < channels.index("defaults"), \
                   "The conda_forge channel should be higher priority, since it is from a parent node and the defaults channel is from the env file."
        return {'dependencies': []}

    mocker.patch('open_ce.conda_utils.get_latest_package_info',
                 side_effect=validate_channels)

    mock_build_tree._create_remote_deps(dep_graph)
Esempio n. 7
0
def test_get_installable_package_for_non_runtime_package():
    '''
    Tests that `get_installable_package` doesn't return the packages marked as
    non-runtime i.e. build command with runtime_package=False.
    '''
    build_commands = graph.OpenCEGraph()
    node1 = build_tree.DependencyNode(
        packages=["package1a"],
        build_command=build_tree.BuildCommand(
            "recipe1",
            "repo1", ["package1a"],
            runtime_package=False,
            python="2.6",
            build_type="cuda",
            mpi_type="openmpi",
            cudatoolkit="10.2",
            output_files=["package1a-py26-cuda-openmpi"]))
    node2 = build_tree.DependencyNode(
        packages=["package2a"],
        build_command=build_tree.BuildCommand(
            "recipe2",
            "repo2", ["package2a"],
            python="2.6",
            build_type="cpu",
            mpi_type="openmpi",
            cudatoolkit="10.2",
            output_files=["package2a-py26-cuda-openmpi"]))

    build_commands.add_node(node1)
    build_commands.add_node(node2)
    build_commands.add_edge(node1, node2)

    external_deps = [
        "external_pac1    1.2", "external_pack2", "external_pack3=1.2.3"
    ]
    for dep in external_deps:
        build_commands.add_node(build_tree.DependencyNode({dep}))
    packages = build_tree.get_installable_packages(build_commands,
                                                   external_deps)
    assert not "package1a" in packages
Esempio n. 8
0
def test_dag_cleanup():
    '''
    Test that external packages are removed during cleanup.
    '''
    mock_build_tree = TestBuildTree([], "3.6", "cpu", "openmpi", "10.2")
    mock_build_tree._tree = sample_build_commands()

    external_node = build_tree.DependencyNode(packages=["external_package"])
    nodes = list(mock_build_tree._tree.nodes())
    parent_node = nodes[0]
    child_node = nodes[1]
    mock_build_tree._tree.add_node(external_node)
    mock_build_tree._tree.add_edge(parent_node, external_node)
    mock_build_tree._tree.add_edge(external_node, child_node)

    mock_build_tree.remove_external_deps_from_dag()

    assert not external_node in mock_build_tree._tree.nodes()
    assert child_node in mock_build_tree._tree.successors(parent_node)
    assert parent_node in mock_build_tree._tree.predecessors(child_node)
Esempio n. 9
0
def sample_build_commands():
    retval = networkx.DiGraph()
    node1 = build_tree.DependencyNode(
        packages=["package1a", "package1b"],
        build_command=build_tree.BuildCommand(
            "recipe1",
            "repo1", ["package1a", "package1b"],
            python="3.6",
            build_type="cuda",
            mpi_type="openmpi",
            cudatoolkit="10.2",
            output_files=[
                "package1a-1.0-py36_cuda10.2.tar.bz2",
                "package1b-1.0-py36_cuda10.2.tar.bz2"
            ],
            run_dependencies=[
                "python     >=3.6", "pack1    1.0", "pack2   >=2.0", "pack3 9b"
            ]))
    node2 = build_tree.DependencyNode(
        packages=["package2a"],
        build_command=build_tree.BuildCommand(
            "recipe2",
            "repo2", ["package2a"],
            python="3.6",
            build_type="cpu",
            mpi_type="system",
            cudatoolkit="10.2",
            output_files=["package2a-1.0-py36_cuda10.2.tar.bz2"],
            run_dependencies=[
                "python ==3.6", "pack1 >=1.0", "pack2   ==2.0",
                "pack3 3.3 build"
            ]))
    node3 = build_tree.DependencyNode(
        packages=["package3a", "package3b"],
        build_command=build_tree.BuildCommand(
            "recipe3",
            "repo3", ["package3a", "package3b"],
            python="3.7",
            build_type="cpu",
            mpi_type="openmpi",
            cudatoolkit="10.2",
            output_files=[
                "package3a-1.0-py37_cuda10.2.tar.bz2",
                "package3b-1.0-py37_cuda10.2.tar.bz2"
            ],
            run_dependencies=[
                "python 3.7", "pack1==1.0", "pack2 <=2.0", "pack3   3.0.*",
                "pack4=1.15.0=py38h6ffa863_0"
            ]))
    node4 = build_tree.DependencyNode(
        packages=["package4a", "package4b"],
        build_command=build_tree.BuildCommand(
            "recipe4",
            "repo4", ["package4a", "package4b"],
            python="3.7",
            build_type="cuda",
            mpi_type="system",
            cudatoolkit="10.2",
            output_files=[
                "package4a-1.0-py37_cuda.tar.bz2",
                "package4b-1.0-py37_cuda.tar.bz2"
            ],
            run_dependencies=["pack1==1.0", "pack2 <=2.0",
                              "pack3-suffix 3.0"]))

    retval.add_node(node1)
    retval.add_node(node2)
    retval.add_node(node3)
    retval.add_node(node4)

    for dep in external_deps:
        retval.add_node(build_tree.DependencyNode({dep}))

    return retval