Skip to content

Commit f258b58

Browse files
authored
Expose meta for Metric and SemanticModel (#250)
Resolves #251 <!--- Include the number of the issue addressed by this PR above if applicable. PRs for code changes without an associated issue *will not be merged*. See CONTRIBUTING.md for more information. --> ### Description This PR exposes the `meta` field for Metric and SemanticModel which enables it to be parsed out in the semantic manifest for use in the SL APIs <!--- Describe the Pull Request here. Add any references and info to help reviewers understand your changes. Include any tradeoffs you considered. --> ### Checklist - [x] I have read [the contributing guide](https://github.com/dbt-labs/dbt-semantic-interfaces/blob/main/CONTRIBUTING.md) and understand what's expected of me - [x] I have signed the [CLA](https://docs.getdbt.com/docs/contributor-license-agreements) - [x] This PR includes tests, or tests are not required/relevant for this PR - [x] I have run `changie new` to [create a changelog entry](https://github.com/dbt-labs/dbt-semantic-interfaces/blob/main/CONTRIBUTING.md#adding-a-changelog-entry)
1 parent cc2d6d6 commit f258b58

File tree

11 files changed

+127
-5
lines changed

11 files changed

+127
-5
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
kind: Features
2+
body: Expose meta on Metric/SemanticModel
3+
time: 2024-01-20T00:03:29.80055-05:00
4+
custom:
5+
Author: WilliamDee
6+
Issue: "251"

dbt_semantic_interfaces/implementations/metric.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from __future__ import annotations
22

3-
from typing import List, Optional, Sequence
3+
from typing import Any, Dict, List, Optional, Sequence
4+
5+
from typing_extensions import override
46

57
from dbt_semantic_interfaces.enum_extension import assert_values_exhausted
68
from dbt_semantic_interfaces.errors import ParsingException
@@ -14,6 +16,7 @@
1416
PydanticWhereFilterIntersection,
1517
)
1618
from dbt_semantic_interfaces.implementations.metadata import PydanticMetadata
19+
from dbt_semantic_interfaces.protocols import MetricConfig, ProtocolHint
1720
from dbt_semantic_interfaces.references import MeasureReference, MetricReference
1821
from dbt_semantic_interfaces.type_enums import (
1922
ConversionCalculationType,
@@ -170,6 +173,14 @@ class PydanticMetricTypeParams(HashableBaseModel):
170173
input_measures: List[PydanticMetricInputMeasure] = Field(default_factory=list)
171174

172175

176+
class PydanticMetricConfig(HashableBaseModel, ProtocolHint[MetricConfig]): # noqa: D
177+
@override
178+
def _implements_protocol(self) -> MetricConfig: # noqa: D
179+
return self
180+
181+
meta: Dict[str, Any] = Field(default_factory=dict)
182+
183+
173184
class PydanticMetric(HashableBaseModel, ModelWithMetadataParsing):
174185
"""Describes a metric."""
175186

@@ -180,6 +191,7 @@ class PydanticMetric(HashableBaseModel, ModelWithMetadataParsing):
180191
filter: Optional[PydanticWhereFilterIntersection]
181192
metadata: Optional[PydanticMetadata]
182193
label: Optional[str] = None
194+
config: Optional[PydanticMetricConfig]
183195

184196
@property
185197
def input_measures(self) -> Sequence[PydanticMetricInputMeasure]:

dbt_semantic_interfaces/implementations/semantic_model.py

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from __future__ import annotations
22

3-
from typing import Any, List, Optional, Sequence
3+
from typing import Any, Dict, List, Optional, Sequence
44

55
from typing_extensions import override
66

@@ -15,6 +15,7 @@
1515
from dbt_semantic_interfaces.protocols import (
1616
ProtocolHint,
1717
SemanticModel,
18+
SemanticModelConfig,
1819
SemanticModelDefaults,
1920
)
2021
from dbt_semantic_interfaces.references import (
@@ -24,7 +25,7 @@
2425
SemanticModelReference,
2526
TimeDimensionReference,
2627
)
27-
from dsi_pydantic_shim import validator
28+
from dsi_pydantic_shim import Field, validator
2829

2930

3031
class NodeRelation(HashableBaseModel):
@@ -76,6 +77,14 @@ def _implements_protocol(self) -> SemanticModelDefaults: # noqa: D
7677
agg_time_dimension: Optional[str]
7778

7879

80+
class PydanticSemanticModelConfig(HashableBaseModel, ProtocolHint[SemanticModelConfig]): # noqa: D
81+
@override
82+
def _implements_protocol(self) -> SemanticModelConfig: # noqa: D
83+
return self
84+
85+
meta: Dict[str, Any] = Field(default_factory=dict)
86+
87+
7988
class PydanticSemanticModel(HashableBaseModel, ModelWithMetadataParsing, ProtocolHint[SemanticModel]):
8089
"""Describes a semantic model."""
8190

@@ -95,6 +104,7 @@ def _implements_protocol(self) -> SemanticModel:
95104
label: Optional[str] = None
96105

97106
metadata: Optional[PydanticMetadata]
107+
config: Optional[PydanticSemanticModelConfig]
98108

99109
@property
100110
def entity_references(self) -> List[LinkableElementReference]: # noqa: D

dbt_semantic_interfaces/parsing/generated_json_schemas/default_explicit_schema.json

+32
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,19 @@
328328
],
329329
"type": "object"
330330
},
331+
"metric_config_schema": {
332+
"$id": "metric_config_schema",
333+
"additionalProperties": false,
334+
"properties": {
335+
"meta": {
336+
"propertyNames": {
337+
"type": "string"
338+
},
339+
"type": "object"
340+
}
341+
},
342+
"type": "object"
343+
},
331344
"metric_input_measure_schema": {
332345
"$id": "metric_input_measure_schema",
333346
"oneOf": [
@@ -383,6 +396,9 @@
383396
"$id": "metric_schema",
384397
"additionalProperties": false,
385398
"properties": {
399+
"config": {
400+
"$ref": "#/definitions/metric_config_schema"
401+
},
386402
"description": {
387403
"type": "string"
388404
},
@@ -578,6 +594,19 @@
578594
],
579595
"type": "object"
580596
},
597+
"semantic_model_config_schema": {
598+
"$id": "semantic_model_config_schema",
599+
"additionalProperties": false,
600+
"properties": {
601+
"meta": {
602+
"propertyNames": {
603+
"type": "string"
604+
},
605+
"type": "object"
606+
}
607+
},
608+
"type": "object"
609+
},
581610
"semantic_model_defaults_schema": {
582611
"$id": "semantic_model_defaults_schema",
583612
"additionalProperties": false,
@@ -593,6 +622,9 @@
593622
"$id": "semantic_model_schema",
594623
"additionalProperties": false,
595624
"properties": {
625+
"config": {
626+
"$ref": "#/definitions/semantic_model_config_schema"
627+
},
596628
"defaults": {
597629
"$ref": "#/definitions/semantic_model_defaults_schema"
598630
},

dbt_semantic_interfaces/parsing/schemas.py

+22
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,15 @@
252252
"required": ["name", "type"],
253253
}
254254

255+
metric_config_schema = {
256+
"$id": "metric_config_schema",
257+
"type": "object",
258+
"properties": {
259+
"meta": {"type": "object", "propertyNames": {"type": "string"}},
260+
},
261+
"additionalProperties": False,
262+
}
263+
255264
# Top level object schemas
256265
metric_schema = {
257266
"$id": "metric_schema",
@@ -266,6 +275,7 @@
266275
"filter": {"$ref": "filter_schema"},
267276
"description": {"type": "string"},
268277
"label": {"type": "string"},
278+
"config": {"$ref": "metric_config_schema"},
269279
},
270280
"additionalProperties": False,
271281
"required": ["name", "type", "type_params"],
@@ -378,6 +388,15 @@
378388
"additionalProperties": False,
379389
}
380390

391+
semantic_model_config_schema = {
392+
"$id": "semantic_model_config_schema",
393+
"type": "object",
394+
"properties": {
395+
"meta": {"type": "object", "propertyNames": {"type": "string"}},
396+
},
397+
"additionalProperties": False,
398+
}
399+
381400
semantic_model_schema = {
382401
"$id": "semantic_model_schema",
383402
"type": "object",
@@ -396,6 +415,7 @@
396415
"dimensions": {"type": "array", "items": {"$ref": "dimension_schema"}},
397416
"description": {"type": "string"},
398417
"label": {"type": "string"},
418+
"config": {"$ref": "semantic_model_config_schema"},
399419
},
400420
"additionalProperties": False,
401421
"required": ["name"],
@@ -428,6 +448,8 @@
428448
export_schema["$id"]: export_schema,
429449
export_config_schema["$id"]: export_config_schema,
430450
saved_query_query_params_schema["$id"]: saved_query_query_params_schema,
451+
semantic_model_config_schema["$id"]: semantic_model_config_schema,
452+
metric_config_schema["$id"]: metric_config_schema,
431453
}
432454

433455
resources: List[Tuple[str, Resource]] = [(str(k), DRAFT7.create_resource(v)) for k, v in schema_store.items()]

dbt_semantic_interfaces/protocols/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
ConstantPropertyInput,
1515
ConversionTypeParams,
1616
Metric,
17+
MetricConfig,
1718
MetricInput,
1819
MetricInputMeasure,
1920
MetricTimeWindow,
@@ -27,6 +28,7 @@
2728
)
2829
from dbt_semantic_interfaces.protocols.semantic_model import ( # noqa:F401
2930
SemanticModel,
31+
SemanticModelConfig,
3032
SemanticModelDefaults,
3133
SemanticModelT,
3234
)

dbt_semantic_interfaces/protocols/metric.py

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22

33
from abc import abstractmethod
4-
from typing import Optional, Protocol, Sequence
4+
from typing import Any, Dict, Optional, Protocol, Sequence
55

66
from dbt_semantic_interfaces.protocols.metadata import Metadata
77
from dbt_semantic_interfaces.protocols.where_filter import WhereFilterIntersection
@@ -228,6 +228,16 @@ def conversion_type_params(self) -> Optional[ConversionTypeParams]: # noqa: D
228228
pass
229229

230230

231+
class MetricConfig(Protocol): # noqa: D
232+
"""The config property allows you to configure additional resources/metadata."""
233+
234+
@property
235+
@abstractmethod
236+
def meta(self) -> Dict[str, Any]:
237+
"""The meta field can be used to set metadata for a resource."""
238+
pass
239+
240+
231241
class Metric(Protocol):
232242
"""Describes a metric."""
233243

@@ -280,6 +290,11 @@ def input_metrics(self) -> Sequence[MetricInput]:
280290
def metadata(self) -> Optional[Metadata]: # noqa: D
281291
pass
282292

293+
@property
294+
@abstractmethod
295+
def config(self) -> Optional[MetricConfig]: # noqa: D
296+
pass
297+
283298
@property
284299
@abstractmethod
285300
def label(self) -> Optional[str]:

dbt_semantic_interfaces/protocols/semantic_model.py

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22

33
from abc import abstractmethod
4-
from typing import Optional, Protocol, Sequence, TypeVar
4+
from typing import Any, Dict, Optional, Protocol, Sequence, TypeVar
55

66
from dbt_semantic_interfaces.protocols.dimension import Dimension
77
from dbt_semantic_interfaces.protocols.entity import Entity
@@ -50,6 +50,16 @@ def agg_time_dimension(self) -> Optional[str]:
5050
pass
5151

5252

53+
class SemanticModelConfig(Protocol): # noqa: D
54+
"""The config property allows you to configure additional resources/metadata."""
55+
56+
@property
57+
@abstractmethod
58+
def meta(self) -> Dict[str, Any]:
59+
"""The meta field can be used to set metadata for a resource."""
60+
pass
61+
62+
5363
class SemanticModel(Protocol):
5464
"""Describes a semantic model."""
5565

@@ -159,6 +169,11 @@ def reference(self) -> SemanticModelReference:
159169
def metadata(self) -> Optional[Metadata]: # noqa: D
160170
pass
161171

172+
@property
173+
@abstractmethod
174+
def config(self) -> Optional[SemanticModelConfig]: # noqa: D
175+
pass
176+
162177
@abstractmethod
163178
def checked_agg_time_dimension_for_measure(self, measure_reference: MeasureReference) -> TimeDimensionReference:
164179
"""Returns the `TimeDimensionReference` what a measure should use for it's `agg_time_dimension`.

tests/parsing/test_metric_parsing.py

+3
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ def test_base_metric_parsing() -> None:
9191
type: {metric_type.value}
9292
description: {description}
9393
label: {label}
94+
config:
95+
meta:
96+
random: metadata
9497
type_params:
9598
measure:
9699
name: metadata_test_measure

tests/parsing/test_semantic_model_parsing.py

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ def test_base_semantic_model_parsing() -> None:
2828
node_relation:
2929
alias: source_table
3030
schema_name: some_schema
31+
config:
32+
meta:
33+
test_metadata: random
3134
"""
3235
)
3336
file = YamlConfigFile(filepath="test_dir/inline_for_test", contents=yaml_contents)

tests/test_implements_satisfy_protocols.py

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from dbt_semantic_interfaces.implementations.metric import (
2323
PydanticConversionTypeParams,
2424
PydanticMetric,
25+
PydanticMetricConfig,
2526
PydanticMetricInput,
2627
PydanticMetricInputMeasure,
2728
PydanticMetricTypeParams,
@@ -117,6 +118,7 @@
117118
filter=builds(PydanticWhereFilter) | none(),
118119
metadata=OPTIONAL_METADATA_STRATEGY,
119120
label=OPTIONAL_STR_STRATEGY,
121+
config=builds(PydanticMetricConfig),
120122
)
121123

122124
SAVED_QUERY_STRATEGY = builds(

0 commit comments

Comments
 (0)