Beispiel #1
0
def test_solid_invocation_with_cm_resource():
    teardown_log = []

    @resource
    def cm_resource(_):
        try:
            yield "foo"
        finally:
            teardown_log.append("collected")

    @solid(required_resource_keys={"cm_resource"})
    def solid_requires_cm_resource(context):
        return context.resources.cm_resource

    # Attempt to use solid context as fxn with cm resource should fail
    context = build_solid_context(resources={"cm_resource": cm_resource})
    with pytest.raises(DagsterInvariantViolationError):
        solid_requires_cm_resource(context)

    del context
    assert teardown_log == ["collected"]

    # Attempt to use solid context as cm with cm resource should succeed
    with build_solid_context(
            resources={"cm_resource": cm_resource}) as context:
        assert solid_requires_cm_resource(context) == "foo"

    assert teardown_log == ["collected", "collected"]
Beispiel #2
0
def test_solid_invocation_with_config():
    @solid(config_schema={"foo": str})
    def solid_requires_config(context):
        assert context.solid_config["foo"] == "bar"
        return 5

    # Ensure that error is raised when attempting to execute and no context is provided
    with pytest.raises(
            DagsterInvalidInvocationError,
            match=
            "Compute function of solid 'solid_requires_config' has context argument, but no "
            "context was provided when invoking.",
    ):
        solid_requires_config()

    # Ensure that error is raised when we attempt to invoke with a None context
    with pytest.raises(
            DagsterInvalidInvocationError,
            match=
            'Solid "solid_requires_config" has required config schema, but no context was '
            "provided.",
    ):
        solid_requires_config(None)

    # Ensure that error is raised when context does not have the required config.
    context = build_solid_context()
    with pytest.raises(
            DagsterInvalidConfigError,
            match="Error in config for solid",
    ):
        solid_requires_config(context)

    # Ensure that error is raised when attempting to execute and no context is provided, even when
    # configured
    with pytest.raises(
            DagsterInvalidInvocationError,
            match=
            "Compute function of solid 'configured_solid' has context argument, but no "
            "context was provided when invoking.",
    ):
        solid_requires_config.configured({"foo": "bar"},
                                         name="configured_solid")()

    # Ensure that if you configure the solid, you can provide a none-context.
    result = solid_requires_config.configured({"foo": "bar"},
                                              name="configured_solid")(None)
    assert result == 5

    result = solid_requires_config(build_solid_context(config={"foo": "bar"}))
    assert result == 5
Beispiel #3
0
def solid_invocation_result(
    solid_def_or_invocation: Union["SolidDefinition", "PendingNodeInvocation"],
    context: Optional["UnboundSolidExecutionContext"],
    *args,
    **kwargs,
) -> Any:
    from dagster.core.execution.context.invocation import build_solid_context
    from dagster.core.definitions.decorators.solid import DecoratedSolidFunction
    from .composition import PendingNodeInvocation

    solid_def = (solid_def_or_invocation.node_def.ensure_solid_def()
                 if isinstance(solid_def_or_invocation, PendingNodeInvocation)
                 else solid_def_or_invocation)

    _check_invocation_requirements(solid_def, context)

    context = (context or build_solid_context()).bind(solid_def_or_invocation)

    input_dict = _resolve_inputs(solid_def, args, kwargs, context)

    compute_fn = solid_def.compute_fn
    if not isinstance(compute_fn, DecoratedSolidFunction):
        check.failed("solid invocation only works with decorated solid fns")

    result = (compute_fn.decorated_fn(context, **input_dict)
              if compute_fn.has_context_arg() else compute_fn.decorated_fn(
                  **input_dict))

    return _type_check_output_wrapper(solid_def, result, context)
Beispiel #4
0
def test_solid_invocation_with_resources():
    @solid(required_resource_keys={"foo"})
    def solid_requires_resources(context):
        assert context.resources.foo == "bar"
        return context.resources.foo

    # Ensure that a check invariant is raise when we attempt to invoke without context
    with pytest.raises(
            DagsterInvalidInvocationError,
            match=
            "Compute function of solid 'solid_requires_resources' has context argument, but no "
            "context was provided when invoking.",
    ):
        solid_requires_resources()

    # Ensure that error is raised when we attempt to invoke with a None context
    with pytest.raises(
            DagsterInvalidInvocationError,
            match=
            'Solid "solid_requires_resources" has required resources, but no context was '
            "provided.",
    ):
        solid_requires_resources(None)

    # Ensure that error is raised when we attempt to invoke with a context without the required
    # resource.
    context = build_solid_context()
    with pytest.raises(
            DagsterInvalidInvocationError,
            match=
            'Solid "solid_requires_resources" requires resource "foo", but no resource '
            "with that key was found on the context.",
    ):
        solid_requires_resources(context)

    context = build_solid_context(resources={"foo": "bar"})
    assert solid_requires_resources(context) == "bar"
Beispiel #5
0
def test_yielded_asset_materialization():
    @solid
    def solid_yields_materialization(_):
        yield AssetMaterialization(asset_key=AssetKey(["fake"]))
        yield Output(5)
        yield AssetMaterialization(asset_key=AssetKey(["fake2"]))

    # Ensure that running without context works, and that asset
    # materializations are just ignored in this case.
    assert solid_yields_materialization(None) == 5

    context = build_solid_context()
    assert solid_yields_materialization(context) == 5
    materializations = context.asset_materializations
    assert len(materializations) == 2
Beispiel #6
0
def test_solid_invocation_no_arg():
    @solid
    def basic_solid():
        return 5

    result = basic_solid()
    assert result == 5

    with pytest.raises(
            DagsterInvalidInvocationError,
            match="Compute function of solid 'basic_solid' has no context "
            "argument, but context was provided when invoking.",
    ):
        basic_solid(build_solid_context())

    with pytest.raises(
            DagsterInvalidInvocationError,
            match=
            "Too many input arguments were provided for solid 'basic_solid'. This may be "
            "because an argument was provided for the context parameter, but no context parameter was "
            "defined for the solid.",
    ):
        basic_solid(None)