Beispiel #1
0
 def parse_param(k, v) -> V1Param:
     if not isinstance(v, V1Param):
         v = V1Param.read(v, config_type=".yaml")
     if v and k in contexts_by_keys:
         v.context_only = True
         if v.to_init is None:
             v.to_init = contexts_by_keys[k].to_init
         if v.connection is None:
             v.connection = contexts_by_keys[k].connection
     return v
Beispiel #2
0
 def parse_param(v) -> V1Param:
     if isinstance(v, V1Param):
         return v
     return V1Param.read(v, config_type=".yaml")
Beispiel #3
0
def validate_params(
    params: Dict[str, Union[Dict, V1Param]],
    inputs: List[V1IO],
    outputs: List[V1IO],
    parallel: V1Parallel = None,
    context: Dict = None,
    is_template: bool = True,
    check_runs: bool = False,
    extra_info: str = None,
) -> List[ParamSpec]:
    """
    Validates Params given inputs, and an optional context.

    Params can be:
     * plain values: we check them against the inputs types
     * job/experiment references: We postpone to server side validation.
     * ops reference: in that case a context must be provided to validate that the reference exists.
        and types are correct.
    """
    if requires_params(inputs, outputs):
        if not is_template and not params and not parallel:
            message = ("The Polyaxonfile has non optional inputs/outputs, "
                       "you need to pass valid params.")
            if extra_info:
                message += " Please check: {}".format(extra_info)

            raise ValidationError(message)
    elif not accepts_params(inputs, outputs) and params:
        message = "Received unexpected params `{}`.".format(params)
        if extra_info:
            message += " Please check: {}".format(extra_info)
        raise ValidationError(message)

    def parse_param(v) -> V1Param:
        if isinstance(v, V1Param):
            return v
        return V1Param.read(v, config_type=".yaml")

    def validate_parallel(io: V1IO) -> bool:
        if isinstance(parallel, V1Mapping):
            return parallel.has_key(io.name)
        elif io.name in parallel.params:
            parallel.params[io.name].validate_io(io)
            return True
        return False

    params = params or {}
    params = {k: parse_param(params[k]) for k in params}
    parallel = parallel or {}
    inputs = inputs or []
    outputs = outputs or []

    processed_params = []
    validated_params = []

    for inp in inputs:
        if inp.name in params:
            param_value = params[inp.name]
            param_spec = param_value.get_spec(
                name=inp.name,
                iotype=inp.iotype,
                is_flag=inp.is_flag,
                is_list=inp.is_list,
            )
            if param_spec.param.is_ref:
                param_spec.validate_ref(context, is_template, check_runs)
            else:  # Plain value
                inp.validate_value(param_value.value)
            validated_params.append(param_spec)
            processed_params.append(inp.name)
        elif parallel and validate_parallel(inp):
            pass
        elif not inp.is_optional and not is_template:
            message = "Input {} is required, no param was passed.".format(
                inp.name)
            if extra_info:
                message += " Please check: {}".format(extra_info)
            raise ValidationError(message)
        else:
            validated_params.append(
                ParamSpec(
                    name=inp.name,
                    param=V1Param(value=inp.value),
                    iotype=inp.iotype,
                    is_flag=inp.is_flag,
                    is_list=inp.is_list,
                ))

    for out in outputs:
        if out.name in params:
            param_value = params[out.name]
            param_spec = param_value.get_spec(
                name=out.name,
                iotype=out.iotype,
                is_flag=out.is_flag,
                is_list=out.is_list,
            )
            validated_params.append(param_spec)
            if param_spec.param.is_ref:
                param_spec.validate_ref(None,
                                        is_template=False,
                                        check_runs=check_runs)
            else:  # Plain value
                out.validate_value(param_value.value)
            validated_params.append(param_spec)
            processed_params.append(out.name)
        # No validation for outputs we assume that the op might populate a context or send a metric
        else:
            validated_params.append(
                ParamSpec(
                    name=out.name,
                    param=V1Param(value=out.value),
                    iotype=out.iotype,
                    is_flag=out.is_flag,
                    is_list=out.is_list,
                ))
    extra_params = set(params.keys()) - set(processed_params)
    if extra_params:
        message = "Received unexpected params `{}`.".format(extra_params)
        if extra_info:
            message += " Please check: {}".format(extra_info)
        raise ValidationError(message)

    return validated_params
Beispiel #4
0
def validate_params(
    params: Dict[str, Union[Dict, V1Param]],
    inputs: List[V1IO],
    outputs: List[V1IO],
    contexts: List[V1IO] = None,
    matrix: V1Matrix = None,
    context: Dict = None,
    is_template: bool = True,
    check_runs: bool = False,
    extra_info: str = None,
    parse_values: bool = False,
) -> List[ParamSpec]:
    """
    Validates Params given inputs, and an optional context.

    Params can be:
     * plain values: we check them against the inputs types
     * job/experiment references: We postpone to server side validation.
     * ops reference: in that case a context must be provided to validate that the reference exists.
        and types are correct.
    """
    contexts_by_keys = {k.name: k for k in contexts or []}

    def parse_param(k, v) -> V1Param:
        if not isinstance(v, V1Param):
            v = V1Param.read(v, config_type=".yaml")
        if v and k in contexts_by_keys:
            v.context_only = True
            if v.to_init is None:
                v.to_init = contexts_by_keys[k].to_init
            if v.connection is None:
                v.connection = contexts_by_keys[k].connection
        return v

    def validate_matrix(io: V1IO) -> bool:
        if isinstance(matrix, V1Mapping):
            return matrix.has_key(io.name)  # noqa
        elif io.name in matrix.params:
            matrix.params[io.name].validate_io(io)
            return True
        elif hasattr(matrix, "resource") and io.name == matrix.resource.name:
            return True
        return False

    params = params or {}
    params = {k: parse_param(k, params[k]) for k in params}

    if requires_params(inputs, outputs):
        if not is_template and not params and not matrix:
            message = ("The Polyaxonfile has non optional inputs/outputs, "
                       "you need to pass valid params")
            if extra_info:
                message += " Please check: {}".format(extra_info)

            raise ValidationError(message)
    elif not accepts_params(inputs, outputs) and params:
        extra_params = set(
            params.keys()) - {p
                              for p in params if params[p].context_only}
        if extra_params:
            message = "Received unexpected params `{}`".format(extra_params)
            if extra_info:
                message += " Please check: {}".format(extra_info)
            raise ValidationError(message)

    matrix = matrix or {}
    inputs = inputs or []
    outputs = outputs or []

    processed_params = []
    validated_params = []

    for inp in inputs:
        if inp.name in params:
            param_value = params[inp.name]
            param_spec = param_value.get_spec(
                name=inp.name,
                iotype=inp.iotype,
                is_flag=inp.is_flag,
                is_list=inp.is_list,
                is_context=False,
                arg_format=inp.arg_format,
            )
            if param_spec.param.is_ref:
                param_spec.validate_ref(context, is_template, check_runs)
            else:  # Plain value
                parsed_value = inp.validate_value(param_value.value)
                if parse_values:
                    param_spec.param.value = parsed_value
                    if not param_spec.param.connection and param_value.connection:
                        param_spec.param.connection = inp.connection
                    if not param_spec.param.to_init and param_value.to_init:
                        param_spec.param.to_init = inp.to_init
            validated_params.append(param_spec)
            if not param_spec.param.context_only:
                processed_params.append(inp.name)
        elif matrix and validate_matrix(inp):
            pass
        elif not inp.is_optional and not is_template:
            message = "Input {} is required, no param was passed.".format(
                inp.name)
            if extra_info:
                message += " Please check: {}".format(extra_info)
            raise ValidationError(message)
        else:
            validated_params.append(
                ParamSpec(
                    name=inp.name,
                    param=V1Param(value=inp.value,
                                  connection=inp.connection,
                                  to_init=inp.to_init),
                    iotype=inp.iotype,
                    is_flag=inp.is_flag,
                    is_list=inp.is_list,
                    is_context=False,
                    arg_format=inp.arg_format,
                ))

    for out in outputs:
        if out.name in params:
            param_value = params[out.name]
            param_spec = param_value.get_spec(
                name=out.name,
                iotype=out.iotype,
                is_flag=out.is_flag,
                is_list=out.is_list,
                is_context=False,
                arg_format=out.arg_format,
            )
            if param_spec.param.is_ref:
                param_spec.validate_ref(None,
                                        is_template=False,
                                        check_runs=check_runs)
            else:  # Plain value
                parsed_value = out.validate_value(param_value.value)
                if parse_values:
                    param_spec.param.value = parsed_value
                    if not param_spec.param.connection and param_value.connection:
                        param_spec.param.connection = out.connection
                    if not param_spec.param.to_init and param_value.to_init:
                        param_spec.param.to_init = out.to_init
            validated_params.append(param_spec)
            if not param_spec.param.context_only:
                processed_params.append(out.name)
        # No validation for outputs we assume that the op might populate a context or send a metric
        else:
            validated_params.append(
                ParamSpec(
                    name=out.name,
                    param=V1Param(value=out.value,
                                  connection=out.connection,
                                  to_init=out.to_init),
                    iotype=out.iotype,
                    is_flag=out.is_flag,
                    is_list=out.is_list,
                    is_context=False,
                    arg_format=out.arg_format,
                ))
    extra_params = set(params.keys()) - set(processed_params)
    context_params = {p for p in params if params[p].context_only}
    extra_invalid_params = extra_params - context_params
    if extra_invalid_params:
        message = "Received unexpected params `{}`".format(
            extra_invalid_params)
        if extra_info:
            message += " Please check: {}".format(extra_info)
        raise ValidationError(message)

    # Add all (extra) context params that were not processed during the IO check
    for p in contexts_by_keys:
        if p in extra_params:
            param_value = params[p]
            param_spec = param_value.get_spec(
                name=p,
                iotype=None,
                is_flag=None,
                is_list=None,
                is_context=True,
                arg_format=None,
            )
            validated_params.append(param_spec)
        else:
            context_io = contexts_by_keys[p]
            validated_params.append(
                ParamSpec(
                    name=p,
                    param=V1Param(
                        value=context_io.value,
                        connection=context_io.connection,
                        to_init=context_io.to_init,
                    ),
                    iotype=None,
                    is_flag=None,
                    is_list=None,
                    is_context=True,
                    arg_format=None,
                ))
    return validated_params