def check_polyaxonfile(polyaxonfile, params=None, profile=None, queue=None, nocache=None, log=True): if not polyaxonfile: polyaxonfile = PolyaxonFile.check_default_path(path=".") if not polyaxonfile: polyaxonfile = "" polyaxonfile = to_list(polyaxonfile) exists = [os.path.isfile(f) for f in polyaxonfile] parsed_params = None if params: parsed_params = parse_params(params) if not any(exists): Printer.print_error("Polyaxonfile is not present, " "please run {}".format(constants.INIT_COMMAND)) sys.exit(1) try: plx_file = PolyaxonFile(polyaxonfile) plx_file = plx_file.get_op_specification(params=parsed_params, profile=profile, queue=queue, nocache=nocache) if log: Printer.print_success("Polyaxonfile valid") return plx_file except Exception as e: handle_cli_error(e, message="Polyaxonfile is not valid.") sys.exit(1)
def test_passing_params_to_no_io_overrides_polyaxonfiles_raises(self): polyaxonfile = PolyaxonFile( os.path.abspath("tests/fixtures/plain/simple_job.yml")) with self.assertRaises(PolyaxonfileError): polyaxonfile.get_op_specification(params={ "flag": True, "loss": "some-loss" })
def test_no_params_for_required_inputs_outputs_raises(self): plx = PolyaxonFile( os.path.abspath("tests/fixtures/typing/required_inputs.yml")) with self.assertRaises(PolyaxonfileError): plx.specification.apply_context() plx = PolyaxonFile( os.path.abspath("tests/fixtures/typing/required_outputs.yml")) with self.assertRaises(PolyaxonfileError): plx.specification.apply_context()
def test_cyclic_pipeline_raises(self): plx_file = PolyaxonFile( os.path.abspath("tests/fixtures/pipelines/cyclic_pipeline.yml")) assert plx_file.specification.has_dag is True assert plx_file.specification.has_pipeline is True with self.assertRaises(PolyaxonSchemaError): plx_file.specification.apply_context()
def test_pipeline_ops_not_corresponding_to_components(self): plx_file = PolyaxonFile( os.path.abspath( "tests/fixtures/pipelines/pipeline_ops_not_corresponding_to_components.yml" )) with self.assertRaises(PolyaxonSchemaError): plx_file.specification.apply_context()
def test_dag_pipeline(self): plx_file = PolyaxonFile( os.path.abspath( "tests/fixtures/pipelines/simple_dag_pipeline.yml")) spec = plx_file.specification spec = spec.apply_context() assert len(spec.config.workflow.strategy.ops) == 5 assert spec.config.workflow.strategy.ops[0].name == "job1" assert spec.config.workflow.strategy.ops[1].name == "experiment1" assert spec.config.workflow.strategy.ops[1].dependencies == ["job1"] assert spec.config.workflow.strategy.ops[2].name == "experiment2" assert spec.config.workflow.strategy.ops[2].dependencies == ["job1"] assert spec.config.workflow.strategy.ops[3].name == "experiment3" assert spec.config.workflow.strategy.ops[3].dependencies == ["job1"] assert spec.config.workflow.strategy.ops[4].name == "job2" assert spec.config.workflow.strategy.ops[4].dependencies == [ "experiment1", "experiment2", "experiment3", ] dag_strategy = spec.config.workflow.strategy sorted_dag = dag_strategy.sort_topologically(dag_strategy.dag) assert sorted_dag[0] == ["job1"] assert set( sorted_dag[1]) == {"experiment1", "experiment2", "experiment3"} assert sorted_dag[2] == ["job2"] assert spec.config.workflow.concurrency == 3 assert spec.config.schedule is None assert spec.concurrency == 3 assert spec.schedule is None
def test_parallel_pipeline(self): plx_file = PolyaxonFile( os.path.abspath( "tests/fixtures/pipelines/simple_parallel_pipeline.yml")) spec = plx_file.specification spec = spec.apply_context() assert len(spec.config.workflow.strategy.ops) == 4 assert spec.config.workflow.strategy.ops[0].name == "job1" assert spec.config.workflow.strategy.ops[0].dependencies is None assert spec.config.workflow.strategy.ops[1].name == "job2" assert spec.config.workflow.strategy.ops[1].dependencies is None assert spec.config.workflow.strategy.ops[2].name == "experiment1" assert spec.config.workflow.strategy.ops[2].dependencies is None assert spec.config.workflow.strategy.ops[3].name == "experiment2" assert spec.config.workflow.strategy.ops[3].dependencies is None dag_strategy = spec.config.workflow.strategy assert set(dag_strategy.sort_topologically(dag_strategy.dag)[0]) == { "job1", "job2", "experiment1", "experiment2", } assert spec.config.workflow.concurrency == 2 assert spec.config.schedule is None assert spec.concurrency == 2 assert spec.schedule is None
def test_sequential_pipeline(self): plx_file = PolyaxonFile( os.path.abspath( "tests/fixtures/pipelines/simple_sequential_pipeline.yml")) spec = plx_file.specification spec = spec.apply_context() assert spec.config.workflow is not None assert len(spec.config.workflow.strategy.ops) == 4 assert spec.config.workflow.strategy.ops[0].name == "job1" assert spec.config.workflow.strategy.ops[1].name == "job2" assert spec.config.workflow.strategy.ops[1].dependencies == ["job1"] assert spec.config.workflow.strategy.ops[2].name == "experiment1" assert spec.config.workflow.strategy.ops[2].dependencies == ["job2"] assert spec.config.workflow.strategy.ops[3].name == "experiment2" assert spec.config.workflow.strategy.ops[3].dependencies == [ "experiment1" ] dag_strategy = spec.config.workflow.strategy assert dag_strategy.sort_topologically(dag_strategy.dag) == [ ["job1"], ["job2"], ["experiment1"], ["experiment2"], ] assert spec.config.schedule is None
def test_mapping_early_stopping_file_passes(self): plx_file = PolyaxonFile( os.path.abspath( "tests/fixtures/plain/mapping_job_file_early_stopping.yml")) # Get compiled_operation data config_run = OperationSpecification.compile_operation(plx_file.config) config_run = CompiledOperationSpecification.apply_context(config_run) assert config_run.version == 1.05 assert isinstance(config_run.parallel, V1Mapping) assert config_run.parallel.values == [ { "lr": 0.001, "loss": "MeanSquaredError" }, { "lr": 0.1, "loss": "AbsoluteDifference" }, ] assert config_run.parallel.concurrency == 2 assert isinstance(config_run.parallel, V1Mapping) assert config_run.parallel.kind == V1Mapping.IDENTIFIER assert len(config_run.parallel.early_stopping) == 1 assert isinstance(config_run.parallel.early_stopping[0], V1MetricEarlyStopping)
def test_matrix_early_stopping_file_passes(self): plx_file = PolyaxonFile( os.path.abspath( "tests/fixtures/plain/matrix_job_file_early_stopping.yml")) # Get compiled_operation data run_config = OperationSpecification.compile_operation(plx_file.config) run_config = CompiledOperationSpecification.apply_context(run_config) assert run_config.version == 1.05 assert isinstance(run_config.parallel, V1RandomSearch) assert isinstance(run_config.parallel.params["lr"], V1HpLinSpace) assert isinstance(run_config.parallel.params["loss"], V1HpChoice) assert run_config.parallel.params["lr"].to_dict() == { "kind": "linspace", "value": { "start": 0.01, "stop": 0.1, "num": 5 }, } assert run_config.parallel.params["loss"].to_dict() == { "kind": "choice", "value": ["MeanSquaredError", "AbsoluteDifference"], } assert run_config.parallel.concurrency == 2 assert run_config.parallel.num_runs == 300 assert isinstance(run_config.parallel, V1RandomSearch) assert run_config.parallel.kind == V1RandomSearch.IDENTIFIER assert len(run_config.parallel.early_stopping) == 1 assert isinstance(run_config.parallel.early_stopping[0], V1MetricEarlyStopping)
def test_matrix_file_passes_int_float_types(self): plxfile = PolyaxonFile( os.path.abspath( "tests/fixtures/pipelines/matrix_file_with_int_float_types.yml" )) spec = plxfile.specification spec = spec.apply_context() assert spec.version == 1.0 assert spec.is_component is True assert spec.has_dag_run is True assert spec.has_pipeline is True assert spec.config.schedule is None assert spec.run.concurrency == 4 assert spec.run_concurrency == 4 assert isinstance(spec.run, DagConfig) assert spec.run.early_stopping is None assert spec.run_early_stopping == [] assert spec.run_kind == DagConfig.IDENTIFIER assert len(spec.run.ops) == 2 assert len(spec.run.components) == 1 template_grid = spec.run.components[0].parallel assert isinstance(template_grid, GridSearchConfig) assert isinstance(template_grid.matrix["param1"], MatrixChoiceConfig) assert isinstance(template_grid.matrix["param2"], MatrixChoiceConfig) assert template_grid.matrix["param1"].to_dict() == { "kind": "choice", "value": [1, 2], } assert template_grid.matrix["param2"].to_dict() == { "kind": "choice", "value": [3.3, 4.4], } assert template_grid.concurrency == 2 assert template_grid.early_stopping is None
def test_matrix_file_passess(self): plxfile = PolyaxonFile( os.path.abspath("tests/fixtures/pipelines/matrix_file.yml")) spec = plxfile.specification spec = spec.apply_context() assert spec.version == 1.0 assert spec.is_component is True assert spec.has_dag_run is True assert spec.has_pipeline is True assert spec.config.schedule is None assert spec.run.concurrency == 4 assert spec.run_concurrency == 4 assert isinstance(spec.run, DagConfig) assert spec.run.early_stopping is None assert spec.run_early_stopping == [] assert spec.run_kind == DagConfig.IDENTIFIER assert len(spec.run.ops) == 2 assert len(spec.run.components) == 1 template_hyperband = spec.run.components[0].parallel assert isinstance(template_hyperband.matrix["lr"], MatrixLinSpaceConfig) assert isinstance(template_hyperband.matrix["loss"], MatrixChoiceConfig) assert template_hyperband.matrix["lr"].to_dict() == { "kind": "linspace", "value": { "start": 0.01, "stop": 0.1, "num": 5 }, } assert template_hyperband.matrix["loss"].to_dict() == { "kind": "choice", "value": ["MeanSquaredError", "AbsoluteDifference"], } assert template_hyperband.matrix["normal_rate"].to_dict() == { "kind": "normal", "value": { "loc": 0, "scale": 0.9 }, } assert template_hyperband.matrix["dropout"].to_dict() == { "kind": "qloguniform", "value": { "high": 0.8, "low": 0, "q": 0.1 }, } assert template_hyperband.matrix["activation"].to_dict() == { "kind": "pchoice", "value": [["relu", 0.1], ["sigmoid", 0.8]], } assert template_hyperband.matrix["model"].to_dict() == { "kind": "choice", "value": ["CDNA", "DNA", "STP"], } assert template_hyperband.concurrency == 2 assert isinstance(template_hyperband, HyperbandConfig)
def test_matrix_job_file_passes_int_float_types(self): plxfile = PolyaxonFile( os.path.abspath( "tests/fixtures/typing/matrix_job_file_with_int_float_types.yml" )) op_config = plxfile.config # Get compiled_operation data run_config = OperationSpecification.compile_operation(op_config) run_config = CompiledOperationSpecification.apply_context(run_config) assert run_config.version == 1.05 assert isinstance(run_config.parallel.params["param1"], V1HpChoice) assert isinstance(run_config.parallel.params["param2"], V1HpChoice) assert run_config.parallel.params["param1"].to_dict() == { "kind": "choice", "value": [1, 2], } assert run_config.parallel.params["param2"].to_dict() == { "kind": "choice", "value": [3.3, 4.4], } assert isinstance(run_config.parallel, V1GridSearch) assert run_config.parallel.concurrency == 2 assert run_config.parallel.kind == V1GridSearch.IDENTIFIER assert run_config.parallel.early_stopping is None
def test_matrix_file_passes_int_float_types(self): plxfile = PolyaxonFile( os.path.abspath( "tests/fixtures/typing/matrix_file_with_int_float_types.yml")) spec = plxfile.specification spec = spec.apply_context() assert spec.version == 0.6 assert spec.is_component assert spec.has_pipeline assert spec.has_dag is False assert isinstance(spec.workflow.strategy.matrix["param1"], MatrixChoiceConfig) assert isinstance(spec.workflow.strategy.matrix["param2"], MatrixChoiceConfig) assert spec.workflow.strategy.matrix["param1"].to_dict() == { "kind": "choice", "value": [1, 2], } assert spec.workflow.strategy.matrix["param2"].to_dict() == { "kind": "choice", "value": [3.3, 4.4], } assert isinstance(spec.workflow, WorkflowConfig) assert spec.concurrency == 2 assert isinstance(spec.workflow_strategy, GridSearchConfig) assert spec.workflow_strategy_kind == GridSearchConfig.IDENTIFIER assert spec.workflow.early_stopping is None assert spec.early_stopping == []
def test_job_file_with_environment_passes(self): plxfile = PolyaxonFile( os.path.abspath("tests/fixtures/plain/job_file_with_environment.yml") ) spec = plxfile.specification spec = spec.apply_context() assert spec.version == 1.0 assert spec.is_component assert isinstance(spec.environment, EnvironmentConfig) assert spec.node_selector == {"polyaxon.com": "core"} assert spec.resources.to_dict() == { "requests": {"cpu": 1, "memory": 200}, "limits": {"cpu": 2, "memory": 200}, } assert spec.affinity == { "nodeAffinity": {"requiredDuringSchedulingIgnoredDuringExecution": {}} } assert spec.tolerations == [{"key": "key", "operator": "Exists"}] assert spec.labels == {"label_key1": "val1", "label_key2": "val2"} assert spec.annotations == { "annotation_key1": "val1", "annotation_key2": "val2", } assert spec.service_account == "new_sa" assert spec.image_pull_secrets == ["secret1", "secret2"] assert spec.env_vars == {"env_var_key1": "val1", "env_var_key2": "val2"} assert spec.security_context == { "runAsUser": 1000, "runAsGroup": 3000, "fsGroup": 5000, } assert spec.log_level == "DEBUG"
def test_matrix_file_passes_int_float_types(self): plxfile = PolyaxonFile( os.path.abspath( "tests/fixtures/plain/matrix_job_file_with_int_float_types.yml" )) spec = plxfile.specification spec = spec.apply_context() assert spec.version == 1.0 assert spec.is_component assert isinstance(spec.parallel, GridSearchConfig) assert isinstance(spec.parallel.matrix["param1"], MatrixChoiceConfig) assert isinstance(spec.parallel.matrix["param2"], MatrixChoiceConfig) assert spec.parallel.matrix["param1"].to_dict() == { "kind": "choice", "value": [1, 2], } assert spec.parallel.matrix["param2"].to_dict() == { "kind": "choice", "value": [3.3, 4.4], } assert spec.parallel.concurrency == 2 assert isinstance(spec.parallel, GridSearchConfig) assert spec.parallel_kind == GridSearchConfig.IDENTIFIER assert spec.parallel.early_stopping is None assert spec.parallel_early_stopping == []
def test_mpi_passes(self): plxfile = PolyaxonFile( os.path.abspath("tests/fixtures/plain/distributed_mpi_file.yml")) spec = plxfile.specification spec = spec.apply_context() assert spec.meta_info.to_dict() == { "service": False, "concurrency": None, "parallel_kind": None, "run_kind": "mpi_job", } assert spec.version == 1.0 assert spec.log_level == "INFO" assert spec.is_component assert spec.config.has_mpi_job_run assert spec.config.run.launcher.replicas == 1 assert spec.config.run.launcher.container.to_dict() == { "image": "mpioperator/tensorflow-benchmarks:latest", "command": ["mpirun", "python", "run.py"], } assert spec.config.run.launcher.termination is None assert spec.config.run.launcher.environment is None assert spec.config.run.worker.replicas == 2 assert spec.config.run.worker.environment.affinity is None assert spec.config.run.worker.environment.node_selector is not None assert isinstance(spec.config.run.worker.environment.tolerations, list) assert spec.config.run.worker.environment.resources.to_dict() == { "limits": { "nvidia.com/gpu": 1 } }
def test_mapping_early_stopping_file_passes(self): plxfile = PolyaxonFile( os.path.abspath( "tests/fixtures/plain/mapping_job_file_early_stopping.yml")) spec = plxfile.specification spec = spec.apply_context() assert spec.meta_info.to_dict() == { "service": False, "concurrency": 2, "parallel_kind": "mapping", "run_kind": "container", } assert spec.version == 1.0 assert spec.is_component assert isinstance(spec.parallel, MappingConfig) assert spec.parallel.values == [ { "lr": 0.001, "loss": "MeanSquaredError" }, { "lr": 0.1, "loss": "AbsoluteDifference" }, ] assert spec.parallel.concurrency == 2 assert isinstance(spec.parallel, MappingConfig) assert spec.parallel_kind == MappingConfig.IDENTIFIER assert spec.parallel_early_stopping == spec.parallel.early_stopping assert len(spec.parallel_early_stopping) == 1 assert isinstance(spec.parallel_early_stopping[0], MetricEarlyStoppingConfig)
def test_job_file_with_init_passes(self): plxfile = PolyaxonFile( os.path.abspath("tests/fixtures/plain/job_file_with_init.yml")) spec = plxfile.specification spec = spec.apply_context() assert spec.version == 1.0 assert spec.is_component assert isinstance(spec.environment, EnvironmentConfig) assert spec.environment.log_level == "INFO" assert isinstance(spec.init, InitConfig) assert spec.auth_context is True assert spec.shm_context is True assert spec.docker_context is True assert spec.outputs is True assert spec.logs is None assert len(spec.artifacts) == 2 assert spec.artifacts[0].to_dict() == { "name": "data1", "paths": ["path1", "path2"], } assert spec.artifacts[1].to_dict() == {"name": "data2"} assert len(spec.secrets) == 1 assert spec.secrets[0].to_dict() == { "name": "my_ssh_secret", "mount_path": "~/.ssh/id_rsa", } assert len(spec.config_maps) == 2 assert spec.config_maps[0].to_dict() == {"name": "config_map1"} assert spec.config_maps[1].to_dict() == { "name": "config_map2", "items": ["item1", "item2"], }
def test_matrix_early_stopping_file_passes(self): plxfile = PolyaxonFile( os.path.abspath( "tests/fixtures/plain/matrix_job_file_early_stopping.yml")) spec = plxfile.specification spec = spec.apply_context() assert spec.version == 0.6 assert spec.is_component assert isinstance(spec.workflow, WorkflowConfig) assert isinstance(spec.workflow.strategy.matrix["lr"], MatrixLinSpaceConfig) assert isinstance(spec.workflow.strategy.matrix["loss"], MatrixChoiceConfig) assert spec.workflow.strategy.matrix["lr"].to_dict() == { "kind": "linspace", "value": { "start": 0.01, "stop": 0.1, "num": 5 }, } assert spec.workflow.strategy.matrix["loss"].to_dict() == { "kind": "choice", "value": ["MeanSquaredError", "AbsoluteDifference"], } assert spec.workflow.concurrency == 2 assert spec.workflow.strategy.n_experiments == 300 assert isinstance(spec.workflow_strategy, RandomSearchConfig) assert spec.workflow_strategy_kind == RandomSearchConfig.IDENTIFIER assert spec.early_stopping == spec.workflow.early_stopping assert len(spec.early_stopping) == 1 assert isinstance(spec.early_stopping[0], MetricEarlyStoppingConfig)
def test_mapping_early_stopping_file_passes(self): plxfile = PolyaxonFile( os.path.abspath( "tests/fixtures/plain/mapping_job_file_early_stopping.yml")) spec = plxfile.specification spec = spec.apply_context() assert spec.version == 0.6 assert spec.is_component assert isinstance(spec.workflow, WorkflowConfig) assert spec.workflow.strategy.values == [ { "lr": 0.001, "loss": "MeanSquaredError" }, { "lr": 0.1, "loss": "AbsoluteDifference" }, ] assert spec.workflow.concurrency == 2 assert isinstance(spec.workflow_strategy, MappingConfig) assert spec.workflow_strategy_kind == MappingConfig.IDENTIFIER assert spec.early_stopping == spec.workflow.early_stopping assert len(spec.early_stopping) == 1 assert isinstance(spec.early_stopping[0], MetricEarlyStoppingConfig)
def test_run_with_refs(self): plxfile = PolyaxonFile( os.path.abspath("tests/fixtures/typing/run_with_refs.yml") ) spec = plxfile.specification params = { "num_masks": 2, "model_path": "{{ runs.64332180bfce46eba80a65caf73c5396.outputs.doo }}", } validated_params = spec.validate_params(params=params) assert { "num_masks": 2, "model_path": "runs.64332180bfce46eba80a65caf73c5396.outputs.doo", } == {p.name: p.value for p in validated_params} ref_param = get_params_with_refs(validated_params)[0] assert ref_param == validated_params[0] assert ref_param.name == "model_path" assert ref_param.entity == "runs" assert ref_param.value == "runs.64332180bfce46eba80a65caf73c5396.outputs.doo" with self.assertRaises(PolyaxonfileError): spec.apply_params(params=params) spec.apply_params( params=params, context={ "runs.64332180bfce46eba80a65caf73c5396.outputs.doo": IOConfig( name="model_path", value="model_path", is_optional=True, iotype="path", ) }, ) params = {"num_masks": 2, "model_path": "{{ ops.A.outputs.doo }}"} validated_params = spec.validate_params(params=params) assert {"num_masks": 2, "model_path": "ops.A.outputs.doo"} == { p.name: p.value for p in validated_params } ref_param = get_params_with_refs(validated_params)[0] assert ref_param == validated_params[0] assert ref_param.name == "model_path" assert ref_param.entity == "ops" assert ref_param.value == "ops.A.outputs.doo" with self.assertRaises(PolyaxonfileError): spec.apply_params(params=params) spec.apply_params( params=params, context={ "ops.A.outputs.doo": IOConfig( name="model_path", value="model_path", is_optional=True, iotype="path", ) }, )
def test_polyaxon_found(self): def create_file(path, filename, ext): fpath = "{}/{}.{}".format(path, filename, ext) open(fpath, "w") for filename in DEFAULT_POLYAXON_FILE_NAME: for ext in DEFAULT_POLYAXON_FILE_EXTENSION: path = tempfile.mkdtemp() create_file(path, filename, ext) assert PolyaxonFile.check_default_path(path=path)
def test_pytorch_passes(self): plxfile = PolyaxonFile( os.path.abspath( "tests/fixtures/plain/distributed_pytorch_file.yml")) spec = plxfile.specification spec = spec.apply_context() assert spec.meta_info.to_dict() == { "service": False, "concurrency": None, "parallel_kind": None, "run_kind": "pytorch_job", } assert spec.version == 1.0 assert spec.log_level == "INFO" assert spec.is_component assert isinstance(spec.environment, EnvironmentConfig) assert spec.environment.node_selector is None assert spec.environment.tolerations is None assert spec.environment.node_selector is None assert isinstance(spec.environment.affinity, dict) assert spec.environment.resources.to_dict() == { "requests": { "cpu": 1 }, "limits": { "cpu": 2 }, } assert spec.config.has_pytorch_job_run assert spec.config.run.master.replicas == 5 assert spec.config.run.master.termination is not None assert spec.config.run.master.termination.restart_policy == "OnFailure" assert spec.config.run.master.environment.resources.to_dict() == { "requests": { "memory": "300Mi" }, "limits": { "memory": "300Mi" }, } assert spec.config.run.worker.replicas == 10 assert spec.config.run.worker.environment.affinity is None assert isinstance(spec.config.run.worker.environment.tolerations, list) assert spec.config.run.worker.environment.resources.to_dict() == { "requests": { "cpu": 3, "memory": "256Mi" }, "limits": { "cpu": 3, "memory": "256Mi" }, }
def test_matrix_file_passes(self): plxfile = PolyaxonFile( os.path.abspath("tests/fixtures/plain/matrix_job_file.yml")) spec = plxfile.specification spec = spec.apply_context() assert spec.version == 0.6 assert spec.is_component assert isinstance(spec.workflow, WorkflowConfig) assert isinstance(spec.workflow.strategy.matrix["lr"], MatrixLinSpaceConfig) assert isinstance(spec.workflow.strategy.matrix["loss"], MatrixChoiceConfig) assert spec.workflow.strategy.matrix["lr"].to_dict() == { "kind": "linspace", "value": { "start": 0.01, "stop": 0.1, "num": 5 }, } assert spec.workflow.strategy.matrix["loss"].to_dict() == { "kind": "choice", "value": ["MeanSquaredError", "AbsoluteDifference"], } assert spec.workflow.strategy.matrix["normal_rate"].to_dict() == { "kind": "normal", "value": { "loc": 0, "scale": 0.9 }, } assert spec.workflow.strategy.matrix["dropout"].to_dict() == { "kind": "qloguniform", "value": { "high": 0.8, "low": 0, "q": 0.1 }, } assert spec.workflow.strategy.matrix["activation"].to_dict() == { "kind": "pchoice", "value": [["relu", 0.1], ["sigmoid", 0.8]], } assert spec.workflow.strategy.matrix["model"].to_dict() == { "kind": "choice", "value": ["CDNA", "DNA", "STP"], } assert spec.workflow.concurrency == 2 assert spec.concurrency == 2 assert isinstance(spec.workflow_strategy, HyperbandConfig) assert spec.workflow_strategy_kind == HyperbandConfig.IDENTIFIER assert spec.workflow.early_stopping is None assert spec.early_stopping == []
def test_pytorch_passes(self): plxfile = PolyaxonFile( os.path.abspath( "tests/fixtures/plain/distributed_pytorch_file.yml")) spec = plxfile.specification spec = spec.apply_context() assert spec.version == 0.6 assert spec.log_level == "INFO" assert spec.is_component assert isinstance(spec.environment, EnvironmentConfig) assert spec.environment.node_selector is None assert spec.environment.tolerations is None assert spec.environment.node_selector is None assert isinstance(spec.environment.affinity, dict) assert spec.environment.resources.to_dict() == { "requests": { "cpu": 1 }, "limits": { "cpu": 2 }, } assert spec.config.workflow.has_pytorch_job_strategy assert spec.config.workflow.strategy.master.replicas == 5 assert spec.config.workflow.strategy.master.termination is not None assert (spec.config.workflow.strategy.master.termination.restart_policy == "OnFailure") assert spec.config.workflow.strategy.master.environment.resources.to_dict( ) == { "requests": { "memory": "300Mi" }, "limits": { "memory": "300Mi" }, } assert spec.config.workflow.strategy.worker.replicas == 10 assert spec.config.workflow.strategy.worker.environment.affinity is None assert isinstance( spec.config.workflow.strategy.worker.environment.tolerations, list) assert spec.config.workflow.strategy.worker.environment.resources.to_dict( ) == { "requests": { "cpu": 3, "memory": "256Mi" }, "limits": { "cpu": 3, "memory": "256Mi" }, }
def test_build_run_pipeline(self): plx_file = PolyaxonFile( os.path.abspath("tests/fixtures/pipelines/build_run_pipeline.yml")) spec = plx_file.specification spec = spec.apply_context() assert len(spec.workflow_strategy.ops) == 2 assert spec.workflow_strategy.ops[0].name == "build" assert spec.workflow_strategy.ops[1].name == "run" assert spec.config.workflow is not None assert spec.has_dag is True assert spec.has_pipeline is True assert spec.config.schedule is None assert len(spec.workflow_strategy.components) == 2 assert spec.workflow_strategy.components[ 0].name == "experiment-template" assert spec.workflow_strategy.components[0].container.to_dict() == { "image": "{{ image }}", "command": ["python3", "main.py"], "args": "--lr={{ lr }}", } assert spec.workflow_strategy.components[1].name == "build-template" assert spec.workflow_strategy.components[1].container.to_light_dict( ) == { "image": "base" } assert spec.workflow_strategy.components[1].init.build.to_light_dict( ) == { "image": "base", "env": "{{ env_vars }}", "name": POLYAXON_DOCKERFILE_NAME, "workdir": POLYAXON_DOCKER_WORKDIR, "shell": POLYAXON_DOCKER_SHELL, } # Create a an op spec spec.workflow_strategy.set_op_component("run") assert spec.workflow_strategy.ops[1].component is not None job_spec = OpSpecification(spec.workflow_strategy.ops[1].to_dict()) assert job_spec.config.params == { "image": "{{ ops.build.outputs.docker-image }}", "lr": 0.001, } op_spec = get_specification(job_spec.generate_run_data()) assert op_spec.is_component is True op_spec.apply_params({"image": "foo", "lr": 0.001}) op_spec = op_spec.apply_context() op_spec = op_spec.apply_container_contexts() assert op_spec.config.container.to_dict() == { "image": "foo", "command": ["python3", "main.py"], "args": "--lr=0.001", }
def test_job_file_with_termination_passes(self): plxfile = PolyaxonFile( os.path.abspath( "tests/fixtures/plain/job_file_with_termination.yml")) spec = plxfile.specification spec = spec.apply_context() assert spec.version == 1.0 assert spec.is_component assert isinstance(spec.termination, TerminationConfig) assert spec.max_retries == 5 assert spec.timeout == 500 assert spec.restart_policy == "never" assert spec.ttl == 400
def test_cyclic_pipeline_raises(self): plx_file = PolyaxonFile( os.path.abspath("tests/fixtures/pipelines/cyclic_pipeline.yml")) assert plx_file.specification.has_dag_run is True assert plx_file.specification.has_pipeline is True assert plx_file.specification.meta_info.to_dict() == { "service": False, "concurrency": None, "run_kind": "dag", "parallel_kind": None, } with self.assertRaises(PolyaxonSchemaError): plx_file.specification.apply_context()
def test_required_inputs_with_params(self): plxfile = PolyaxonFile( os.path.abspath("tests/fixtures/typing/required_inputs.yml")) spec = plxfile.specification with self.assertRaises(PolyaxonfileError): spec.apply_context() assert spec.config.inputs[0].value is None assert spec.config.inputs[1].value is None spec.apply_params(params={"loss": "bar", "flag": False}) assert spec.config.inputs[0].value == "bar" assert spec.config.inputs[1].value is False spec = spec.apply_context() spec = spec.apply_container_contexts() assert spec.version == 0.6 assert spec.tags == ["foo", "bar"] assert spec.container.image == "my_image" assert spec.container.command == ["/bin/sh", "-c"] assert spec.container.args == "video_prediction_train --loss=bar " assert spec.environment is None assert spec.is_component plxfile = PolyaxonFile( os.path.abspath("tests/fixtures/typing/required_inputs.yml")) spec = plxfile.specification assert spec.config.inputs[0].value is None assert spec.config.inputs[1].value is None spec.apply_params(params={"loss": "bar", "flag": True}) assert spec.config.inputs[0].value == "bar" assert spec.config.inputs[1].value is True spec = spec.apply_context() spec = spec.apply_container_contexts() assert spec.version == 0.6 assert spec.tags == ["foo", "bar"] assert spec.container.image == "my_image" assert spec.container.command == ["/bin/sh", "-c"] assert spec.container.args == "video_prediction_train --loss=bar --flag" assert spec.environment is None assert spec.is_component # Adding extra value raises with self.assertRaises(PolyaxonfileError): spec.validate_params(params={ "loss": "bar", "flag": True, "value": 1.1 }) with self.assertRaises(PolyaxonfileError): polyaxonfile = PolyaxonFile( os.path.abspath("tests/fixtures/typing/required_inputs.yml")) polyaxonfile.get_op_specification(params={ "loss": "bar", "value": 1.1 }) # Adding non valid params raises with self.assertRaises(PolyaxonfileError): spec.validate_params(params={"value": 1.1})