def test_job_refs_params(self): config_dict = { "inputs": [ { "name": "param1", "type": types.INT }, { "name": "param9", "type": types.FLOAT }, ], "run": { "kind": "container", "image": "test" }, } params = {"param1": "{{ job.A.outputs.foo }}", "param9": 13.1} config = ComponentConfig.from_dict(config_dict) # Validation outside the context of a pipeline with self.assertRaises(ValidationError): ops_params.validate_params(params=params, inputs=config.inputs, outputs=None, is_template=False)
def test_incomplete_params(self): config_dict = { "inputs": [ { "name": "param1", "type": types.INT }, { "name": "param2", "type": types.INT }, ], "run": { "kind": "container", "image": "test" }, } config = ComponentConfig.from_dict(config_dict) with self.assertRaises(ValidationError): ops_params.validate_params( params={"param1": 1}, inputs=config.inputs, outputs=config.outputs, is_template=False, ) config_dict = { "outputs": [ { "name": "param1", "type": types.INT, "value": 12, "is_optional": True }, { "name": "param2", "type": types.INT }, ], "run": { "kind": "container", "image": "test" }, } config = ComponentConfig.from_dict(config_dict) ops_params.validate_params( params={"param1": 1}, inputs=config.inputs, outputs=config.outputs, is_template=False, )
def test_extra_params(self): # inputs config_dict = { "inputs": [{ "name": "param1", "type": types.INT }], "run": { "kind": "container", "image": "test" }, } config = ComponentConfig.from_dict(config_dict) with self.assertRaises(ValidationError): ops_params.validate_params( params={ "param1": 1, "param2": 2 }, inputs=config.inputs, outputs=config.outputs, is_template=False, ) # outputs config_dict = { "outputs": [{ "name": "param1", "type": types.INT }], "run": { "kind": "container", "image": "test" }, } config = ComponentConfig.from_dict(config_dict) with self.assertRaises(ValidationError): ops_params.validate_params( params={ "param1": 1, "param2": 2 }, inputs=config.inputs, outputs=config.outputs, is_template=False, )
def test_experiment_and_job_refs_params(self): config_dict = { "inputs": [ { "name": "param1", "type": types.INT }, { "name": "param2", "type": types.FLOAT }, { "name": "param9", "type": types.WASB }, { "name": "param11", "type": types.METRIC }, ], "run": { "kind": "container", "image": "test" }, } op = ComponentConfig.from_dict(config_dict) params = { "param1": "{{ runs.64332180bfce46eba80a65caf73c5396.outputs.foo }}", "param2": "{{ runs.0de53b5bf8b04a219d12a39c6b92bcce.outputs.foo }}", "param9": "wasbs://[email protected]/", "param11": "{{ runs.fcc462d764104eb698d3cca509f34154.outputs.accuracy }}", } validated_params = ops_params.validate_params(params=params, inputs=op.inputs, outputs=None, is_template=False) assert {p.name: p.value for p in validated_params} == { "param1": "runs.64332180bfce46eba80a65caf73c5396.outputs.foo", "param2": "runs.0de53b5bf8b04a219d12a39c6b92bcce.outputs.foo", "param9": "wasbs://[email protected]/", "param11": "runs.fcc462d764104eb698d3cca509f34154.outputs.accuracy", }
def validate_params( self, params=None, context=None, is_template=True, check_runs=False ): try: return ops_params.validate_params( inputs=self.config.inputs, outputs=self.config.outputs, params=params, context=context, is_template=is_template, check_runs=check_runs, ) except ValidationError as e: raise PolyaxonfileError("Params validation error: `{}`".format(e))
def process_components(self, inputs=None): inputs = inputs or [] for _input in inputs: self._context["dag.inputs.{}".format(_input.name)] = _input if not self.ops: 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.ops: op_name = op.name if op.component: outputs = op.component.outputs inputs = op.component.inputs elif op.component_ref and op.component_ref.name: component_ref_name = op.component_ref.name 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.component_ref.hub: continue else: raise PolyaxonSchemaError( "Pipeline op has no component or component_ref `{}`". 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 for op in self.ops: if op.component: outputs = op.component.outputs inputs = op.component.inputs elif op.component_ref.hub: continue else: outputs = self._components_by_names[ op.component_ref.name].outputs inputs = self._components_by_names[ op.component_ref.name].inputs ops_params.validate_params( params=op.params, inputs=inputs, outputs=outputs, context=self._context, is_template=False, check_runs=False, extra_info="<op {}>.<component {}>".format( op.name, op.component.name if op.component else op.component_ref.name, ), )
def test_param_validation_with_inputs(self): config_dict = { "inputs": [ { "name": "param1", "type": IOTypes.STR }, { "name": "param2", "type": IOTypes.INT }, { "name": "param3", "type": IOTypes.FLOAT }, { "name": "param4", "type": IOTypes.BOOL }, { "name": "param5", "type": IOTypes.DICT }, { "name": "param6", "type": IOTypes.LIST }, { "name": "param7", "type": IOTypes.GCS_PATH }, { "name": "param8", "type": IOTypes.S3_PATH }, { "name": "param9", "type": IOTypes.AZURE_PATH }, { "name": "param10", "type": IOTypes.PATH }, ], "container": { "image": "test" }, } op = ComponentConfig.from_dict(config_dict) params = { "param1": "text", "param2": 12, "param3": 13.3, "param4": False, "param5": { "foo": "bar" }, "param6": [1, 3, 45, 5], "param7": "gs://bucket/path/to/blob/", "param8": "s3://test/this/is/bad/key.txt", "param9": "wasbs://[email protected]/", "param10": "/foo/bar", } validated_params = ops_params.validate_params(params=params, inputs=op.inputs, outputs=None, is_template=False) assert params == {p.name: p.value for p in validated_params} # Passing missing params params.pop("param1") params.pop("param2") with self.assertRaises(ValidationError): ops_params.validate_params(params=params, inputs=op.inputs, outputs=None, is_template=False)
def test_param_validation_with_mismatched_outputs(self): config_dict = { "outputs": [{ "name": "param1", "type": IOTypes.INT }], "container": { "image": "test" }, } config = ComponentConfig.from_dict(config_dict) # Passing correct param ops_params.validate_params( params={"param1": 1}, inputs=config.inputs, outputs=config.outputs, is_template=False, ) # Passing wrong type with self.assertRaises(ValidationError): ops_params.validate_params( params={"param1": "text"}, inputs=config.inputs, outputs=config.outputs, is_template=False, ) with self.assertRaises(ValidationError): ops_params.validate_params( params={"param1": 12.1}, inputs=config.inputs, outputs=config.outputs, is_template=False, ) with self.assertRaises(ValidationError): ops_params.validate_params( params={"param1": { "foo": "bar" }}, inputs=config.inputs, outputs=config.outputs, is_template=False, ) with self.assertRaises(ValidationError): ops_params.validate_params( params={"param1": "gs://bucket/path/to/blob/"}, inputs=config.inputs, outputs=config.outputs, is_template=False, ) config_dict = { "outputs": [{ "name": "param2", "type": IOTypes.STR }], "container": { "image": "test" }, } config = ComponentConfig.from_dict(config_dict) # Passing correct param ops_params.validate_params( params={"param2": "text"}, inputs=config.inputs, outputs=config.outputs, is_template=False, ) # Passing wrong type with self.assertRaises(ValidationError): ops_params.validate_params( params={"param2": 1}, inputs=config.inputs, outputs=config.outputs, is_template=False, ) with self.assertRaises(ValidationError): ops_params.validate_params( params={"param2": False}, inputs=config.inputs, outputs=config.outputs, is_template=False, ) with self.assertRaises(ValidationError): ops_params.validate_params( params={"param2": { "foo": "bar" }}, inputs=config.inputs, outputs=config.outputs, is_template=False, ) with self.assertRaises(ValidationError): ops_params.validate_params( params={"param2": ["gs://bucket/path/to/blob/"]}, inputs=config.inputs, outputs=config.outputs, is_template=False, ) config_dict = { "outputs": [{ "name": "param7", "type": IOTypes.AZURE_PATH }], "container": { "image": "test" }, } config = ComponentConfig.from_dict(config_dict) # Passing correct param ops_params.validate_params( params={"param7": "wasbs://[email protected]/"}, inputs=config.inputs, outputs=config.outputs, is_template=False, ) # Passing wrong param with self.assertRaises(ValidationError): ops_params.validate_params( params={"param7": "gs://bucket/path/to/blob/"}, inputs=config.inputs, outputs=config.outputs, is_template=False, ) with self.assertRaises(ValidationError): ops_params.validate_params( params={"param7": "s3://test/this/is/bad/key.txt"}, inputs=config.inputs, outputs=config.outputs, is_template=False, ) with self.assertRaises(ValidationError): ops_params.validate_params( params={"param7": 1}, inputs=config.inputs, outputs=config.outputs, is_template=False, )
def test_required_input_no_param_only_validated_on_run(self): # Inputs config_dict = { "inputs": [ { "name": "param1", "type": IOTypes.STR }, { "name": "param10", "type": IOTypes.PATH }, ], "container": { "image": "test" }, } config = ComponentConfig.from_dict(config_dict) with self.assertRaises(ValidationError): ops_params.validate_params( params={"param1": "text"}, inputs=config.inputs, outputs=config.outputs, is_template=False, ) # Outputs config_dict = { "outputs": [ { "name": "param1", "type": IOTypes.STR }, { "name": "param10", "type": IOTypes.PATH }, ], "container": { "image": "test" }, } config = ComponentConfig.from_dict(config_dict) ops_params.validate_params( params={"param1": "text"}, inputs=config.inputs, outputs=config.outputs, is_template=False, ) # IO config_dict = { "inputs": [{ "name": "param1", "type": IOTypes.STR }], "outputs": [{ "name": "param10", "type": IOTypes.PATH }], "container": { "image": "test" }, } config = ComponentConfig.from_dict(config_dict) ops_params.validate_params( params={"param1": "text"}, inputs=config.inputs, outputs=config.outputs, is_template=False, )
def test_param_validation_with_outputs(self): config_dict = { "outputs": [ { "name": "param1", "type": types.STR }, { "name": "param2", "type": types.INT }, { "name": "param3", "type": types.FLOAT }, { "name": "param4", "type": types.BOOL }, { "name": "param5", "type": types.DICT }, { "name": "param6", "type": types.LIST }, { "name": "param7", "type": types.GCS }, { "name": "param8", "type": types.S3 }, { "name": "param9", "type": types.WASB }, { "name": "param10", "type": types.PATH }, { "name": "param11", "type": types.METRIC }, { "name": "param12", "type": types.METADATA }, { "name": "param13", "type": types.METADATA }, { "name": "param14", "type": types.METADATA }, ], "run": { "kind": "container", "image": "test" }, } op = ComponentConfig.from_dict(config_dict) params = { "param1": "text", "param2": 12, "param3": 13.3, "param4": False, "param5": { "foo": "bar" }, "param6": [1, 3, 45, 5], "param7": "gs://bucket/path/to/blob/", "param8": "s3://test/this/is/bad/key.txt", "param9": "wasbs://[email protected]/", "param10": "/foo/bar", "param11": 124.4, "param12": { "foo": 124.4 }, "param13": { "foo": "bar" }, "param14": { "foo": ["foo", 124.4] }, } validated_params = ops_params.validate_params(params=params, inputs=None, outputs=op.outputs, is_template=False) assert params == {p.name: p.value for p in validated_params} # Passing missing params params.pop("param1") params.pop("param2") validated_params = ops_params.validate_params(params=params, inputs=None, outputs=op.outputs, is_template=False) params["param1"] = None params["param2"] = None assert params == {p.name: p.value for p in validated_params}