From 7a4920d97795cce945beb9b310d66caca09ad450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?JB=20Onofr=C3=A9?= Date: Fri, 18 Sep 2026 06:29:55 +0200 Subject: [PATCH] Fix Sigma and NVIDIA GSF converters for flat semantic model documents PR #383 moved the Ossie document schema to one semantic model directly at the document root (dropping the `semantic_model:` wrapper), and #407 fixed the Microsoft converter for it, but the Sigma and NVIDIA GSF converters were never updated, so their CI failed on main as soon as an unrelated change touched their paths and re-triggered it. The Sigma, dbt, and wisdom converters share the `ossie` Python package's OssieDocument/OssieSemanticModel pydantic models, so fixing OssieDocument to match the flat schema required updating all three converters (and their tests/snapshots) together to keep them internally consistent. NVIDIA GSF parses Ossie YAML directly against a dict shape and is fixed independently. Co-Authored-By: Claude Sonnet 5 --- converters/dbt/tests/test_msi_to_ossie.py | 2 +- converters/sigma/src/ossie_sigma/ossie_to_sigma.py | 3 +-- converters/sigma/tests/test_ossie_to_sigma.py | 8 ++++---- converters/sigma/tests/test_roundtrip.py | 11 +++++++---- converters/wisdom/tests/test_ossie_to_wisdom.py | 4 ++-- python/src/ossie/models.py | 2 +- 6 files changed, 16 insertions(+), 14 deletions(-) diff --git a/converters/dbt/tests/test_msi_to_ossie.py b/converters/dbt/tests/test_msi_to_ossie.py index 7ed0aa89..418cff0a 100644 --- a/converters/dbt/tests/test_msi_to_ossie.py +++ b/converters/dbt/tests/test_msi_to_ossie.py @@ -75,7 +75,7 @@ def _field_expr(result: OssieDocument, field_idx: int = 0) -> str: def _ossie_metrics(result: OssieDocument) -> list: - """Return Ossie metrics for the first semantic model, asserting they exist.""" + """Return the document's Ossie metrics, asserting they exist.""" metrics = result.metrics assert metrics is not None return metrics diff --git a/converters/sigma/src/ossie_sigma/ossie_to_sigma.py b/converters/sigma/src/ossie_sigma/ossie_to_sigma.py index 3753aa70..abde620d 100644 --- a/converters/sigma/src/ossie_sigma/ossie_to_sigma.py +++ b/converters/sigma/src/ossie_sigma/ossie_to_sigma.py @@ -30,7 +30,6 @@ OssieField, OssieMetric, OssieRelationship, - OssieSemanticModel, OssieVendor, ) @@ -40,7 +39,7 @@ from ossie_sigma.spec_keys import MODEL_LEVEL_SPEC_KEYS # Objects a `SIGMA` custom_extensions vendor entry can be attached to. -_SigmaExtensionHost = Union[OssieDataset, OssieField, OssieMetric, OssieRelationship, OssieSemanticModel] +_SigmaExtensionHost = Union[OssieDataset, OssieField, OssieMetric, OssieRelationship, OssieDocument] _ID_NAMESPACE = uuid5(NAMESPACE_URL, "ossie.apache.org/converters/sigma") diff --git a/converters/sigma/tests/test_ossie_to_sigma.py b/converters/sigma/tests/test_ossie_to_sigma.py index da6ff383..20e1800a 100644 --- a/converters/sigma/tests/test_ossie_to_sigma.py +++ b/converters/sigma/tests/test_ossie_to_sigma.py @@ -17,6 +17,7 @@ from pathlib import Path +import pytest import yaml from ossie import ( OssieDataset, @@ -28,7 +29,6 @@ OssieMetric, ) -import pytest from ossie import OssieRelationship from pydantic import ValidationError @@ -121,7 +121,7 @@ def test_relationship_ids_are_scoped_by_owning_dataset(): OssieRelationship( name="Parent", **{"from": "shipments"}, to="carriers", from_columns=["x"], to_columns=["y"] ), - ] + ], ) spec = OssieToSigmaConverter().convert(document).output @@ -205,7 +205,7 @@ def test_untranslatable_expression_omits_the_column_instead_of_faking_a_formula( ] ), ) - ] + ], ) result = OssieToSigmaConverter().convert(document) @@ -259,7 +259,7 @@ def test_datatypes_only_ever_emit_the_two_documented_format_kinds(): ) ], ) - ] + ], ) columns = OssieToSigmaConverter().convert(document).output["pages"][0]["elements"][0]["columns"] diff --git a/converters/sigma/tests/test_roundtrip.py b/converters/sigma/tests/test_roundtrip.py index 6c03251d..4e5a0905 100644 --- a/converters/sigma/tests/test_roundtrip.py +++ b/converters/sigma/tests/test_roundtrip.py @@ -61,11 +61,14 @@ def test_osi_sigma_osi_roundtrip_preserves_portable_fields(fixture_name): document_2 = SigmaToOssieConverter().convert(spec_2).output def portable(document): - model = document return { - "datasets": [(d.name, d.source, [(f.name, f.datatype) for f in d.fields or []]) for d in model.datasets], - "relationships": [(r.name, r.from_dataset, r.to, r.from_columns, r.to_columns) for r in model.relationships or []], - "metrics": [(m.name,) for m in model.metrics or []], + "datasets": [ + (d.name, d.source, [(f.name, f.datatype) for f in d.fields or []]) for d in document.datasets + ], + "relationships": [ + (r.name, r.from_dataset, r.to, r.from_columns, r.to_columns) for r in document.relationships or [] + ], + "metrics": [(m.name,) for m in document.metrics or []], } assert portable(document_1) == portable(document_2) diff --git a/converters/wisdom/tests/test_ossie_to_wisdom.py b/converters/wisdom/tests/test_ossie_to_wisdom.py index f89f5413..bfee1bad 100644 --- a/converters/wisdom/tests/test_ossie_to_wisdom.py +++ b/converters/wisdom/tests/test_ossie_to_wisdom.py @@ -190,7 +190,7 @@ def test_one_to_one_note_restores_relationship_type(): to_columns=["id"], ai_context="one-to-one relationship", ) - ] + ], ) export = OssieToWisdomConverter().convert(document, exported_at="2026-07-10T00:00:00+00:00").output edges = export["domain"]["zsheet_json"]["relationshipGraph"]["relationships"] @@ -203,7 +203,7 @@ def test_unresolved_metric_attaches_to_first_dataset(): document = OssieDocument( name="m", datasets=[OssieDataset(name="a", source="db.s.a"), OssieDataset(name="b", source="db.s.b")], - metrics=[OssieMetric(name="row_count", expression=_snowflake("COUNT(*)"))] + metrics=[OssieMetric(name="row_count", expression=_snowflake("COUNT(*)"))], ) result = OssieToWisdomConverter().convert(document, exported_at="2026-07-10T00:00:00+00:00") export = result.output diff --git a/python/src/ossie/models.py b/python/src/ossie/models.py index a1825557..9a00b44b 100644 --- a/python/src/ossie/models.py +++ b/python/src/ossie/models.py @@ -194,7 +194,7 @@ class OssieMetric(BaseModel): class OssieSemanticModel(BaseModel): - """Top-level container representing a complete semantic model.""" + """Semantic model: the datasets, relationships, and metrics for one business domain.""" model_config = ConfigDict(frozen=True)