def _compare_component(component_spec: ComponentSpec, compare_path: str):
        """Compare an existing specification file to a new specification.

        Args:
            component_spec: A `component.yaml` specification object.
            compare_path: The path of the existing specification file.
        """
        # Write new spec into a temporary file
        temp_spec_file = NamedTemporaryFile(mode="w", delete=False)
        component_spec.save(temp_spec_file.name)

        ignore_image: Callable[
            [str], bool] = lambda line: not line.lstrip().startswith("image:")

        with open(temp_spec_file.name, mode="r") as temp_file:
            with open(compare_path, mode="r") as existing_file:
                temp_lines = list(filter(ignore_image, temp_file.readlines()))
                existing_lines = list(
                    filter(ignore_image, existing_file.readlines()))

                # Cast to list to read through generator
                diff_results = list(
                    difflib.unified_diff(
                        temp_lines,
                        existing_lines,
                        fromfile=temp_spec_file.name,
                        tofile=compare_path,
                    ))

        if len(diff_results) == 0:
            return False
        return "\n".join(diff_results)
    def _write_component(component_spec: ComponentSpec, output_path: str):
        """Write a component YAML specification to a file.

        Args:
            component_spec: A `component.yaml` specification object.
            output_path: The path to write the specification.
        """
        component_spec.save(output_path)
Esempio n. 3
0
    def component_yaml_generator(**kwargs):
        input_specs = []
        input_args = []
        input_kwargs = {}

        serialized_args = {INIT_KEY: {}, METHOD_KEY: {}}

        init_kwargs = {}
        method_kwargs = {}

        for key, value in kwargs.items():
            if key in init_arg_names:
                prefix_key = INIT_KEY
                init_kwargs[key] = value
                signature = init_signature
            else:
                prefix_key = METHOD_KEY
                method_kwargs[key] = value
                signature = method_signature

            # no need to add this argument because it's optional
            # this param is validated against the signature because
            # of init_kwargs, method_kwargs
            if value is None:
                continue

            param_type = signature.parameters[key].annotation
            param_type = resolve_annotation(param_type)
            serializer = get_serializer(param_type)
            if serializer:
                param_type = str
                value = serializer(value)

            # TODO remove PipelineParam check when Metadata Importer component available
            # if we serialize we need to include the argument as input
            # perhaps, another option is to embed in yaml as json serialized list
            component_param_name = component_param_name_to_mb_sdk_param_name.get(
                key, key
            )
            if isinstance(value,
                          kfp.dsl._pipeline_param.PipelineParam) or serializer:
                if is_mb_sdk_resource_noun_type(param_type):
                    metadata_type = map_resource_to_metadata_type(param_type)[1]
                    component_param_type = metadata_type
                else:
                    component_param_type = 'String'

                input_specs.append(
                    InputSpec(
                        name=key,
                        type=component_param_type,
                    )
                )
                input_args.append(f'--{prefix_key}.{component_param_name}')
                if is_mb_sdk_resource_noun_type(param_type):
                    input_args.append(InputUriPlaceholder(input_name=key))
                else:
                    input_args.append(InputValuePlaceholder(input_name=key))

                input_kwargs[key] = value
            else:
                # Serialized arguments must always be strings
                value = str(value)
                serialized_args[prefix_key][component_param_name] = value

        # validate parameters
        if should_serialize_init:
            init_signature.bind(**init_kwargs)
        method_signature.bind(**method_kwargs)

        component_spec = ComponentSpec(
            name=f'{cls_name}-{method_name}',
            inputs=input_specs,
            outputs=output_specs,
            implementation=ContainerImplementation(
                container=ContainerSpec(
                    image=DEFAULT_CONTAINER_IMAGE,
                    command=[
                        'python3',
                        '-m',
                        'google_cloud_pipeline_components.aiplatform.remote_runner',
                        '--cls_name',
                        cls_name,
                        '--method_name',
                        method_name,
                    ],
                    args=make_args(serialized_args) + output_args + input_args,
                )
            )
        )
        component_path = tempfile.mktemp()
        component_spec.save(component_path)

        return components.load_component_from_file(component_path)(
            **input_kwargs
        )