diff --git a/src/boring_semantic_layer/serialization/extract.py b/src/boring_semantic_layer/serialization/extract.py index 8d547dd..52c9f49 100644 --- a/src/boring_semantic_layer/serialization/extract.py +++ b/src/boring_semantic_layer/serialization/extract.py @@ -101,6 +101,8 @@ def _extract_semantic_table(op, context: BSLSerializationContext) -> dict[str, A metadata["calc_measures"] = calc_data if op.name: metadata["name"] = op.name + if op.description: + metadata["description"] = op.description return metadata diff --git a/src/boring_semantic_layer/serialization/reconstruct.py b/src/boring_semantic_layer/serialization/reconstruct.py index 782e500..8e0e271 100644 --- a/src/boring_semantic_layer/serialization/reconstruct.py +++ b/src/boring_semantic_layer/serialization/reconstruct.py @@ -141,6 +141,7 @@ def _reconstruct_table(): measures=measures, calc_measures=calc_measures, name=metadata.get("name"), + description=metadata.get("description"), ) diff --git a/src/boring_semantic_layer/tests/test_xorq_convert.py b/src/boring_semantic_layer/tests/test_xorq_convert.py index 642175f..0917e2e 100644 --- a/src/boring_semantic_layer/tests/test_xorq_convert.py +++ b/src/boring_semantic_layer/tests/test_xorq_convert.py @@ -167,6 +167,30 @@ def test_to_xorq_returns_xorq_expr(): assert hasattr(tagged_expr, "op") +@pytest.mark.skipif(not xorq, reason="xorq not available") +def test_descriptions_roundtrip_to_tagged_from_tagged(): + """Model, dimension, and measure descriptions survive to_tagged → from_tagged.""" + import ibis + + from boring_semantic_layer import SemanticModel + from boring_semantic_layer.ops import Dimension, Measure + + table = ibis.memtable({"a": [1, 2, 3], "b": [4, 5, 6]}) + model = SemanticModel( + table=table, + dimensions={"a": Dimension(expr=lambda t: t.a, description="The A dim")}, + measures={"sum_b": Measure(expr=lambda t: t.b.sum(), description="Sum of B")}, + name="m", + description="Top-level model description", + ) + + restored = from_tagged(to_tagged(model)) + + assert restored.description == "Top-level model description" + assert restored.get_dimensions()["a"].description == "The A dim" + assert restored.get_measures()["sum_b"].description == "Sum of B" + + @pytest.mark.skipif(not xorq, reason="xorq not available") def test_from_xorq_returns_bsl_expr(): from xorq.api import memtable