Skip to content

Commit 6ed313d

Browse files
authored
fix(config): stringify pydantic error loc before join (#5884)
Signed-off-by: Anas Khan <83116240+anxkhn@users.noreply.github.com>
1 parent b43743a commit 6ed313d

3 files changed

Lines changed: 25 additions & 3 deletions

File tree

sqlmesh/utils/pydantic.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ def _formatted_validation_errors(error: pydantic.ValidationError) -> t.List[str]
242242
for e in error.errors():
243243
msg = e["msg"]
244244
loc: t.Optional[t.Tuple] = e.get("loc")
245-
loc_str = ".".join(loc) if loc else None
245+
loc_str = ".".join(str(p) for p in loc) if loc else None
246246
result.append(f"Invalid field '{loc_str}':\n {msg}" if loc_str else msg)
247247
return result
248248

tests/core/test_config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,7 @@ def test_load_model_defaults_validation_statements(tmp_path):
702702
"""
703703
)
704704

705-
with pytest.raises(TypeError, match=r"expected str instance, int found"):
705+
with pytest.raises(ConfigError, match=r"Invalid field 'model_defaults\.pre_statements\.0"):
706706
config = load_config_from_paths(
707707
Config,
708708
project_paths=[config_path],

tests/utils/test_pydantic.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,14 @@
22
import pytest
33
from functools import cached_property
44

5+
import pydantic
6+
57
from sqlmesh.utils.date import TimeLike, to_date, to_datetime
6-
from sqlmesh.utils.pydantic import PydanticModel, get_concrete_types_from_typehint
8+
from sqlmesh.utils.pydantic import (
9+
PydanticModel,
10+
get_concrete_types_from_typehint,
11+
validation_error_message,
12+
)
713

814

915
def test_datetime_date_serialization() -> None:
@@ -87,3 +93,19 @@ class TestModel(PydanticModel):
8793
)
8894
def test_get_concrete_types_from_typehint(input: t.Any, output: set[type]) -> None:
8995
assert get_concrete_types_from_typehint(input) == output
96+
97+
98+
def test_validation_error_message_with_list_index_location() -> None:
99+
class Inner(PydanticModel):
100+
x: int
101+
102+
class Outer(PydanticModel):
103+
items: t.List[Inner]
104+
105+
with pytest.raises(pydantic.ValidationError) as ex:
106+
Outer(items=[{"x": "not_an_int"}])
107+
108+
# The error is located at a list index, so pydantic's loc mixes str field
109+
# names with an int sequence index (e.g. ("items", 0, "x")).
110+
message = validation_error_message(ex.value, "Invalid config:")
111+
assert "Invalid field 'items.0.x'" in message

0 commit comments

Comments
 (0)