Esempio n. 1
0
def _create_task_spec_from_component_and_arguments(
        component_spec: structures.ComponentSpec,
        arguments: Mapping[str, Any],
        component_ref: structures.ComponentReference = None,
        **kwargs) -> structures.TaskSpec:
    """Constructs a TaskSpec object from component reference and arguments.

    The function also checks the arguments types and serializes them.
  """
    if component_ref is None:
        component_ref = structures.ComponentReference(spec=component_spec)
    else:
        component_ref = copy.copy(component_ref)
        component_ref.spec = component_spec

    # Not checking for missing or extra arguments since the dynamic factory function checks that
    task_arguments = {}
    for input_name, argument_value in arguments.items():
        input_type = component_spec._inputs_dict[input_name].type

        if isinstance(
                argument_value,
            (structures.GraphInputArgument, structures.TaskOutputArgument)):
            # argument_value is a reference
            if isinstance(argument_value, structures.GraphInputArgument):
                reference_type = argument_value.graph_input.type
            elif isinstance(argument_value, structures.TaskOutputArgument):
                reference_type = argument_value.task_output.type
            else:
                reference_type = None

            if reference_type and input_type and reference_type != input_type:
                _react_to_incompatible_reference_type(input_type,
                                                      reference_type,
                                                      input_name)

            task_arguments[input_name] = argument_value
        else:
            # argument_value is a constant value
            serialized_argument_value = serialize_value(
                argument_value, input_type)
            task_arguments[input_name] = serialized_argument_value

    task = structures.TaskSpec(
        component_ref=component_ref,
        arguments=task_arguments,
    )
    task._init_outputs()

    return task
Esempio n. 2
0
    def test_create_pipeline_task_valid(self):
        expected_component_spec = structures.ComponentSpec(
            name='component1',
            implementation=structures.Implementation(
                container=structures.ContainerSpec(
                    image='alpine',
                    commands=['sh', '-c', 'echo "$0" >> "$1"'],
                    arguments=[
                        structures.InputValuePlaceholder(input_name='input1'),
                        structures.OutputPathPlaceholder(
                            output_name='output1'),
                    ],
                )),
            inputs={
                'input1': structures.InputSpec(type='String'),
            },
            outputs={
                'output1': structures.OutputSpec(type='Artifact'),
            },
        )
        expected_task_spec = structures.TaskSpec(
            name='component1',
            inputs={'input1': 'value'},
            dependent_tasks=[],
            component_ref='component1',
        )
        expected_container_spec = structures.ContainerSpec(
            image='alpine',
            commands=['sh', '-c', 'echo "$0" >> "$1"'],
            arguments=[
                "{{$.inputs.parameters['input1']}}",
                "{{$.outputs.artifacts['output1'].path}}",
            ],
        )

        task = pipeline_task.PipelineTask(
            component_spec=structures.ComponentSpec.load_from_component_yaml(
                V2_YAML),
            arguments={'input1': 'value'},
        )
        self.assertEqual(task.task_spec, expected_task_spec)
        self.assertEqual(task.component_spec, expected_component_spec)
        self.assertEqual(task.container_spec, expected_container_spec)
Esempio n. 3
0
    def __init__(
        self,
        component_spec: structures.ComponentSpec,
        arguments: Mapping[str, Any],
    ):
        """Initilizes a PipelineTask instance.

        Args:
            component_spec: The component definition.
            arguments: The dictionary of component arguments.
        """
        arguments = arguments or {}

        for input_name, argument_value in arguments.items():

            if input_name not in component_spec.inputs:
                raise ValueError(
                    f'Component "{component_spec.name}" got an unexpected input:'
                    f' {input_name}.')

            input_type = component_spec.inputs[input_name].type
            argument_type = None

            if isinstance(argument_value, pipeline_channel.PipelineChannel):
                argument_type = argument_value.channel_type
            elif isinstance(argument_value, str):
                argument_type = 'String'
            elif isinstance(argument_value, bool):
                argument_type = 'Boolean'
            elif isinstance(argument_value, int):
                argument_type = 'Integer'
            elif isinstance(argument_value, float):
                argument_type = 'Float'
            elif isinstance(argument_value, dict):
                argument_type = 'Dict'
            elif isinstance(argument_value, list):
                argument_type = 'List'
            else:
                raise ValueError(
                    'Input argument supports only the following types: '
                    'str, int, float, bool, dict, and list. Got: '
                    f'"{argument_value}" of type "{type(argument_value)}".')

            type_utils.verify_type_compatibility(
                given_type=argument_type,
                expected_type=input_type,
                error_message_prefix=(
                    'Incompatible argument passed to the input '
                    f'"{input_name}" of component "{component_spec.name}": '),
            )

        self.component_spec = component_spec

        self.task_spec = structures.TaskSpec(
            name=self.register_task_handler(),
            inputs={
                input_name: value for input_name, value in arguments.items()
            },
            dependent_tasks=[],
            component_ref=component_spec.name,
            enable_caching=True,
        )

        self.importer_spec = None
        self.container_spec = None

        if component_spec.implementation.container is not None:
            self.container_spec = self._resolve_command_line_and_arguments(
                component_spec=component_spec,
                arguments=arguments,
            )
        elif component_spec.implementation.importer is not None:
            self.importer_spec = component_spec.implementation.importer
            self.importer_spec.artifact_uri = arguments['uri']

        self._outputs = {
            output_name: pipeline_channel.create_pipeline_channel(
                name=output_name,
                channel_type=output_spec.type,
                task_name=self.task_spec.name,
            ) for output_name, output_spec in (
                component_spec.outputs or {}).items()
        }

        self._inputs = arguments

        self._channel_inputs = [
            value for _, value in arguments.items()
            if isinstance(value, pipeline_channel.PipelineChannel)
        ] + pipeline_channel.extract_pipeline_channels_from_any([
            value for _, value in arguments.items()
            if not isinstance(value, pipeline_channel.PipelineChannel)
        ])