예제 #1
0
async def test_computation_nodes_user_raised_runtime_error_and_logging(caplog):
    def provide_two_values():
        return {"a": 1.2, "b": 2.5}

    def add_two_values(*, c, d):
        raise RuntimeExecutionError("Error in user code!")
        return {"sum": c + d}

    source_node = ComputationNode(
        func=provide_two_values,
        operator_hierarchical_id="SOURCE_ID",
        operator_hierarchical_name="TEST_SOURCE_OPERATOR",
    )
    target_node = ComputationNode(
        func=add_two_values,
        inputs={
            "c": (source_node, "a"),
            "d": (
                source_node,
                # b is not present in the output of source_node
                "b",
            ),
        },
    )

    with caplog.at_level(logging.INFO):
        caplog.clear()
        with pytest.raises(RuntimeExecutionError):
            res = await target_node.result

        assert "User raised" in caplog.text
        assert "UNKNOWN" in caplog.text
        assert "SOURCE_ID" in caplog.text
        assert "TEST_SOURCE_OPERATOR" in caplog.text
예제 #2
0
def parse_component_node(
    component_node: ComponentNode,
    component_dict: Dict[str, ComponentRevision],
    code_module_dict: Dict[str, CodeModule],
    path_prefix: str,
) -> ComputationNode:
    """Parse component node into a ComputationNode

    Includes importing and loading of component function
    """
    try:
        comp_rev = component_dict[component_node.component_uuid]
    except KeyError as e:
        msg = (
            f"The component revision with UUID {component_node.component_uuid} referenced in"
            f"the workflow in operator {str(component_node.name)} is not present in"
            " the provided components"
        )
        logger.info(msg)
        raise ComponentRevisionDoesNotExist(msg) from e

    # Load entrypoint function
    component_func = load_func(comp_rev, code_module_dict)

    return ComputationNode(
        func=component_func,
        component_id=component_node.component_uuid,
        operator_name=component_node.name
        if component_node.name is not None
        else "UNKNOWN",
        inputs=None,  # inputs are added later by the surrounding workflow
        operator_hierarchical_id=path_prefix + ":" + component_node.id,
    )
예제 #3
0
async def test_computation_nodes():
    def provide_two_values():
        return {"a": 1.2, "b": 2.5}

    def add_two_values(*, c, d):
        return {"sum": c + d}

    source_node = ComputationNode(func=provide_two_values)
    target_node = ComputationNode(func=add_two_values,
                                  inputs={
                                      "c": (source_node, "a"),
                                      "d": (source_node, "b")
                                  })

    res = await target_node.result
    assert res["sum"] == 3.7
예제 #4
0
async def test_computation_wrong_input_source():
    def provide_two_values():
        return {"a": 1.2, "b": 2.5}

    def add_two_values(*, c, d):
        return {"sum": c + d}

    source_node = ComputationNode(func=provide_two_values)
    target_node = ComputationNode(
        func=add_two_values,
        inputs={  # here something for d is missing
            "c": (source_node, "a"),
            "wrong": (source_node, "b"),
        },
    )

    with pytest.raises(MissingInputSource):
        res = await target_node.result
예제 #5
0
async def test_computation_cycle_detection():
    def provide_two_values():
        return {"a": 1.2, "b": 2.5}

    def add_two_values(*, c, d):
        return {"sum": c + d}

    source_node = ComputationNode(func=provide_two_values)
    target_node = ComputationNode(
        func=add_two_values,
        inputs={  # here something for d is missing
            "c": (source_node, "a"),
            "d": (source_node, "b"),
        },
    )
    source_node.add_inputs({"some_input": (target_node, "sum")})

    with pytest.raises(CircularDependency):
        res = await target_node.result
예제 #6
0
async def test_computation_nodes_wrong_inputs():
    def provide_two_values():
        return {"a": 1.2, "wrong": 2.5}

    def add_two_values(*, c, d):
        return {"sum": c + d}

    source_node = ComputationNode(func=provide_two_values)
    target_node = ComputationNode(
        func=add_two_values,
        inputs={
            "c": (source_node, "a"),
            "d": (
                source_node,
                # b is not present in the output of source_node
                "b",
            ),
        },
    )

    with pytest.raises(MissingOutputException):
        res = await target_node.result
예제 #7
0
async def test_basic_workflow_execution():
    def provide_two_values():
        return {"a": 1.2, "b": 2.5}

    def add_two_values(*, c, d):
        return {"sum": c + d}

    source_node = ComputationNode(func=provide_two_values)
    target_node = ComputationNode(func=add_two_values,
                                  inputs={
                                      "c": (source_node, "a"),
                                      "d": (source_node, "b")
                                  })

    wf = Workflow(
        sub_nodes=[source_node, target_node],
        input_mappings={},
        output_mappings={"sum_result": (target_node, "sum")},
    )

    res = await wf.result
    assert res["sum_result"] == 3.7
예제 #8
0
async def test_nested_workflow():
    def provide_two_values():
        return {"a": 1.2, "b": 2.5}

    def add_two_values(*, c, d):
        return {"sum": c + d}

    source_node = ComputationNode(func=provide_two_values)

    target_node_in_sub_wf = ComputationNode(func=add_two_values,
                                            inputs={
                                                "c": (source_node, "a"),
                                                "d": (source_node, "b")
                                            })

    sub_wf = Workflow(
        sub_nodes=[target_node_in_sub_wf],
        input_mappings={
            "sub_wf_first_inp": (target_node_in_sub_wf, "c"),
            "sub_wf_second_inp": (target_node_in_sub_wf, "d"),
        },
        output_mappings={"sub_wf_sum_outp": (target_node_in_sub_wf, "sum")},
        inputs={
            "sub_wf_first_inp": (source_node, "a"),
            "sub_wf_second_inp": (source_node, "b"),
        },
    )

    wf = Workflow(
        sub_nodes=[source_node, sub_wf],
        input_mappings={},
        output_mappings={"sum_result": (sub_wf, "sub_wf_sum_outp")},
    )

    res = await wf.result
    assert res["sum_result"] == 3.7
예제 #9
0
async def test_workflow_with_inputs_via_constant_node():
    def add_two_values(*, c, d):
        return {"sum": c + d}

    target_node = ComputationNode(
        func=add_two_values,
        operator_hierarchical_name="sum node",
        operator_hierarchical_id="sum node",
    )

    wf = Workflow(
        sub_nodes=[target_node],
        input_mappings={
            "first": (target_node, "c"),
            "second": (target_node, "d")
        },
        output_mappings={"sum_result": (target_node, "sum")},
        operator_hierarchical_name="Workflow",
        operator_hierarchical_id="Workflow",
    )

    wf.add_constant_providing_node([
        {
            "name": "first",
            "value": 1.9,
            "type": "FLOAT"
        },
        {
            "name": "second",
            "value": 0.1,
            "type": "FLOAT"
        },
    ])

    res = await wf.result
    assert res["sum_result"] == 2.0