Skip to content

Commit d3496fd

Browse files
authored
fix(datatypes): give a more useful error message when trying to cast structs with different fields (#10214)
1 parent dfe7c34 commit d3496fd

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

ibis/expr/datatypes/cast.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ def castable(source: dt.DataType, target: dt.DataType, value: Any = None) -> boo
116116
)
117117
elif target.is_struct():
118118
return source.is_struct() and all(
119-
castable(source[field], target[field]) for field in target.names
119+
field in source and castable(source[field], target[field])
120+
for field in target.names
120121
)
121122
elif target.is_geospatial():
122123
return source.is_geospatial() or source.is_array()

ibis/expr/datatypes/tests/test_cast.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,21 @@ def test_implicitly_castable_int_to_bool(value):
101101
)
102102
def test_implicitly_uncastable_values(source, target, value):
103103
assert not source.castable(target, value=value)
104+
105+
106+
def test_struct_different_fields():
107+
x = dt.Struct({"x": dt.int32})
108+
x2 = dt.Struct({"x": dt.int64})
109+
y = dt.Struct({"y": dt.int32})
110+
xy = dt.Struct({"x": dt.int32, "y": dt.int32})
111+
112+
# Can upcast int32 to int64, but not other way
113+
assert x.castable(x2)
114+
assert not x2.castable(x)
115+
# Can remove a field, but not add one
116+
assert xy.castable(x)
117+
assert not x.castable(xy)
118+
119+
# Missing fields entirely from each other
120+
assert not x.castable(y)
121+
assert not y.castable(x)

0 commit comments

Comments
 (0)