Exemple #1
0
    def load_task_params_from_task_band(self, task_band, task_params):
        task_band_value = target(task_band).as_object.read_json()

        new_params = {}
        found = []
        source = "task_band.json"
        for name, p_value in iteritems(task_params):
            if name not in task_band_value or name == RESULT_PARAM:
                new_params[name] = p_value
                continue

            value = p_value.parameter.calc_init_value(task_band_value[name])
            found.append(name)
            new_parameter_value = ParameterValue(
                parameter=p_value.parameter,
                source=source,
                source_value=value,
                value=value,
            )
            new_params[new_parameter_value.name] = new_parameter_value

        logger.info("Loading task '{task_family}' from {task_band}:\n"
                    "\tfields taken:\t{found}".format(
                        task_family=self.task_family,
                        task_band=task_band,
                        found=",".join(found)))
        return new_params
Exemple #2
0
    def load_task_params_from_task_band(self, task_band, task_params):
        task_band_value = target(task_band).as_object.read_json()

        new_params = []
        found = []

        source = "task_band.json"
        for p_value in task_params:
            if p_value.name not in task_band_value or p_value.name == "result":
                new_params.append(p_value)
                continue

            value = p_value.parameter.calc_init_value(
                task_band_value[p_value.name])
            found.append(p_value.name)
            new_parameter_value = ParameterValue(
                parameter=p_value.parameter,
                source=source,
                source_value=value,
                value=value,
            )
            new_params.append(new_parameter_value)

        logger.info("Loading task '{task_family}' from {task_band}:\n"
                    "\tfields taken:\t{found}".format(
                        task_family=self.task_family,
                        task_band=task_band,
                        found=",".join(found)))
        return new_params
Exemple #3
0
def build_user_parameter_value(name, value, source):
    """
    Build parameter value for user defined name and value
    """
    value_type = get_value_type_of_obj(
        value, default_value_type=DefaultObjectValueType)
    param_f = get_parameter_for_value_type(value_type)
    param = build_parameter(param_f)
    param.name = name

    if value is NOTHING:
        parameter, warnings = param, []
        actual_value = param.default
    else:
        parameter, warnings = infer_parameter_value_type(param, value)
        actual_value = value

    return ParameterValue(
        parameter=parameter,
        source=source,
        source_value=value,
        value=actual_value,
        parsed=False,
        warnings=warnings,
    )
Exemple #4
0
    def build_parameter_value(self, param_def):
        # This is the place we calculate param_def value
        # based on Class(defaults, constructor, overrides, root)
        # and Config(env, cmd line, config)  state

        # used for target_format update
        # change param_def definition based on config state
        param_def = self._update_param_def_target_config(param_def=param_def)
        param_name = param_def.name
        p_config_value = self._get_param_config_value(param_def)

        if p_config_value and p_config_value.override:
            cf_value = p_config_value
        elif param_name in self.ctor_kwargs:
            cf_value = ConfigValue(self.ctor_kwargs.get(param_name),
                                   source=self._source_name("ctor"))
        elif p_config_value:
            cf_value = p_config_value
        elif param_def.is_output():
            # outputs can be none, we "generate" their values later
            cf_value = None
        else:
            err_msg = "No value defined for '{name}' at {context_str}".format(
                name=param_name, context_str=self._exc_desc)
            raise MissingParameterError(
                err_msg,
                help_msg=param_def._get_help_message(
                    sections=self.task_config_sections),
            )
        if cf_value:
            param_def, p_value = build_parameter_value(param_def, cf_value)
            p_value = ParameterValue(
                parameter=param_def,
                source=cf_value.source,
                source_value=cf_value.value,
                value=p_value,
                parsed=cf_value.require_parse,
            )
        else:
            p_value = ParameterValue(
                parameter=param_def,
                source=None,
                source_value=NOTHING,
                value=NOTHING,
                parsed=False,
            )
        return p_value
Exemple #5
0
    def _build_user_parameter_value(self, param_def, value):
        if value is NOTHING:
            parameter, warnings = param_def, []
            actual_value = param_def.default
        else:
            parameter, warnings = infer_parameter_value_type(param_def, value)
            actual_value = value

        return ParameterValue(
            parameter=parameter,
            source=self.task_definition.full_task_family_short,
            source_value=value,
            value=actual_value,
            parsed=False,
            warnings=warnings,
        )
Exemple #6
0
def build_result_param(task_passport, param_def=None, name=RESULT_PARAM):
    # type: (TaskPassport, Optional[ParameterDefinition], str) -> ParameterValue
    """
    Build results parameter for the task definition, if parameter definition is not specify it will build a naive one.
    """

    if not param_def:
        from targets.values import ObjectValueType

        # naive creation of result param definition - default named "result" and single value
        param_def = parameter.modify(
            name=name,
            value_type=ObjectValueType).output.build_parameter("inline")

    return ParameterValue(
        parameter=param_def,
        source=task_passport.full_task_family_short,
        source_value=None,
        value=NOTHING,
        parsed=False,
    )
def build_parameter_value(parameter, cf_value):
    # type: (ParameterDefinition, ConfigValue) -> ParameterValue
    if not cf_value:
        return ParameterValue(
            parameter=parameter,
            source=None,
            source_value=NOTHING,
            value=NOTHING,
            parsed=False,
        )

    warnings = []
    value = cf_value.value
    try:
        if value is not None and not parameter.is_output():
            updated_value_type = _update_parameter_from_runtime_value_type(
                parameter, value)
            message = ("{parameter}: type of the value at runtime '{runtime}"
                       " doesn't match user defined type '{compile}'".format(
                           parameter=parameter,
                           runtime=updated_value_type,
                           compile=parameter.value_type,
                       ))
            if updated_value_type:
                if isinstance(parameter.value_type, DefaultObjectValueType):
                    # we are going to update
                    parameter = attr.evolve(
                        parameter,
                        value_type=updated_value_type,
                        load_on_build=updated_value_type.load_on_build,
                    )
                    message = "%s: updating parameter with the runtime info" % (
                        message)
                # warn anyway
                warnings.append(message)

    except Exception as ex:
        # we don't want to fail user code on failed value discovery
        # we only print message from "friendly exception" and show real stack
        logger.exception("Failed to discover runtime for %s", parameter)

    try:
        p_val = parameter.calc_init_value(value)
    except Exception as ex:
        raise parameter.parameter_exception("calculate value from '%s'" %
                                            safe_string(value, 100),
                                            ex=ex)

    # we need to break strong reference between tasks
    # otherwise we will have pointer from task to another task
    # if p_val is task, that's ok, but let minimize the risk by patching cf_value
    if isinstance(value, _TaskParamContainer):
        cf_value.value = str(cf_value)

    try:
        if p_val is not None and not isinstance(p_val, Target):
            parameter.validate(p_val)
    except Exception as ex:
        raise parameter.parameter_exception("validate value='%s'" %
                                            safe_string(p_val),
                                            ex=ex)

    p_value = ParameterValue(
        parameter=parameter,
        source=cf_value.source,
        source_value=cf_value.value,
        value=p_val,
        parsed=cf_value.require_parse,
        warnings=warnings + cf_value.warnings,
    )

    return p_value
Exemple #8
0
    def _build_parameter_value(self, param_def):
        # type: (ParameterDefinition) -> ParameterValue
        """
               -= MAIN FUNCTION for Parameter Calculation =-
        This is the place we calculate param_def value
        based on Class(defaults, constructor, overrides, root)
        and Config(env, cmd line, config)  state

        Build parameter value from config_value and param_definition.
        Considerate - priority, constructor values, param type and so on.
        """
        config_values_stack = self._get_config_value_stack_for_param(param_def)
        param_name = param_def.name

        # if we will use config values we will need to reduce them to a single value
        # if there is only one - reduce will get it
        # other wise we need combine the values using `fold_parameter_value`
        # may raise if can't fold two values together!!

        has_overrides_in_config = any(
            cf for cf in config_values_stack
            if cf and cf.priority >= ConfigValuePriority.OVERRIDE)

        # first check for override (HIGHEST PRIORITY)
        if has_overrides_in_config:
            config_values_as_param_values = [
                build_parameter_value(param_def, cf)
                for cf in config_values_stack
            ]
            return functools.reduce(fold_parameter_value,
                                    config_values_as_param_values)

        # second using kwargs we received from the user
        # do we need to do it for tracking?
        elif param_name in self.task_kwargs:
            return build_parameter_value(
                param_def,
                ConfigValue(self.task_kwargs.get(param_name),
                            source=self._source_name("ctor")),
            )

        if config_values_stack:
            config_values_as_param_values = [
                build_parameter_value(param_def, cf)
                for cf in config_values_stack
            ]
            return functools.reduce(fold_parameter_value,
                                    config_values_as_param_values)

        if (self.parent_task
                and param_name in self.parent_task.task_children_scope_params):
            # we have parent task with param = parameter(scope=ParameterScope.children)
            # the priority is lower than config (as this one is more like "default" than "explicit config")
            # see _calculate_task_children_scope_params implementation and ParameterScope.children
            parameter_value = self.parent_task.task_children_scope_params[
                param_name]
            return build_parameter_value(
                param_def,
                ConfigValue(value=parameter_value.value,
                            source=parameter_value.source),
            )

        if param_def.from_task_env_config:
            # param = parameter(from_task_env_config=True)
            # we check task.task_env.param for the value
            if not self.task_env_config:
                raise friendly_error.task_parameters.task_env_param_with_no_env(
                    context=self._ctor_as_str, key=param_name)
            param_env_config_value = self.task_env_config.task_params.get_param_value(
                param_name)
            if param_env_config_value is None:
                raise friendly_error.task_parameters.task_env_param_not_exists_in_env(
                    context=self._ctor_as_str,
                    key=param_name,
                    env_config=self.task_env_config,
                )
            return build_parameter_value(
                param_def,
                ConfigValue(
                    value=param_env_config_value.value,
                    source=param_env_config_value.source,
                ),
            )

        if param_name in self.task_definition.param_defaults:
            # we can't "add" defaults to the current config and rely on configuration system
            # we don't know what section name to use, and it my clash with current config
            return build_parameter_value(
                param_def,
                ConfigValue(
                    self.task_definition.param_defaults.get(param_name),
                    source=self._source_name("default"),
                ),
            )

        if not param_def.is_output():
            # outputs can be none, we "generate" their values later
            err_msg = "No value defined for '{name}' at {context_str}".format(
                name=param_name, context_str=self._ctor_as_str)
            raise MissingParameterError(
                err_msg,
                help_msg=param_def._get_help_message(
                    sections=self.config_sections),
            )

        # returning empty Output value
        return ParameterValue(
            parameter=param_def,
            source="",
            source_value=NOTHING,
            value=NOTHING,
            parsed=False,
        )
Exemple #9
0
import pytest

from dbnd import parameter
from dbnd._core.parameter.parameter_value import ParameterValue, fold_parameter_value

list_of_ints = parameter[List[int]].build_parameter("context")
str_to_init_map = parameter[Dict[str, int]].build_parameter("context")
just_int = parameter[int].build_parameter("context")


@pytest.mark.parametrize(
    "left, right, expected",
    [
        pytest.param(
            ParameterValue(parameter=list_of_ints,
                           value=[1],
                           source="test",
                           source_value=[1]),
            None,
            ParameterValue(parameter=list_of_ints,
                           value=[1],
                           source="test",
                           source_value=[1]),
            id="Fold value with None",
        ),
        pytest.param(
            ParameterValue(parameter=list_of_ints,
                           value=[1],
                           source="test",
                           source_value=[1]),
            ParameterValue(parameter=list_of_ints,
                           value=[2],