-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update SemanticModel node to match DSI 0.1.0dev3 protocols (#7848)
* Add tests to ensure our semantic layer nodes satisfy the DSI protocols These tests create runtime checkable versions of the protocols defined in DSI. Thus we can instantiate instances of our semantic layer nodes and use `isinstance` to check that they satisfy the protocol. These `runtime_checkable` versions of the protocols should only exist in testing and should never be used in the actual package code. * Update the `Dimension` object of `SemanticModel` node to match DSI protocol * Make `UnparsedDimension` more strict and update schema readers accordingly * Update the `Entity` object of `SemanticModel` node to match DSI protocol * Make `UnparsedEntity` more strict and update schema readers accordingly * Update the `Measure` object of `SemanticModel` node to match DSI protocol * Make `UnparsedMeasure` more strict and update schema readers accordingly * Update the `SemanticModel` node to match DSI protocol A lot of the additions are helper functions which we don't actually use in core. This is a known issue. We're in the process of removing a fair number of them from the DSI protocol spec. However, in the meantime we need to implement them to satisfy the protocol unfortunately. * Make `UnparsedSemanticModel` more strict and update schema readers accordingly * Changie entry for updating SemanticModel node
- Loading branch information
Showing
7 changed files
with
472 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
kind: Fixes | ||
body: Update SemanticModel node to properly impelment the DSI 0.1.0dev3 SemanticModel | ||
protocol spec | ||
time: 2023-06-12T17:58:54.289704-07:00 | ||
custom: | ||
Author: QMalcolm | ||
Issue: 7833 7827 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
from dataclasses import dataclass | ||
from dbt.dataclass_schema import dbtClassMixin | ||
from dbt_semantic_interfaces.references import ( | ||
DimensionReference, | ||
EntityReference, | ||
MeasureReference, | ||
TimeDimensionReference, | ||
) | ||
from dbt_semantic_interfaces.type_enums.aggregation_type import AggregationType | ||
from dbt_semantic_interfaces.type_enums.dimension_type import DimensionType | ||
from dbt_semantic_interfaces.type_enums.entity_type import EntityType | ||
from dbt_semantic_interfaces.type_enums.time_granularity import TimeGranularity | ||
from typing import List, Optional | ||
|
||
|
||
@dataclass | ||
class FileSlice(dbtClassMixin): | ||
"""Provides file slice level context about what something was created from. | ||
Implementation of the dbt-semantic-interfaces `FileSlice` protocol | ||
""" | ||
|
||
filename: str | ||
content: str | ||
start_line_number: int | ||
end_line_number: int | ||
|
||
|
||
@dataclass | ||
class SourceFileMetadata(dbtClassMixin): | ||
"""Provides file context about what something was created from. | ||
Implementation of the dbt-semantic-interfaces `Metadata` protocol | ||
""" | ||
|
||
repo_file_path: str | ||
file_slice: FileSlice | ||
|
||
|
||
@dataclass | ||
class Defaults(dbtClassMixin): | ||
agg_time_dimension: Optional[str] = None | ||
|
||
|
||
# ==================================== | ||
# Dimension objects | ||
# ==================================== | ||
|
||
|
||
@dataclass | ||
class DimensionValidityParams(dbtClassMixin): | ||
is_start: bool = False | ||
is_end: bool = False | ||
|
||
|
||
@dataclass | ||
class DimensionTypeParams(dbtClassMixin): | ||
time_granularity: TimeGranularity | ||
validity_params: Optional[DimensionValidityParams] = None | ||
|
||
|
||
@dataclass | ||
class Dimension(dbtClassMixin): | ||
name: str | ||
type: DimensionType | ||
description: Optional[str] = None | ||
is_partition: bool = False | ||
type_params: Optional[DimensionTypeParams] = None | ||
expr: Optional[str] = None | ||
metadata: Optional[SourceFileMetadata] = None | ||
|
||
@property | ||
def reference(self) -> DimensionReference: | ||
return DimensionReference(element_name=self.name) | ||
|
||
@property | ||
def time_dimension_reference(self) -> Optional[TimeDimensionReference]: | ||
if self.type == DimensionType.TIME: | ||
return TimeDimensionReference(element_name=self.name) | ||
else: | ||
return None | ||
|
||
@property | ||
def validity_params(self) -> Optional[DimensionValidityParams]: | ||
if self.type_params: | ||
return self.type_params.validity_params | ||
else: | ||
return None | ||
|
||
|
||
# ==================================== | ||
# Entity objects | ||
# ==================================== | ||
|
||
|
||
@dataclass | ||
class Entity(dbtClassMixin): | ||
name: str | ||
type: EntityType | ||
description: Optional[str] = None | ||
role: Optional[str] = None | ||
expr: Optional[str] = None | ||
|
||
@property | ||
def reference(self) -> EntityReference: | ||
return EntityReference(element_name=self.name) | ||
|
||
@property | ||
def is_linkable_entity_type(self) -> bool: | ||
return self.type in (EntityType.PRIMARY, EntityType.UNIQUE, EntityType.NATURAL) | ||
|
||
|
||
# ==================================== | ||
# Measure objects | ||
# ==================================== | ||
|
||
|
||
@dataclass | ||
class MeasureAggregationParameters(dbtClassMixin): | ||
percentile: Optional[float] = None | ||
use_discrete_percentile: Optional[bool] = None | ||
use_approximate_percentile: Optional[bool] = None | ||
|
||
|
||
@dataclass | ||
class NonAdditiveDimension(dbtClassMixin): | ||
name: str | ||
window_choice: AggregationType | ||
window_grouples: List[str] | ||
|
||
|
||
@dataclass | ||
class Measure(dbtClassMixin): | ||
name: str | ||
agg: AggregationType | ||
description: Optional[str] = None | ||
create_metric: bool = False | ||
expr: Optional[str] = None | ||
agg_params: Optional[MeasureAggregationParameters] = None | ||
non_additive_dimension: Optional[NonAdditiveDimension] = None | ||
agg_time_dimension: Optional[str] = None | ||
|
||
@property | ||
def checked_agg_time_dimension(self) -> TimeDimensionReference: | ||
if self.agg_time_dimension is not None: | ||
return TimeDimensionReference(element_name=self.agg_time_dimension) | ||
else: | ||
raise Exception("Measure is missing agg_time_dimension!") | ||
|
||
@property | ||
def reference(self) -> MeasureReference: | ||
return MeasureReference(element_name=self.name) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.