From 3fd9bd8b925602b9213af9ec5add5cda94ee0635 Mon Sep 17 00:00:00 2001 From: Phillip Cloud <417981+cpcloud@users.noreply.github.com> Date: Sun, 3 Jul 2022 14:58:11 -0500 Subject: [PATCH] feat(api): make struct metadata more convenient to access --- ibis/expr/types/structs.py | 19 ++++++++++++++++++- ibis/tests/expr/test_value_exprs.py | 20 ++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/ibis/expr/types/structs.py b/ibis/expr/types/structs.py index b2ac054387ec..c711e405fe5c 100644 --- a/ibis/expr/types/structs.py +++ b/ibis/expr/types/structs.py @@ -2,10 +2,12 @@ import collections import itertools -from typing import TYPE_CHECKING, Iterable, Mapping +from typing import TYPE_CHECKING, Iterable, Mapping, Sequence +from cached_property import cached_property from public import public +from ibis import util from ibis.expr.types.generic import Column, Scalar, Value, literal from ibis.expr.types.typing import V @@ -78,6 +80,21 @@ def __getitem__(self, name: str) -> ir.Value: return ops.StructField(self, name).to_expr().name(name) + @cached_property + def names(self) -> Sequence[str]: + """Return the field names of the struct.""" + return self.type().names + + @cached_property + def types(self) -> Sequence[dt.DataType]: + """Return the field types of the struct.""" + return self.type().types + + @cached_property + def fields(self) -> Mapping[str, dt.DataType]: + """Return a mapping from field name to field type of the struct.""" + return util.frozendict(self.type().pairs) + def destructure(self) -> DestructValue: """Destructure `self` into a `DestructValue`. diff --git a/ibis/tests/expr/test_value_exprs.py b/ibis/tests/expr/test_value_exprs.py index 8faa0bcdbb8d..0becdd2cb1e6 100644 --- a/ibis/tests/expr/test_value_exprs.py +++ b/ibis/tests/expr/test_value_exprs.py @@ -1524,3 +1524,23 @@ def test_non_null_with_null_precedence(expr_fn, expected_type): t = ibis.table(dict(a="int64", b="!string"), name="t") expr = expr_fn(t) assert expr.type() == expected_type + + +@pytest.mark.parametrize( + ("name", "expected"), + [ + ("names", ("a", "b", "c")), + ("types", (dt.int8, dt.string, dt.Array(dt.Array(dt.float64)))), + ( + "fields", + ibis.util.frozendict( + a=dt.int8, + b=dt.string, + c=dt.Array(dt.Array(dt.float64)), + ), + ), + ], +) +def test_struct_names_types_fields(name, expected): + s = ibis.struct(dict(a=1, b="2", c=[[1.0], [], [None]])) + assert getattr(s, name) == expected