Ejemplo n.º 1
0
def _type_checked_event_sequence_for_input(
        step_context: StepExecutionContext, input_name: str,
        input_value: Any) -> Iterator[DagsterEvent]:
    check.inst_param(step_context, "step_context", StepExecutionContext)
    check.str_param(input_name, "input_name")

    step_input = step_context.step.step_input_named(input_name)
    input_def = step_input.source.get_input_def(step_context.pipeline_def)
    dagster_type = input_def.dagster_type
    with user_code_error_boundary(
            DagsterTypeCheckError,
            lambda:
        (f'Error occurred while type-checking input "{input_name}" of solid '
         f'"{str(step_context.step.solid_handle)}", with Python type {type(input_value)} and '
         f"Dagster type {dagster_type.display_name}"),
    ):
        type_check = do_type_check(step_context.for_type(dagster_type),
                                   dagster_type, input_value)

    yield _create_step_input_event(step_context,
                                   input_name,
                                   type_check=type_check,
                                   success=type_check.success)

    if not type_check.success:
        raise DagsterTypeCheckDidNotPass(
            description=(f'Type check failed for step input "{input_name}" - '
                         f'expected type "{dagster_type.display_name}". '
                         f"Description: {type_check.description}."),
            metadata_entries=type_check.metadata_entries,
            dagster_type=dagster_type,
        )
Ejemplo n.º 2
0
def _type_check_output(output_def: "OutputDefinition", output: Any,
                       context: "BoundSolidExecutionContext") -> Any:
    """Validates and performs core type check on a provided output.

    Args:
        output_def (OutputDefinition): The output definition to validate against.
        output (Any): The output to validate.
        context (BoundSolidExecutionContext): Context containing resources to be used for type
            check.
    """
    from ..execution.plan.execute_step import do_type_check

    op_label = context.describe_op()

    if isinstance(output, (Output, DynamicOutput)):
        dagster_type = output_def.dagster_type
        type_check = do_type_check(context.for_type(dagster_type),
                                   dagster_type, output.value)
        if not type_check.success:
            raise DagsterTypeCheckDidNotPass(
                description=
                (f'Type check failed for {op_label} output "{output.output_name}" - '
                 f'expected type "{dagster_type.display_name}". '
                 f"Description: {type_check.description}"),
                metadata_entries=type_check.metadata_entries,
                dagster_type=dagster_type,
            )

        context.observe_output(
            output.output_name,
            output.mapping_key if isinstance(output, DynamicOutput) else None)
        return output
    else:
        dagster_type = output_def.dagster_type
        type_check = do_type_check(context.for_type(dagster_type),
                                   dagster_type, output)
        if not type_check.success:
            raise DagsterTypeCheckDidNotPass(
                description=
                (f'Type check failed for {op_label} output "{output_def.name}" - '
                 f'expected type "{dagster_type.display_name}". '
                 f"Description: {type_check.description}"),
                metadata_entries=type_check.metadata_entries,
                dagster_type=dagster_type,
            )
        return output
Ejemplo n.º 3
0
def _type_check_output(
    step_context: SystemStepExecutionContext,
    step_output_handle: StepOutputHandle,
    output: Any,
    version: Optional[str],
) -> Iterator[DagsterEvent]:
    check.inst_param(step_context, "step_context", SystemStepExecutionContext)
    check.inst_param(output, "output", (Output, DynamicOutput))

    step_output = step_context.step.step_output_named(output.output_name)
    step_output_def = step_context.solid_def.output_def_named(step_output.name)

    dagster_type = step_output_def.dagster_type
    with user_code_error_boundary(
            DagsterTypeCheckError,
            lambda: ('In solid "{handle}" the output "{output_name}" received '
                     "value {output_value} of Python type {output_type} which "
                     "does not pass the typecheck for Dagster type "
                     "{dagster_type_name}. Step {step_key}.").format(
                         handle=str(step_context.step.solid_handle),
                         output_name=output.output_name,
                         output_value=output.value,
                         output_type=type(output.value),
                         dagster_type_name=dagster_type.display_name,
                         step_key=step_context.step.key,
                     ),
    ):
        type_check = _do_type_check(step_context.for_type(dagster_type),
                                    dagster_type, output.value)

    yield DagsterEvent.step_output_event(
        step_context=step_context,
        step_output_data=StepOutputData(
            step_output_handle=step_output_handle,
            type_check_data=TypeCheckData(
                success=type_check.success,
                label=step_output_handle.output_name,
                description=type_check.description if type_check else None,
                metadata_entries=type_check.metadata_entries
                if type_check else [],
            ),
            version=version,
        ),
    )

    if not type_check.success:
        raise DagsterTypeCheckDidNotPass(
            description=
            'Type check failed for step output "{output_name}" - expected type "{dagster_type}".'
            .format(
                output_name=output.output_name,
                dagster_type=dagster_type.display_name,
            ),
            metadata_entries=type_check.metadata_entries,
            dagster_type=dagster_type,
        )
Ejemplo n.º 4
0
def _type_check_output(
    step_context: StepExecutionContext,
    step_output_handle: StepOutputHandle,
    output: Any,
    version: Optional[str],
) -> Iterator[DagsterEvent]:
    check.inst_param(step_context, "step_context", StepExecutionContext)
    check.inst_param(output, "output", (Output, DynamicOutput))

    step_output = step_context.step.step_output_named(output.output_name)
    step_output_def = step_context.solid_def.output_def_named(step_output.name)

    dagster_type = step_output_def.dagster_type
    type_check_context = step_context.for_type(dagster_type)
    op_label = step_context.describe_op()
    output_type = type(output.value)

    with user_code_error_boundary(
            DagsterTypeCheckError,
            lambda:
        (f'Error occurred while type-checking output "{output.output_name}" of {op_label}, with '
         f"Python type {output_type} and Dagster type {dagster_type.display_name}"
         ),
            log_manager=type_check_context.log,
    ):
        type_check = do_type_check(type_check_context, dagster_type,
                                   output.value)

    yield DagsterEvent.step_output_event(
        step_context=step_context,
        step_output_data=StepOutputData(
            step_output_handle=step_output_handle,
            type_check_data=TypeCheckData(
                success=type_check.success,
                label=step_output_handle.output_name,
                description=type_check.description if type_check else None,
                metadata_entries=type_check.metadata_entries
                if type_check else [],
            ),
            version=version,
            metadata_entries=[
                entry for entry in output.metadata_entries
                if isinstance(entry, MetadataEntry)
            ],
        ),
    )

    if not type_check.success:
        raise DagsterTypeCheckDidNotPass(
            description=(
                f'Type check failed for step output "{output.output_name}" - '
                f'expected type "{dagster_type.display_name}". '
                f"Description: {type_check.description}"),
            metadata_entries=type_check.metadata_entries,
            dagster_type=dagster_type,
        )
Ejemplo n.º 5
0
def _type_checked_step_output_event_sequence(step_context, output):
    from dagster.core.execution.api import create_execution_plan

    check.inst_param(step_context, "step_context", SystemStepExecutionContext)
    check.inst_param(output, "output", Output)

    step_output = step_context.step.step_output_named(output.output_name)
    speculative_execution_plan = create_execution_plan(
        step_context.pipeline_def,
        run_config=step_context.run_config,
        mode=step_context.mode_def.name,
    )

    version = resolve_step_output_versions(
        speculative_execution_plan,
        run_config=step_context.run_config,
        mode=step_context.mode_def.name,
    )[StepOutputHandle(step_context.step.key, output.output_name)]
    with user_code_error_boundary(
            DagsterTypeCheckError,
            lambda: ('In solid "{handle}" the output "{output_name}" received '
                     "value {output_value} of Python type {output_type} which "
                     "does not pass the typecheck for Dagster type "
                     "{dagster_type_name}. Step {step_key}.").format(
                         handle=str(step_context.step.solid_handle),
                         output_name=output.output_name,
                         output_value=output.value,
                         output_type=type(output.value),
                         dagster_type_name=step_output.dagster_type.name,
                         step_key=step_context.step.key,
                     ),
    ):
        type_check = _do_type_check(
            step_context.for_type(step_output.dagster_type),
            step_output.dagster_type, output.value)

        yield _create_step_output_event(
            step_context,
            output,
            type_check=type_check,
            success=type_check.success,
            version=version,
        )

        if not type_check.success:
            raise DagsterTypeCheckDidNotPass(
                description=
                "Type check failed for step output {output_name} of type {dagster_type}."
                .format(
                    output_name=output.output_name,
                    dagster_type=step_output.dagster_type.name,
                ),
                metadata_entries=type_check.metadata_entries,
                dagster_type=step_output.dagster_type,
            )
Ejemplo n.º 6
0
def _execute_and_retrieve_outputs(solid_def: "SolidDefinition",
                                  context: "DirectSolidExecutionContext",
                                  input_dict: Dict[str, Any]) -> tuple:
    from dagster.core.execution.plan.execute_step import do_type_check

    output_values = {}
    output_defs = {
        output_def.name: output_def
        for output_def in solid_def.output_defs
    }

    for output in _core_generator(solid_def, context, input_dict):
        if not isinstance(output, AssetMaterialization):
            if output.output_name in output_values:
                raise DagsterInvariantViolationError(
                    f'Solid "{solid_def.name}" returned an output "{output.output_name}" multiple '
                    "times")
            elif output.output_name not in output_defs:
                raise DagsterInvariantViolationError(
                    f'Solid "{solid_def.name}" returned an output "{output.output_name}" that does '
                    f"not exist. The available outputs are {list(output_defs)}"
                )
            else:
                dagster_type = output_defs[output.output_name].dagster_type
                type_check = do_type_check(context.for_type(dagster_type),
                                           dagster_type, output.value)
                if not type_check.success:
                    raise DagsterTypeCheckDidNotPass(
                        description=
                        (f'Type check failed for solid output "{output.output_name}" - '
                         f'expected type "{dagster_type.display_name}". '
                         f"Description: {type_check.description}."),
                        metadata_entries=type_check.metadata_entries,
                        dagster_type=dagster_type,
                    )
                output_values[output.output_name] = output.value
        else:
            context.record_materialization(output)

    # Check to make sure all non-optional outputs were yielded.
    for output_def in solid_def.output_defs:
        if output_def.name not in output_values and output_def.is_required:
            raise DagsterInvariantViolationError(
                f'Solid "{solid_def.name}" did not return an output for non-optional '
                f'output "{output_def.name}"')

    # Explicitly preserve the ordering of output defs
    return tuple([
        output_values[output_def.name] for output_def in solid_def.output_defs
    ])
Ejemplo n.º 7
0
def _resolve_inputs(solid_def: "SolidDefinition", args, kwargs,
                    context: "BoundSolidExecutionContext"):
    from dagster.core.execution.plan.execute_step import do_type_check

    input_defs = solid_def.input_defs

    # Fail early if too many inputs were provided.
    if len(input_defs) < len(args) + len(kwargs):
        raise DagsterInvalidInvocationError(
            f"Too many input arguments were provided for solid '{context.alias}'. This may be because "
            "an argument was provided for the context parameter, but no context parameter was defined "
            "for the solid.")

    input_dict = {
        input_def.name: input_val
        for input_val, input_def in zip(args, input_defs[:len(args)])
    }

    for input_def in input_defs[len(args):]:
        if not input_def.has_default_value and input_def.name not in kwargs:
            raise DagsterInvalidInvocationError(
                f'No value provided for required input "{input_def.name}".')

        input_dict[input_def.name] = (kwargs[input_def.name] if input_def.name
                                      in kwargs else input_def.default_value)

    # Type check inputs
    input_defs_by_name = {
        input_def.name: input_def
        for input_def in input_defs
    }
    for input_name, val in input_dict.items():

        input_def = input_defs_by_name[input_name]
        dagster_type = input_def.dagster_type
        type_check = do_type_check(context.for_type(dagster_type),
                                   dagster_type, val)
        if not type_check.success:
            raise DagsterTypeCheckDidNotPass(
                description=(
                    f'Type check failed for solid input "{input_def.name}" - '
                    f'expected type "{dagster_type.display_name}". '
                    f"Description: {type_check.description}."),
                metadata_entries=type_check.metadata_entries,
                dagster_type=dagster_type,
            )

    return input_dict
Ejemplo n.º 8
0
def _type_check_output(
    step_context: SystemStepExecutionContext,
    step_output_handle: StepOutputHandle,
    output: Any,
    version: Optional[str],
) -> Iterator[DagsterEvent]:
    check.inst_param(step_context, "step_context", SystemStepExecutionContext)
    check.inst_param(output, "output", (Output, DynamicOutput))

    step_output = step_context.step.step_output_named(output.output_name)
    step_output_def = step_context.solid_def.output_def_named(step_output.name)

    dagster_type = step_output_def.dagster_type
    with user_code_error_boundary(
        DagsterTypeCheckError,
        lambda: (
            f'Error occurred while type-checking output "{output.output_name}" of solid '
            f'"{str(step_context.step.solid_handle)}", with Python type {type(output.value)} and '
            f"Dagster type {dagster_type.display_name}"
        ),
    ):
        type_check = _do_type_check(step_context.for_type(dagster_type), dagster_type, output.value)

    yield DagsterEvent.step_output_event(
        step_context=step_context,
        step_output_data=StepOutputData(
            step_output_handle=step_output_handle,
            type_check_data=TypeCheckData(
                success=type_check.success,
                label=step_output_handle.output_name,
                description=type_check.description if type_check else None,
                metadata_entries=type_check.metadata_entries if type_check else [],
            ),
            version=version,
        ),
    )

    if not type_check.success:
        raise DagsterTypeCheckDidNotPass(
            description='Type check failed for step output "{output_name}" - expected type "{dagster_type}".'.format(
                output_name=output.output_name,
                dagster_type=dagster_type.display_name,
            ),
            metadata_entries=type_check.metadata_entries,
            dagster_type=dagster_type,
        )
Ejemplo n.º 9
0
def _type_checked_event_sequence_for_input(
    step_context: StepExecutionContext,
    input_name: str,
    input_value: Any,
) -> Iterator[DagsterEvent]:
    check.inst_param(step_context, "step_context", StepExecutionContext)
    check.str_param(input_name, "input_name")

    step_input = step_context.step.step_input_named(input_name)
    input_def = step_context.solid_def.input_def_named(step_input.name)

    check.invariant(
        input_def.name == input_name,
        f"InputDefinition name does not match, expected {input_name} got {input_def.name}",
    )

    dagster_type = input_def.dagster_type
    type_check_context = step_context.for_type(dagster_type)
    input_type = type(input_value)
    op_label = step_context.describe_op()

    with user_code_error_boundary(
            DagsterTypeCheckError,
            lambda:
        (f'Error occurred while type-checking input "{input_name}" of {op_label}, with Python '
         f"type {input_type} and Dagster type {dagster_type.display_name}"),
            log_manager=type_check_context.log,
    ):
        type_check = do_type_check(type_check_context, dagster_type,
                                   input_value)

    yield _create_step_input_event(step_context,
                                   input_name,
                                   type_check=type_check,
                                   success=type_check.success)

    if not type_check.success:
        raise DagsterTypeCheckDidNotPass(
            description=(f'Type check failed for step input "{input_name}" - '
                         f'expected type "{dagster_type.display_name}". '
                         f"Description: {type_check.description}"),
            metadata_entries=type_check.metadata_entries,
            dagster_type=dagster_type,
        )
Ejemplo n.º 10
0
def _type_checked_event_sequence_for_input(
        step_context: SystemStepExecutionContext, input_name: str,
        input_value: Any) -> Iterator[DagsterEvent]:
    check.inst_param(step_context, "step_context", SystemStepExecutionContext)
    check.str_param(input_name, "input_name")

    step_input = step_context.step.step_input_named(input_name)
    with user_code_error_boundary(
            DagsterTypeCheckError,
            lambda:
        ('In solid "{handle}" the input "{input_name}" received '
         "value {input_value} of Python type {input_type} which "
         "does not pass the typecheck for Dagster type "
         "{dagster_type_name}. Step {step_key}.").format(
             handle=str(step_context.step.solid_handle),
             input_name=input_name,
             input_value=input_value,
             input_type=type(input_value),
             dagster_type_name=step_input.dagster_type.display_name,
             step_key=step_context.step.key,
         ),
    ):
        type_check = _do_type_check(
            step_context.for_type(step_input.dagster_type),
            step_input.dagster_type,
            input_value,
        )

    yield _create_step_input_event(step_context,
                                   input_name,
                                   type_check=type_check,
                                   success=type_check.success)

    if not type_check.success:
        raise DagsterTypeCheckDidNotPass(
            description=
            'Type check failed for step input "{input_name}" - expected type "{dagster_type}".'
            .format(
                input_name=input_name,
                dagster_type=step_input.dagster_type.display_name,
            ),
            metadata_entries=type_check.metadata_entries,
            dagster_type=step_input.dagster_type,
        )
Ejemplo n.º 11
0
def _type_checked_step_output_event_sequence(step_context, output):
    check.inst_param(step_context, "step_context", SystemStepExecutionContext)
    check.inst_param(output, "output", Output)

    step_output = step_context.step.step_output_named(output.output_name)
    version = compute_version_for_step_output(step_context, output)
    with user_code_error_boundary(
            DagsterTypeCheckError,
            lambda: ('In solid "{handle}" the output "{output_name}" received '
                     "value {output_value} of Python type {output_type} which "
                     "does not pass the typecheck for Dagster type "
                     "{dagster_type_name}. Step {step_key}.").format(
                         handle=str(step_context.step.solid_handle),
                         output_name=output.output_name,
                         output_value=output.value,
                         output_type=type(output.value),
                         dagster_type_name=step_output.dagster_type.name,
                         step_key=step_context.step.key,
                     ),
    ):
        type_check = _do_type_check(
            step_context.for_type(step_output.dagster_type),
            step_output.dagster_type, output.value)

        yield _create_step_output_event(
            step_context,
            output,
            type_check=type_check,
            success=type_check.success,
            version=version,
        )

        if not type_check.success:
            raise DagsterTypeCheckDidNotPass(
                description=
                "Type check failed for step output {output_name} of type {dagster_type}."
                .format(
                    output_name=output.output_name,
                    dagster_type=step_output.dagster_type.name,
                ),
                metadata_entries=type_check.metadata_entries,
                dagster_type=step_output.dagster_type,
            )
Ejemplo n.º 12
0
def _type_checked_event_sequence_for_input(step_context, input_name,
                                           input_value):
    check.inst_param(step_context, 'step_context', SystemStepExecutionContext)
    check.str_param(input_name, 'input_name')

    step_input = step_context.step.step_input_named(input_name)
    with user_code_error_boundary(
            DagsterTypeCheckError,
            lambda: ('In solid "{handle}" the input "{input_name}" received '
                     'value {input_value} of Python type {input_type} which '
                     'does not pass the typecheck for Dagster type '
                     '{dagster_type_name}. Step {step_key}.').format(
                         handle=str(step_context.step.solid_handle),
                         input_name=input_name,
                         input_value=input_value,
                         input_type=type(input_value),
                         dagster_type_name=step_input.dagster_type.name,
                         step_key=step_context.step.key,
                     ),
    ):
        type_check = _do_type_check(
            step_context.for_type_check(step_input.dagster_type),
            step_input.dagster_type,
            input_value,
        )

        yield _create_step_input_event(step_context,
                                       input_name,
                                       type_check=type_check,
                                       success=type_check.success)

        if not type_check.success:
            raise DagsterTypeCheckDidNotPass(
                description=
                'Type check failed for step input {input_name} of type {dagster_type}.'
                .format(
                    input_name=input_name,
                    dagster_type=step_input.dagster_type.name,
                ),
                metadata_entries=type_check.metadata_entries,
                dagster_type=step_input.dagster_type,
            )
Ejemplo n.º 13
0
def _resolve_inputs(solid_def: "SolidDefinition", args, kwargs,
                    context: "BoundSolidExecutionContext"):
    from dagster.core.execution.plan.execute_step import do_type_check

    nothing_input_defs = [
        input_def for input_def in solid_def.input_defs
        if input_def.dagster_type.is_nothing
    ]

    # Check kwargs for nothing inputs, and error if someone provided one.
    for input_def in nothing_input_defs:
        if input_def.name in kwargs:
            node_label = solid_def.node_type_str  # string "solid" for solids, "op" for ops

            raise DagsterInvalidInvocationError(
                f"Attempted to provide value for nothing input '{input_def.name}'. Nothing "
                f"dependencies are ignored when directly invoking {node_label}s."
            )

    # Discard nothing dependencies - we ignore them during invocation.
    input_defs_by_name = {
        input_def.name: input_def
        for input_def in solid_def.input_defs
        if not input_def.dagster_type.is_nothing
    }

    # Fail early if too many inputs were provided.
    if len(input_defs_by_name) < len(args) + len(kwargs):
        if len(nothing_input_defs) > 0:
            suggestion = (
                "This may be because you attempted to provide a value for a nothing "
                "dependency. Nothing dependencies are ignored when directly invoking solids."
            )
        else:
            suggestion = (
                "This may be because an argument was provided for the context parameter, "
                "but no context parameter was defined for the solid.")

        node_label = solid_def.node_type_str
        raise DagsterInvalidInvocationError(
            f"Too many input arguments were provided for {node_label} '{context.alias}'. {suggestion}"
        )

    positional_inputs = cast("DecoratedSolidFunction",
                             solid_def.compute_fn).positional_inputs()

    input_dict = {}

    for position, value in enumerate(args):
        input_dict[positional_inputs[position]] = value

    for positional_input in positional_inputs[len(args):]:
        input_def = input_defs_by_name[positional_input]

        if not input_def.has_default_value and positional_input not in kwargs:
            raise DagsterInvalidInvocationError(
                f'No value provided for required input "{positional_input}".')

        input_dict[positional_input] = (kwargs[positional_input]
                                        if positional_input in kwargs else
                                        input_def.default_value)

    # Type check inputs
    op_label = context.describe_op()

    for input_name, val in input_dict.items():

        input_def = input_defs_by_name[input_name]
        dagster_type = input_def.dagster_type
        type_check = do_type_check(context.for_type(dagster_type),
                                   dagster_type, val)
        if not type_check.success:
            raise DagsterTypeCheckDidNotPass(
                description=
                (f'Type check failed for {op_label} input "{input_def.name}" - '
                 f'expected type "{dagster_type.display_name}". '
                 f"Description: {type_check.description}"),
                metadata_entries=type_check.metadata_entries,
                dagster_type=dagster_type,
            )

    return input_dict