From a53ba6dc1e215d88f4b316cf191a6c10390b0244 Mon Sep 17 00:00:00 2001 From: GnanasundaramSampath Date: Fri, 22 May 2026 17:48:32 +0530 Subject: [PATCH 1/4] update for fix schema validation --- .../azure/ai/ml/_schema/schedule/schedule.py | 16 +++++++++------- .../schedule/unittests/test_schedule_schema.py | 11 +++++++++++ ...ron_schedule_with_pipeline_file_not_found.yml | 8 ++++++++ 3 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 sdk/ml/azure-ai-ml/tests/test_configs/schedule/invalid/hello_cron_schedule_with_pipeline_file_not_found.yml diff --git a/sdk/ml/azure-ai-ml/azure/ai/ml/_schema/schedule/schedule.py b/sdk/ml/azure-ai-ml/azure/ai/ml/_schema/schedule/schedule.py index fbde3e9b2cea..efa1a7dceca6 100644 --- a/sdk/ml/azure-ai-ml/azure/ai/ml/_schema/schedule/schedule.py +++ b/sdk/ml/azure-ai-ml/azure/ai/ml/_schema/schedule/schedule.py @@ -4,7 +4,7 @@ from marshmallow import fields -from azure.ai.ml._schema.core.fields import ArmStr, NestedField, UnionField +from azure.ai.ml._schema.core.fields import ArmStr, NestedField, TypeSensitiveUnionField, UnionField from azure.ai.ml._schema.core.resource import ResourceSchema from azure.ai.ml._schema.job import CreationContextSchema from azure.ai.ml._schema.schedule.create_job import ( @@ -33,12 +33,14 @@ class ScheduleSchema(ResourceSchema): class JobScheduleSchema(ScheduleSchema): - create_job = UnionField( - [ + create_job = TypeSensitiveUnionField( + { + "pipeline": [NestedField(PipelineCreateJobSchema)], + "command": [NestedField(CommandCreateJobSchema)], + "spark": [NestedField(SparkCreateJobSchema)], + }, + plain_union_fields=[ ArmStr(azureml_type=AzureMLResourceType.JOB), CreateJobFileRefField, - NestedField(PipelineCreateJobSchema), - NestedField(CommandCreateJobSchema), - NestedField(SparkCreateJobSchema), - ] + ], ) diff --git a/sdk/ml/azure-ai-ml/tests/schedule/unittests/test_schedule_schema.py b/sdk/ml/azure-ai-ml/tests/schedule/unittests/test_schedule_schema.py index 2bf677c8503a..43f89e26cb62 100644 --- a/sdk/ml/azure-ai-ml/tests/schedule/unittests/test_schedule_schema.py +++ b/sdk/ml/azure-ai-ml/tests/schedule/unittests/test_schedule_schema.py @@ -157,3 +157,14 @@ def test_load_invalid_schedule_missing_type(self): with pytest.raises(ValidationError) as e: load_schedule(test_path) assert "'type' must be specified when scheduling a remote job with updates." in e.value.messages[0] + + def test_load_invalid_schedule_pipeline_file_not_found_error_simplified(self): + test_path = "./tests/test_configs/schedule/invalid/hello_cron_schedule_with_pipeline_file_not_found.yml" + with pytest.raises(ValidationError) as e: + load_schedule(test_path) + + error_message = str(e.value.messages) + assert "No such file or directory" in error_message + assert "Not supporting non file for create_job" not in error_message + assert "Value 'pipeline' passed is not in set ['command']" not in error_message + assert "Value 'pipeline' passed is not in set ['spark']" not in error_message diff --git a/sdk/ml/azure-ai-ml/tests/test_configs/schedule/invalid/hello_cron_schedule_with_pipeline_file_not_found.yml b/sdk/ml/azure-ai-ml/tests/test_configs/schedule/invalid/hello_cron_schedule_with_pipeline_file_not_found.yml new file mode 100644 index 000000000000..e1d2b746e617 --- /dev/null +++ b/sdk/ml/azure-ai-ml/tests/test_configs/schedule/invalid/hello_cron_schedule_with_pipeline_file_not_found.yml @@ -0,0 +1,8 @@ +$schema: https://azuremlschemas.azureedge.net/latest/schedule.schema.json +name: weekly_retrain_2022_cron_pipeline_file_not_found +trigger: + type: cron + expression: "15 10 * * 1" +create_job: + type: pipeline + job: ../pipeline.yml From d70ca11ff714fb7578e056b7c1d960fcce8085b3 Mon Sep 17 00:00:00 2001 From: GnanasundaramSampath Date: Mon, 25 May 2026 11:25:33 +0530 Subject: [PATCH 2/4] remove new yaml file --- .../unittests/test_schedule_schema.py | 20 ++++++++++++++++--- ..._schedule_with_pipeline_file_not_found.yml | 8 -------- 2 files changed, 17 insertions(+), 11 deletions(-) delete mode 100644 sdk/ml/azure-ai-ml/tests/test_configs/schedule/invalid/hello_cron_schedule_with_pipeline_file_not_found.yml diff --git a/sdk/ml/azure-ai-ml/tests/schedule/unittests/test_schedule_schema.py b/sdk/ml/azure-ai-ml/tests/schedule/unittests/test_schedule_schema.py index 43f89e26cb62..3c3fe56bc6d7 100644 --- a/sdk/ml/azure-ai-ml/tests/schedule/unittests/test_schedule_schema.py +++ b/sdk/ml/azure-ai-ml/tests/schedule/unittests/test_schedule_schema.py @@ -158,10 +158,24 @@ def test_load_invalid_schedule_missing_type(self): load_schedule(test_path) assert "'type' must be specified when scheduling a remote job with updates." in e.value.messages[0] - def test_load_invalid_schedule_pipeline_file_not_found_error_simplified(self): - test_path = "./tests/test_configs/schedule/invalid/hello_cron_schedule_with_pipeline_file_not_found.yml" + def test_load_invalid_schedule_pipeline_file_not_found_error_simplified(self, tmp_path): + test_path = tmp_path / "invalid_pipeline_schedule.yml" + test_path.write_text( + """ +$schema: https://azuremlschemas.azureedge.net/latest/schedule.schema.json +name: weekly_retrain_2022_cron_pipeline_file_not_found +trigger: + type: cron + expression: "15 10 * * 1" +create_job: + type: pipeline + job: ../pipeline.yml +""".strip(), + encoding="utf-8", + ) + with pytest.raises(ValidationError) as e: - load_schedule(test_path) + load_schedule(str(test_path)) error_message = str(e.value.messages) assert "No such file or directory" in error_message diff --git a/sdk/ml/azure-ai-ml/tests/test_configs/schedule/invalid/hello_cron_schedule_with_pipeline_file_not_found.yml b/sdk/ml/azure-ai-ml/tests/test_configs/schedule/invalid/hello_cron_schedule_with_pipeline_file_not_found.yml deleted file mode 100644 index e1d2b746e617..000000000000 --- a/sdk/ml/azure-ai-ml/tests/test_configs/schedule/invalid/hello_cron_schedule_with_pipeline_file_not_found.yml +++ /dev/null @@ -1,8 +0,0 @@ -$schema: https://azuremlschemas.azureedge.net/latest/schedule.schema.json -name: weekly_retrain_2022_cron_pipeline_file_not_found -trigger: - type: cron - expression: "15 10 * * 1" -create_job: - type: pipeline - job: ../pipeline.yml From 39157819c38102d88be2b064d76c4eefafb71c89 Mon Sep 17 00:00:00 2001 From: GnanasundaramSampath Date: Mon, 25 May 2026 12:07:53 +0530 Subject: [PATCH 3/4] update for build test issues fixing --- .../azure-ai-ml/azure/ai/ml/_schema/schedule/schedule.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sdk/ml/azure-ai-ml/azure/ai/ml/_schema/schedule/schedule.py b/sdk/ml/azure-ai-ml/azure/ai/ml/_schema/schedule/schedule.py index efa1a7dceca6..a7a764662741 100644 --- a/sdk/ml/azure-ai-ml/azure/ai/ml/_schema/schedule/schedule.py +++ b/sdk/ml/azure-ai-ml/azure/ai/ml/_schema/schedule/schedule.py @@ -32,8 +32,14 @@ class ScheduleSchema(ResourceSchema): properties = fields.Dict(keys=fields.Str(), values=fields.Str(allow_none=True)) +class ScheduleCreateJobField(TypeSensitiveUnionField): + # Keep legacy dump behavior so full scheduled jobs continue to serialize via CreateJobFileRefField. + def _serialize(self, value, attr, obj, **kwargs): + return UnionField._serialize(self, value, attr, obj, **kwargs) + + class JobScheduleSchema(ScheduleSchema): - create_job = TypeSensitiveUnionField( + create_job = ScheduleCreateJobField( { "pipeline": [NestedField(PipelineCreateJobSchema)], "command": [NestedField(CommandCreateJobSchema)], From 4ff2d2e6b5b628b431e86f5a8c66db48dafbf935 Mon Sep 17 00:00:00 2001 From: GnanasundaramSampath Date: Mon, 25 May 2026 14:07:09 +0530 Subject: [PATCH 4/4] update for fix build analyze errors --- sdk/ml/azure-ai-ml/azure/ai/ml/_schema/schedule/schedule.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/ml/azure-ai-ml/azure/ai/ml/_schema/schedule/schedule.py b/sdk/ml/azure-ai-ml/azure/ai/ml/_schema/schedule/schedule.py index a7a764662741..13c0592306ab 100644 --- a/sdk/ml/azure-ai-ml/azure/ai/ml/_schema/schedule/schedule.py +++ b/sdk/ml/azure-ai-ml/azure/ai/ml/_schema/schedule/schedule.py @@ -35,7 +35,7 @@ class ScheduleSchema(ResourceSchema): class ScheduleCreateJobField(TypeSensitiveUnionField): # Keep legacy dump behavior so full scheduled jobs continue to serialize via CreateJobFileRefField. def _serialize(self, value, attr, obj, **kwargs): - return UnionField._serialize(self, value, attr, obj, **kwargs) + return super(TypeSensitiveUnionField, self)._serialize(value, attr, obj, **kwargs) class JobScheduleSchema(ScheduleSchema):