diff --git a/.changes/unreleased/Features-20230914-074429.yaml b/.changes/unreleased/Features-20230914-074429.yaml new file mode 100644 index 00000000000..980f932b99c --- /dev/null +++ b/.changes/unreleased/Features-20230914-074429.yaml @@ -0,0 +1,7 @@ +kind: Features +body: Add support for optional label in semantic_models, measures, dimensions and + entities. +time: 2023-09-14T07:44:29.828199-05:00 +custom: + Author: emmyoop + Issue: "8595" diff --git a/core/dbt/contracts/graph/nodes.py b/core/dbt/contracts/graph/nodes.py index b6e685d985f..761d857524a 100644 --- a/core/dbt/contracts/graph/nodes.py +++ b/core/dbt/contracts/graph/nodes.py @@ -1569,6 +1569,7 @@ class SemanticModel(GraphNode): model: str node_relation: Optional[NodeRelation] description: Optional[str] = None + label: Optional[str] = None defaults: Optional[Defaults] = None entities: Sequence[Entity] = field(default_factory=list) measures: Sequence[Measure] = field(default_factory=list) diff --git a/core/dbt/contracts/graph/semantic_models.py b/core/dbt/contracts/graph/semantic_models.py index 2bb75382c46..bdcf1effbce 100644 --- a/core/dbt/contracts/graph/semantic_models.py +++ b/core/dbt/contracts/graph/semantic_models.py @@ -66,6 +66,7 @@ class Dimension(dbtClassMixin): name: str type: DimensionType description: Optional[str] = None + label: Optional[str] = None is_partition: bool = False type_params: Optional[DimensionTypeParams] = None expr: Optional[str] = None @@ -100,6 +101,7 @@ class Entity(dbtClassMixin): name: str type: EntityType description: Optional[str] = None + label: Optional[str] = None role: Optional[str] = None expr: Optional[str] = None @@ -136,6 +138,7 @@ class Measure(dbtClassMixin): name: str agg: AggregationType description: Optional[str] = None + label: Optional[str] = None create_metric: bool = False expr: Optional[str] = None agg_params: Optional[MeasureAggregationParameters] = None diff --git a/core/dbt/contracts/graph/unparsed.py b/core/dbt/contracts/graph/unparsed.py index dbe0bed9812..887359329d7 100644 --- a/core/dbt/contracts/graph/unparsed.py +++ b/core/dbt/contracts/graph/unparsed.py @@ -663,6 +663,7 @@ class UnparsedEntity(dbtClassMixin): name: str type: str # EntityType enum description: Optional[str] = None + label: Optional[str] = None role: Optional[str] = None expr: Optional[str] = None @@ -679,6 +680,7 @@ class UnparsedMeasure(dbtClassMixin): name: str agg: str # actually an enum description: Optional[str] = None + label: Optional[str] = None expr: Optional[Union[str, bool, int]] = None agg_params: Optional[MeasureAggregationParameters] = None non_additive_dimension: Optional[UnparsedNonAdditiveDimension] = None @@ -697,6 +699,7 @@ class UnparsedDimension(dbtClassMixin): name: str type: str # actually an enum description: Optional[str] = None + label: Optional[str] = None is_partition: bool = False type_params: Optional[UnparsedDimensionTypeParams] = None expr: Optional[str] = None @@ -708,6 +711,7 @@ class UnparsedSemanticModel(dbtClassMixin): model: str # looks like "ref(...)" config: Dict[str, Any] = field(default_factory=dict) description: Optional[str] = None + label: Optional[str] = None defaults: Optional[Defaults] = None entities: List[UnparsedEntity] = field(default_factory=list) measures: List[UnparsedMeasure] = field(default_factory=list) diff --git a/core/dbt/parser/schema_yaml_readers.py b/core/dbt/parser/schema_yaml_readers.py index 032b3a8b99d..e9362102138 100644 --- a/core/dbt/parser/schema_yaml_readers.py +++ b/core/dbt/parser/schema_yaml_readers.py @@ -456,6 +456,7 @@ def _get_dimensions(self, unparsed_dimensions: List[UnparsedDimension]) -> List[ name=unparsed.name, type=DimensionType(unparsed.type), description=unparsed.description, + label=unparsed.label, is_partition=unparsed.is_partition, type_params=self._get_dimension_type_params(unparsed=unparsed.type_params), expr=unparsed.expr, @@ -472,6 +473,7 @@ def _get_entities(self, unparsed_entities: List[UnparsedEntity]) -> List[Entity] name=unparsed.name, type=EntityType(unparsed.type), description=unparsed.description, + label=unparsed.label, role=unparsed.role, expr=unparsed.expr, ) @@ -499,6 +501,7 @@ def _get_measures(self, unparsed_measures: List[UnparsedMeasure]) -> List[Measur name=unparsed.name, agg=AggregationType(unparsed.agg), description=unparsed.description, + label=unparsed.label, expr=str(unparsed.expr) if unparsed.expr is not None else None, agg_params=unparsed.agg_params, non_additive_dimension=self._get_non_additive_dimension( @@ -572,6 +575,7 @@ def parse_semantic_model(self, unparsed: UnparsedSemanticModel): parsed = SemanticModel( description=unparsed.description, + label=unparsed.label, fqn=fqn, model=unparsed.model, name=unparsed.name, diff --git a/tests/functional/semantic_models/fixtures.py b/tests/functional/semantic_models/fixtures.py index 12cb3d9d68b..d19ba42f1a6 100644 --- a/tests/functional/semantic_models/fixtures.py +++ b/tests/functional/semantic_models/fixtures.py @@ -58,23 +58,29 @@ semantic_models: - name: semantic_people + label: "Semantic People" model: ref('people') dimensions: - name: favorite_color + label: "Favorite Color" type: categorical - name: created_at + label: "Created At" type: TIME type_params: time_granularity: day measures: - name: years_tenure + label: "Years Tenure" agg: SUM expr: tenure - name: people + label: "People" agg: count expr: id entities: - name: id + label: "Primary ID" type: primary defaults: agg_time_dimension: created_at @@ -85,6 +91,7 @@ semantic_models: - name: semantic_people + label: "Semantic People" model: ref('people') config: enabled: true @@ -115,6 +122,7 @@ semantic_models: - name: semantic_people + label: "Semantic People" model: ref('people') config: enabled: false diff --git a/tests/unit/test_semantic_layer_nodes_satisfy_protocols.py b/tests/unit/test_semantic_layer_nodes_satisfy_protocols.py index 948540f4805..7325a41da19 100644 --- a/tests/unit/test_semantic_layer_nodes_satisfy_protocols.py +++ b/tests/unit/test_semantic_layer_nodes_satisfy_protocols.py @@ -312,6 +312,7 @@ def test_semantic_model_node_satisfies_protocol_optionals_specified( schema_name="test_schema_name", ), description="test_description", + label="test label", defaults=semantic_model_defaults, metadata=source_file_metadata, primary_entity="test_primary_entity", @@ -334,6 +335,7 @@ def test_dimension_satisfies_protocol_optionals_specified( name="test_dimension", type=DimensionType.TIME, description="test_description", + label="test_label", type_params=dimension_type_params, expr="1", metadata=source_file_metadata, @@ -353,6 +355,7 @@ def test_entity_satisfies_protocol_optionals_specified(): entity = Entity( name="test_entity", description="a test entity", + label="A test entity", type=EntityType.PRIMARY, expr="id", role="a_role", @@ -374,6 +377,7 @@ def test_measure_satisfies_protocol_optionals_specified( measure = Measure( name="test_measure", description="a test measure", + label="A test measure", agg="sum", create_metric=True, expr="amount",