diff --git a/.changes/unreleased/Fixes-20241010-142329.yaml b/.changes/unreleased/Fixes-20241010-142329.yaml new file mode 100644 index 00000000..ba0c12ab --- /dev/null +++ b/.changes/unreleased/Fixes-20241010-142329.yaml @@ -0,0 +1,6 @@ +kind: Fixes +body: Fix time spine validation error +time: 2024-10-10T14:23:29.392029-05:00 +custom: + Author: DevonFulcher + Issue: None diff --git a/README.md b/README.md index a69004f1..7a0ee649 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ # dbt-semantic-interfaces -This repo contains the shared semantic classes, default validation, and tests designed to be used by both the dbt-core and MetricFlow projects. By centralizing these shared resources, we aim to maintain consistency and reduce code duplication across both projects. +This repo contains the shared semantic classes, default validation, and tests designed to be used by both the dbt-core and MetricFlow projects. By centralizing these shared resources, we aim to maintain consistency and reduce code duplication across both projects. ## Features - Protocols for shared semantic classes: Define the interfaces and common attributes that must be implemented by the objects in both projects. diff --git a/dbt_semantic_interfaces/validations/time_spines.py b/dbt_semantic_interfaces/validations/time_spines.py index 002affe3..9531df1d 100644 --- a/dbt_semantic_interfaces/validations/time_spines.py +++ b/dbt_semantic_interfaces/validations/time_spines.py @@ -28,10 +28,14 @@ def validate_manifest(semantic_manifest: SemanticManifestT) -> Sequence[Validati if not semantic_manifest.semantic_models: return issues + time_spines = semantic_manifest.project_configuration.time_spines + if not time_spines: + return issues + # Verify that there is only one time spine per granularity time_spines_by_granularity: Dict[TimeGranularity, List[TimeSpine]] = {} granularities_with_multiple_time_spines: Set[TimeGranularity] = set() - for time_spine in semantic_manifest.project_configuration.time_spines: + for time_spine in time_spines: granularity = time_spine.primary_column.time_granularity if granularity in time_spines_by_granularity: time_spines_by_granularity[granularity].append(time_spine) diff --git a/tests/validations/test_time_spines.py b/tests/validations/test_time_spines.py index 70beba35..20cadc88 100644 --- a/tests/validations/test_time_spines.py +++ b/tests/validations/test_time_spines.py @@ -127,6 +127,42 @@ def test_no_warning_for_legacy_time_spine() -> None: # noqa: D assert len(issues.warnings) == 0 +def test_no_time_spine_config() -> None: # noqa: D + validator = SemanticManifestValidator[PydanticSemanticManifest]() + semantic_manifest = PydanticSemanticManifest( + semantic_models=[ + semantic_model_with_guaranteed_meta( + name="sum_measure", + dimensions=[ + PydanticDimension( + name="dim", + type=DimensionType.TIME, + description="", + metadata=None, + type_params=PydanticDimensionTypeParams(time_granularity=TimeGranularity.SECOND), + ) + ], + entities=[PydanticEntity(name="entity", type=EntityType.PRIMARY)], + ), + ], + metrics=[ + PydanticMetric( + name="metric", + description=None, + type=MetricType.SIMPLE, + type_params=PydanticMetricTypeParams(measure=PydanticMetricInputMeasure(name="sum_measure")), + ), + ], + project_configuration=PydanticProjectConfiguration( + time_spine_table_configurations=[], + time_spines=[], + ), + ) + issues = validator.validate_semantic_manifest(semantic_manifest) + assert not issues.has_blocking_issues + assert len(issues.warnings) == 0 + + def test_duplicate_time_spine_granularity() -> None: # noqa: D validator = SemanticManifestValidator[PydanticSemanticManifest]() semantic_manifest = PydanticSemanticManifest(