Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions sdk/ml/azure-ai-ml/azure/ai/ml/_schema/core/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@

module_logger = logging.getLogger(__name__)
T = typing.TypeVar("T")
NO_SUCH_FILE_OR_DIRECTORY_ERROR = "No such file or directory"


class StringTransformedEnum(Field):
Expand Down Expand Up @@ -369,7 +370,10 @@ def _deserialize(self, value, attr, data, **kwargs):
if not path.is_absolute():
path = base_path / path
path.resolve()
data = load_file(path)
try:
data = load_file(path)
except (FileNotFoundError, OSError) as e:
raise ValidationError(f"{NO_SUCH_FILE_OR_DIRECTORY_ERROR}: {path}") from e
return data
raise ValidationError(f"Not supporting non file for {attr}")

Expand Down Expand Up @@ -451,6 +455,16 @@ def union_fields(self):
def insert_union_field(self, field):
self._union_fields.insert(0, field)

@staticmethod
def _contains_file_not_found_error(error_message):
if isinstance(error_message, str):
return NO_SUCH_FILE_OR_DIRECTORY_ERROR in error_message
if isinstance(error_message, dict):
return any(UnionField._contains_file_not_found_error(value) for value in error_message.values())
if isinstance(error_message, list):
return any(UnionField._contains_file_not_found_error(value) for value in error_message)
return False

# This sets the parent for the schema and also handles nesting.
def _bind_to_schema(self, field_name, schema):
super()._bind_to_schema(field_name, schema)
Expand Down Expand Up @@ -484,7 +498,10 @@ def _deserialize(self, value, attr, data, **kwargs):
try:
return schema.deserialize(value, attr, data, **kwargs)
except ValidationError as e:
errors.append(e.normalized_messages())
normalized_messages = e.normalized_messages()
if self._contains_file_not_found_error(normalized_messages):
raise ValidationError(normalized_messages, field_name=attr) from e
errors.append(normalized_messages)
except ValidationException as e:
# ValidationException is explicitly raised in project code so usually easy to locate with error message
errors.append([str(e)])
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from datetime import datetime

import pytest
from marshmallow import ValidationError
from test_utilities.utils import verify_entity_load_and_dump

from azure.ai.ml._schema.core.fields import NO_SUCH_FILE_OR_DIRECTORY_ERROR
from azure.ai.ml.constants import TimeZone
from azure.ai.ml.entities import CronTrigger, JobSchedule, PipelineJob, RecurrencePattern, RecurrenceTrigger
from azure.ai.ml.entities._load_functions import load_job, load_schedule
Expand Down Expand Up @@ -189,3 +191,15 @@ def test_schedule_create_out_of_box_monitoring_job(self):
test_path = "./tests/test_configs/schedule/out_of_box_monitoring.yaml"
schedule = load_schedule(test_path)
assert "genai_app_monitoring", schedule.name

def test_load_schedule_with_nonexistent_pipeline_file_reference(self):
test_path = "./tests/test_configs/schedule/hello_cron_schedule_with_file_reference.yml"
params_override = [{"create_job.job": "../pipeline_jobs/not_exists_pipeline.yml"}]

with pytest.raises(ValidationError) as e:
load_schedule(test_path, params_override=params_override)

message = str(e.value)
assert NO_SUCH_FILE_OR_DIRECTORY_ERROR in message
assert message.count(NO_SUCH_FILE_OR_DIRECTORY_ERROR) == 1
assert "Not supporting non file for create_job" not in message
Loading