Skip to content

Commit

Permalink
fix(datatypes): give a more useful error message when trying to cast …
Browse files Browse the repository at this point in the history
…structs with different fields (#10214)
  • Loading branch information
NickCrews authored Sep 25, 2024
1 parent dfe7c34 commit d3496fd
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 1 deletion.
3 changes: 2 additions & 1 deletion ibis/expr/datatypes/cast.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ def castable(source: dt.DataType, target: dt.DataType, value: Any = None) -> boo
)
elif target.is_struct():
return source.is_struct() and all(
castable(source[field], target[field]) for field in target.names
field in source and castable(source[field], target[field])
for field in target.names
)
elif target.is_geospatial():
return source.is_geospatial() or source.is_array()
Expand Down
18 changes: 18 additions & 0 deletions ibis/expr/datatypes/tests/test_cast.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,21 @@ def test_implicitly_castable_int_to_bool(value):
)
def test_implicitly_uncastable_values(source, target, value):
assert not source.castable(target, value=value)


def test_struct_different_fields():
x = dt.Struct({"x": dt.int32})
x2 = dt.Struct({"x": dt.int64})
y = dt.Struct({"y": dt.int32})
xy = dt.Struct({"x": dt.int32, "y": dt.int32})

# Can upcast int32 to int64, but not other way
assert x.castable(x2)
assert not x2.castable(x)
# Can remove a field, but not add one
assert xy.castable(x)
assert not x.castable(xy)

# Missing fields entirely from each other
assert not x.castable(y)
assert not y.castable(x)

0 comments on commit d3496fd

Please sign in to comment.