Skip to content
Open
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
2 changes: 1 addition & 1 deletion sqlmesh/utils/pydantic.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ def _formatted_validation_errors(error: pydantic.ValidationError) -> t.List[str]
for e in error.errors():
msg = e["msg"]
loc: t.Optional[t.Tuple] = e.get("loc")
loc_str = ".".join(loc) if loc else None
loc_str = ".".join(str(p) for p in loc) if loc else None
result.append(f"Invalid field '{loc_str}':\n {msg}" if loc_str else msg)
return result

Expand Down
2 changes: 1 addition & 1 deletion tests/core/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,7 @@ def test_load_model_defaults_validation_statements(tmp_path):
"""
)

with pytest.raises(TypeError, match=r"expected str instance, int found"):
with pytest.raises(ConfigError, match=r"Invalid field 'model_defaults\.pre_statements\.0"):
config = load_config_from_paths(
Config,
project_paths=[config_path],
Expand Down
24 changes: 23 additions & 1 deletion tests/utils/test_pydantic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@
import pytest
from functools import cached_property

import pydantic

from sqlmesh.utils.date import TimeLike, to_date, to_datetime
from sqlmesh.utils.pydantic import PydanticModel, get_concrete_types_from_typehint
from sqlmesh.utils.pydantic import (
PydanticModel,
get_concrete_types_from_typehint,
validation_error_message,
)


def test_datetime_date_serialization() -> None:
Expand Down Expand Up @@ -87,3 +93,19 @@ class TestModel(PydanticModel):
)
def test_get_concrete_types_from_typehint(input: t.Any, output: set[type]) -> None:
assert get_concrete_types_from_typehint(input) == output


def test_validation_error_message_with_list_index_location() -> None:
class Inner(PydanticModel):
x: int

class Outer(PydanticModel):
items: t.List[Inner]

with pytest.raises(pydantic.ValidationError) as ex:
Outer(items=[{"x": "not_an_int"}])

# The error is located at a list index, so pydantic's loc mixes str field
# names with an int sequence index (e.g. ("items", 0, "x")).
message = validation_error_message(ex.value, "Invalid config:")
assert "Invalid field 'items.0.x'" in message
Loading