Beispiel #1
0
    def test_io_config_default(self):
        config_dict = {
            "name": "input1",
            "description": "some text",
            "type": types.BOOL,
            "isOptional": True,
            "value": True,
        }
        config = V1IO.from_dict(config_dict)
        assert_equal_dict(config.to_dict(), config_dict)
        expected_repr = OrderedDict(
            (("name", "input1"), ("type", "bool"), ("value", True)))
        assert config.get_repr_from_value(None) == expected_repr
        assert config.get_repr() == expected_repr

        config_dict = {
            "name": "input1",
            "description": "some text",
            "type": types.FLOAT,
            "isOptional": True,
            "value": 3.4,
        }
        config = V1IO.from_dict(config_dict)
        assert_equal_dict(config.to_dict(), config_dict)
        expected_repr = OrderedDict(
            (("name", "input1"), ("type", "float"), ("value", 3.4)))
        assert config.get_repr_from_value(None) == expected_repr
        assert config.get_repr() == expected_repr
Beispiel #2
0
    def test_io_config_types(self):
        config_dict = {
            "name": "input1",
            "description": "some text",
            "type": types.INT
        }
        config = V1IO.from_dict(config_dict)
        assert_equal_dict(config.to_dict(), config_dict)
        expected_repr = OrderedDict(
            (("name", "input1"), ("type", "int"), ("value", 3)))
        assert config.get_repr_from_value(3) == expected_repr
        assert config.get_repr() == OrderedDict(
            (("name", "input1"), ("type", "int")))

        config_dict = {
            "name": "input1",
            "description": "some text",
            "type": types.S3
        }
        config = V1IO.from_dict(config_dict)
        assert_equal_dict(config.to_dict(), config_dict)
        expected_repr = OrderedDict(
            (("name", "input1"), ("type", types.S3), ("value", "s3://foo")))
        assert config.get_repr_from_value("s3://foo") == expected_repr
        assert config.get_repr() == OrderedDict(
            (("name", "input1"), ("type", types.S3)))
Beispiel #3
0
    def test_wrong_io_config_default(self):
        with self.assertRaises(ValidationError):
            V1IO.from_dict({
                "name": "input1",
                "type": types.FLOAT,
                "value": "foo"
            })

        with self.assertRaises(ValidationError):
            V1IO.from_dict({"name": "input1", "type": types.GCS, "value": 234})
Beispiel #4
0
    def test_wrong_io_config_flag(self):
        with self.assertRaises(ValidationError):
            V1IO.from_dict({
                "name": "input1",
                "type": types.S3,
                "isFlag": True
            })

        with self.assertRaises(ValidationError):
            V1IO.from_dict({
                "name": "input1",
                "type": types.FLOAT,
                "isFlag": True
            })
Beispiel #5
0
    def test_value_non_typed_input(self):
        config_dict = {"name": "input1"}
        config = V1IO.from_dict(config_dict)
        assert config.validate_value("foo") == "foo"
        assert config.validate_value(1) == 1
        assert config.validate_value(True) is True

        expected_repr = OrderedDict((("name", "input1"), ("value", "foo")))
        assert config.get_repr_from_value("foo") == expected_repr
        assert config.get_repr() == OrderedDict(name="input1")
Beispiel #6
0
    def test_io_config_default_and_required(self):
        config_dict = {
            "name": "input1",
            "description": "some text",
            "type": types.BOOL,
            "value": True,
            "isOptional": True,
        }
        config = V1IO.from_dict(config_dict)
        assert_equal_dict(config.to_dict(), config_dict)

        config_dict = {
            "name": "input1",
            "description": "some text",
            "type": types.STR,
            "value": "foo",
        }
        with self.assertRaises(ValidationError):
            V1IO.from_dict(config_dict)
Beispiel #7
0
    def test_value_typed_input(self):
        config_dict = {"name": "input1", "type": types.BOOL}
        config = V1IO.from_dict(config_dict)
        with self.assertRaises(ValidationError):
            config.validate_value("foo")
        with self.assertRaises(ValidationError):
            config.validate_value(1)
        with self.assertRaises(ValidationError):
            config.validate_value(None)

        assert config.validate_value(True) is True
Beispiel #8
0
 def test_io_config_flag(self):
     config_dict = {
         "name": "input1",
         "description": "some text",
         "type": types.BOOL,
         "isFlag": True,
     }
     config = V1IO.from_dict(config_dict)
     assert_equal_dict(config.to_dict(), config_dict)
     expected_repr = OrderedDict(
         (("name", "input1"), ("type", "bool"), ("value", False)))
     assert config.get_repr_from_value(False) == expected_repr
Beispiel #9
0
 def test_io_config_required(self):
     config_dict = {
         "name": "input1",
         "description": "some text",
         "type": "float",
         "isOptional": False,
     }
     config = V1IO.from_dict(config_dict)
     assert_equal_dict(config.to_dict(), config_dict)
     expected_repr = OrderedDict(
         (("name", "input1"), ("type", "float"), ("value", 1.1)))
     assert config.get_repr_from_value(1.1) == expected_repr
     assert config.get_repr() == OrderedDict(
         (("name", "input1"), ("type", "float")))
Beispiel #10
0
        def set_contexts() -> List[V1IO]:
            context_params = [
                p for p in param_specs if p not in processed_params
            ]
            contexts = []
            for p in context_params:
                current_param = param_specs[p].param
                contexts.append(
                    V1IO(
                        name=p,
                        value=current_param.value,
                        is_optional=True,
                        connection=current_param.connection,
                        to_init=current_param.to_init,
                    ))

            return contexts
Beispiel #11
0
    def test_io_name_blacklist(self):
        config_dict = {"name": "params"}
        with self.assertRaises(ValidationError):
            V1IO.from_dict(config_dict)

        config_dict = {"name": "globals"}
        with self.assertRaises(ValidationError):
            V1IO.from_dict(config_dict)

        config_dict = {"name": "connections"}
        with self.assertRaises(ValidationError):
            V1IO.from_dict(config_dict)
Beispiel #12
0
    def test_value_typed_input_with_default(self):
        config_dict = {
            "name": "input1",
            "type": types.INT,
            "value": 12,
            "isOptional": True,
        }
        config = V1IO.from_dict(config_dict)
        with self.assertRaises(ValidationError):
            config.validate_value("foo")

        assert config.validate_value(1) == 1
        assert config.validate_value(0) == 0
        assert config.validate_value(-1) == -1
        assert config.validate_value(None) == 12
        expected_repr = OrderedDict(
            (("name", "input1"), ("type", "int"), ("value", 12)))
        assert config.get_repr_from_value(None) == expected_repr
        assert config.get_repr() == expected_repr
Beispiel #13
0
    def process_components(self,
                           inputs=None,
                           ignore_hub_validation: bool = False):
        """`ignore_hub_validation` is currently used for ignoring validation
        during tests with hub_ref.
        """
        inputs = inputs or []
        self._context["dag.name"] = V1IO(name="name",
                                         type=types.STR,
                                         value="",
                                         is_optional=True)
        self._context["dag.uuid"] = V1IO(name="uuid",
                                         type=types.STR,
                                         value="",
                                         is_optional=True)
        for _input in inputs:
            self._context["dag.inputs.{}".format(_input.name)] = _input

        if not self.operations:
            raise PolyaxonSchemaError(
                "Pipeline is not valid, it has no ops to validate components.")

        components = self.components or []

        for component in components:
            component_name = component.name
            if component_name in self._components_by_names:
                raise PolyaxonSchemaError(
                    "Pipeline has multiple components with the same name `{}`".
                    format(component_name))
            self._components_by_names[component_name] = component

        for op in self.operations:
            op_name = op.name
            if op.has_component_reference:
                outputs = op.component.outputs
                inputs = op.component.inputs
            elif op.has_dag_reference:
                component_ref_name = op.dag_ref
                if op_name in self._op_component_mapping:
                    raise PolyaxonSchemaError(
                        "Pipeline has multiple ops with the same name `{}`".
                        format(op_name))
                if component_ref_name not in self._components_by_names:
                    raise PolyaxonSchemaError(
                        "Pipeline op with name `{}` requires a component with name `{}`, "
                        "which is not defined on this pipeline.".format(
                            op_name, component_ref_name))
                self._op_component_mapping[op_name] = component_ref_name
                outputs = self._components_by_names[component_ref_name].outputs
                inputs = self._components_by_names[component_ref_name].inputs
            elif op.has_hub_reference and ignore_hub_validation:
                continue
            else:
                raise PolyaxonSchemaError(
                    "Pipeline op has no definition field `{}`".format(op_name))

            if outputs:
                for output in outputs:
                    self._context["ops.{}.outputs.{}".format(
                        op_name, output.name)] = output
                    if output.type == types.ARTIFACTS:
                        self._context["ops.{}.artifacts.{}".format(
                            op_name, output.name)] = output

            if inputs:
                for cinput in inputs:
                    self._context["ops.{}.inputs.{}".format(
                        op_name, cinput.name)] = cinput
                    if cinput.type == types.ARTIFACTS:
                        self._context["ops.{}.artifacts.{}".format(
                            op_name, cinput.name)] = cinput
            for g_context in contexts_sections.GLOBALS_CONTEXTS:
                self._context["ops.{}.globals.{}".format(
                    op_name, g_context)] = V1IO(name=g_context,
                                                type=types.STR,
                                                value="",
                                                is_optional=True)

            # We allow to resolve name, status, project, all outputs/inputs, iteration
            self._context["ops.{}.{}".format(
                op_name, contexts_sections.INPUTS)] = V1IO(name="inputs",
                                                           type=types.DICT,
                                                           value={},
                                                           is_optional=True)
            self._context["ops.{}.{}".format(
                op_name, contexts_sections.OUTPUTS)] = V1IO(name="outputs",
                                                            type=types.DICT,
                                                            value={},
                                                            is_optional=True)
            self._context["ops.{}.{}".format(
                op_name, contexts_sections.GLOBALS)] = V1IO(name="globals",
                                                            type=types.STR,
                                                            value="",
                                                            is_optional=True)
            self._context["ops.{}.{}".format(
                op_name, contexts_sections.ARTIFACTS)] = V1IO(name="artifacts",
                                                              type=types.STR,
                                                              value="",
                                                              is_optional=True)
            self._context["ops.{}.{}".format(
                op_name,
                contexts_sections.INPUTS_OUTPUTS)] = V1IO(name="io",
                                                          type=types.STR,
                                                          value={},
                                                          is_optional=True)

        for op in self.operations:
            if op.has_component_reference:
                component_ref = op.definition.name
                outputs = op.definition.outputs
                inputs = op.definition.inputs
            elif op.has_dag_reference:
                component_ref = op.definition.name
                outputs = self._components_by_names[component_ref].outputs
                inputs = self._components_by_names[component_ref].inputs
            elif op.has_hub_reference and ignore_hub_validation:
                continue
            else:
                raise PolyaxonSchemaError(
                    "Pipeline op has no definition field `{}`".format(op.name))
            ops_params.validate_params(
                params=op.params,
                inputs=inputs,
                outputs=outputs,
                context=self._context,
                matrix=op.matrix,
                joins=op.joins,
                is_template=False,
                check_runs=False,
                extra_info="<op {}>.<component {}>".format(
                    op.name, component_ref),
            )
Beispiel #14
0
    def process_components(self, inputs=None):
        from polyaxon.polyaxonfile.check import collect_references

        inputs = inputs or []
        for _input in inputs:
            self._context["dag.inputs.{}".format(_input.name)] = _input

        if not self.operations:
            raise PolyaxonSchemaError(
                "Pipeline is not valid, it has no ops to validate components.")

        components = self.components or []

        for component in components:
            component_name = component.name
            if component_name in self._components_by_names:
                raise PolyaxonSchemaError(
                    "Pipeline has multiple components with the same name `{}`".
                    format(component_name))
            self._components_by_names[component_name] = component

        for op in self.operations:
            op_name = op.name
            if op.has_url_reference or op.has_path_reference:
                try:
                    op = collect_references(op, self._path_context)
                except Exception as e:
                    raise PolyaxonSchemaError(
                        "Pipeline op with name `{}` requires a component with ref `{}`, "
                        "the reference could not be resolved. Error: {}".
                        format(op_name, op.hub_ref or op.url_ref
                               or op.path_ref, e))
            elif op.has_hub_reference:
                continue
            if op.has_component_reference:
                outputs = op.component.outputs
                inputs = op.component.inputs
            elif op.has_dag_reference:
                component_ref_name = op.dag_ref
                if op_name in self._op_component_mapping:
                    raise PolyaxonSchemaError(
                        "Pipeline has multiple ops with the same name `{}`".
                        format(op_name))
                if component_ref_name not in self._components_by_names:
                    raise PolyaxonSchemaError(
                        "Pipeline op with name `{}` requires a component with name `{}`, "
                        "which is not defined on this pipeline.".format(
                            op_name, component_ref_name))
                self._op_component_mapping[op_name] = component_ref_name
                outputs = self._components_by_names[component_ref_name].outputs
                inputs = self._components_by_names[component_ref_name].inputs
            else:
                raise PolyaxonSchemaError(
                    "Pipeline op has no template field `{}`".format(op_name))

            if outputs:
                for output in outputs:
                    self._context["ops.{}.outputs.{}".format(
                        op_name, output.name)] = output

            if inputs:
                for cinput in inputs:
                    self._context["ops.{}.inputs.{}".format(
                        op_name, cinput.name)] = cinput

            # We allow to resolve name, status, project, all outputs/inputs, iteration
            self._context["ops.{}.inputs".format(op_name)] = V1IO(
                name="inputs", iotype=types.DICT, value={}, is_optional=True)
            self._context["ops.{}.outputs".format(op_name)] = V1IO(
                name="outputs", iotype=types.DICT, value={}, is_optional=True)
            self._context["ops.{}.status".format(op_name)] = V1IO(
                name="status", iotype=types.STR, value="", is_optional=True)
            self._context["ops.{}.name".format(op_name)] = V1IO(
                name="name", iotype=types.STR, value="", is_optional=True)
            self._context["ops.{}.uuid".format(op_name)] = V1IO(
                name="uuid", iotype=types.STR, value="", is_optional=True)
            self._context["ops.{}.project_name".format(op_name)] = V1IO(
                name="project_name",
                iotype=types.STR,
                value="",
                is_optional=True)
            self._context["ops.{}.project_uuid".format(op_name)] = V1IO(
                name="project_uuid",
                iotype=types.STR,
                value="",
                is_optional=True)
            self._context["ops.{}.iteration".format(op_name)] = V1IO(
                name="iteration", iotype=types.STR, value="", is_optional=True)

        for op in self.operations:
            if op.has_hub_reference:
                continue
            elif op.has_component_reference:
                component_ref = op.template.name
                outputs = op.template.outputs
                inputs = op.template.inputs
            elif op.has_dag_reference:
                component_ref = op.template.name
                outputs = self._components_by_names[component_ref].outputs
                inputs = self._components_by_names[component_ref].inputs
            else:
                raise PolyaxonSchemaError(
                    "Pipeline op has no template field `{}`".format(op.name))
            ops_params.validate_params(
                params=op.params,
                inputs=inputs,
                outputs=outputs,
                context=self._context,
                parallel=op.parallel,
                is_template=False,
                check_runs=False,
                extra_info="<op {}>.<component {}>".format(
                    op.name, component_ref),
            )
Beispiel #15
0
    def test_run_with_refs(self):
        # Get compiled_operation data
        run_config = V1CompiledOperation.read([
            os.path.abspath("tests/fixtures/typing/run_with_refs.yml"),
            {
                "kind": "compiled_operation"
            },
        ])
        params = {
            "num_masks": {
                "value": 2
            },
            "model_path": {
                "ref": "runs.64332180bfce46eba80a65caf73c5396",
                "value": "outputs.doo",
            },
        }
        validated_params = run_config.validate_params(params=params)
        param_specs_by_name = {p.name: p.param for p in validated_params}
        assert param_specs_by_name == {
            "num_masks":
            V1Param(value=2),
            "model_path":
            V1Param(ref="runs.64332180bfce46eba80a65caf73c5396",
                    value="outputs.doo"),
        }
        ref_param = param_specs_by_name["model_path"]
        assert ref_param.to_dict() == params["model_path"]

        with self.assertRaises(ValidationError):
            run_config.apply_params(params=params)

        # Passing correct context
        run_config.apply_params(
            params=params,
            context={
                "runs.64332180bfce46eba80a65caf73c5396.outputs.doo":
                V1IO(
                    name="model_path",
                    value="model_path",
                    is_optional=True,
                    iotype="path",
                )
            },
        )

        # New params
        params = {
            "num_masks": {
                "value": 2
            },
            "model_path": {
                "ref": "ops.A",
                "value": "outputs.doo"
            },
        }
        validated_params = run_config.validate_params(params=params)
        param_specs_by_name = {p.name: p.param for p in validated_params}
        assert param_specs_by_name == {
            "num_masks": V1Param(value=2),
            "model_path": V1Param(ref="ops.A", value="outputs.doo"),
        }

        ref_param = param_specs_by_name["model_path"]
        assert ref_param.to_dict() == params["model_path"]

        with self.assertRaises(ValidationError):
            run_config.apply_params(params=params)

        run_config.apply_params(
            params=params,
            context={
                "ops.A.outputs.doo":
                V1IO(
                    name="model_path",
                    value="model_path",
                    is_optional=True,
                    iotype="path",
                )
            },
        )
Beispiel #16
0
 def test_io_config_desc(self):
     # test desc
     config_dict = {"name": "input1", "description": "some text"}
     config = V1IO.from_dict(config_dict)
     assert_equal_dict(config.to_dict(), config_dict)
Beispiel #17
0
 def test_io_config_optionals(self):
     config_dict = {"name": "input1"}
     config = V1IO.from_dict(config_dict)
     assert_equal_dict(config.to_dict(), config_dict)
Beispiel #18
0
 def test_wrong_io_config(self):
     # No name
     with self.assertRaises(ValidationError):
         V1IO.from_dict({})
Beispiel #19
0
 def test_unsupported_io_config_type(self):
     with self.assertRaises(ValidationError):
         V1IO.from_dict({"name": "input1", "type": "something"})