Skip to content

Commit

Permalink
test: check that empty structs are disallowed
Browse files Browse the repository at this point in the history
See #9310 for a discussion of whether
empty structs should be allowed or disallowed.
We settled on disallowing them for now,
since pyarrow is like the only backend to support them,
and it is definitely easier to change our mind and allow them later rather than
disallow them later.

Perhaps if you stay in ibis-land, emptry structs are useful ie for doing type manipulations, or maybe you
only use them for intermediate calculations?
But until we see this concrete use case, don't worry about it.
  • Loading branch information
NickCrews committed Jun 29, 2024
1 parent b150635 commit fd3303e
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 3 deletions.
12 changes: 11 additions & 1 deletion ibis/expr/datatypes/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -831,13 +831,23 @@ def _pretty_piece(self) -> str:

@public
class Struct(Parametric, MapSet):
"""Structured values."""
"""A nested type with ordered fields of any type, analogous to a dataclass in Python.
eg a Struct might have a field a of type int64 and a field b of type string.
"""

fields: FrozenOrderedDict[str, DataType]

scalar = "StructScalar"
column = "StructColumn"

def __init__(self, fields, nullable=True):
# We could do this validation in a type annotation, but I thought this
# was common enough to warrant a nicer error message.
if not fields:
raise TypeError("Structs require at least one field")

Check warning on line 848 in ibis/expr/datatypes/core.py

View check run for this annotation

Codecov / codecov/patch

ibis/expr/datatypes/core.py#L848

Added line #L848 was not covered by tests
super().__init__(fields=fields, nullable=nullable)

@classmethod
def from_tuples(
cls, pairs: Iterable[tuple[str, str | DataType]], nullable: bool = True
Expand Down
2 changes: 0 additions & 2 deletions ibis/expr/datatypes/value.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ def infer(value: Any) -> dt.DataType:
@infer.register(collections.OrderedDict)
def infer_struct(value: Mapping[str, Any]) -> dt.Struct:
"""Infer the [`Struct`](./datatypes.qmd#ibis.expr.datatypes.Struct) type of `value`."""
if not value:
raise TypeError("Empty struct type not supported")
fields = {name: infer(val) for name, val in value.items()}
return dt.Struct(fields)

Expand Down
7 changes: 7 additions & 0 deletions ibis/tests/expr/test_struct.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ def s():
return ibis.table(dict(a="struct<f: float, g: string>"), name="s")


@pytest.mark.parametrize("val", [{}, []])
@pytest.mark.parametrize("typ", [None, "struct<>"])
def test_struct_factory_empty(val, typ):
with pytest.raises(TypeError):
ibis.struct(val, type=typ)

Check warning on line 29 in ibis/tests/expr/test_struct.py

View check run for this annotation

Codecov / codecov/patch

ibis/tests/expr/test_struct.py#L29

Added line #L29 was not covered by tests


def test_struct_operations():
value = OrderedDict(
[
Expand Down

0 comments on commit fd3303e

Please sign in to comment.