Skip to content

Commit

Permalink
Expose meta for Metric and SemanticModel (#250)
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
WilliamDee authored Mar 11, 2024
1 parent cc2d6d6 commit f258b58
Show file tree
Hide file tree
Showing 11 changed files with 127 additions and 5 deletions.
6 changes: 6 additions & 0 deletions .changes/unreleased/Features-20240120-000329.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: Features
body: Expose meta on Metric/SemanticModel
time: 2024-01-20T00:03:29.80055-05:00
custom:
Author: WilliamDee
Issue: "251"
14 changes: 13 additions & 1 deletion dbt_semantic_interfaces/implementations/metric.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from __future__ import annotations

from typing import List, Optional, Sequence
from typing import Any, Dict, List, Optional, Sequence

from typing_extensions import override

from dbt_semantic_interfaces.enum_extension import assert_values_exhausted
from dbt_semantic_interfaces.errors import ParsingException
Expand All @@ -14,6 +16,7 @@
PydanticWhereFilterIntersection,
)
from dbt_semantic_interfaces.implementations.metadata import PydanticMetadata
from dbt_semantic_interfaces.protocols import MetricConfig, ProtocolHint
from dbt_semantic_interfaces.references import MeasureReference, MetricReference
from dbt_semantic_interfaces.type_enums import (
ConversionCalculationType,
Expand Down Expand Up @@ -170,6 +173,14 @@ class PydanticMetricTypeParams(HashableBaseModel):
input_measures: List[PydanticMetricInputMeasure] = Field(default_factory=list)


class PydanticMetricConfig(HashableBaseModel, ProtocolHint[MetricConfig]): # noqa: D
@override
def _implements_protocol(self) -> MetricConfig: # noqa: D
return self

meta: Dict[str, Any] = Field(default_factory=dict)


class PydanticMetric(HashableBaseModel, ModelWithMetadataParsing):
"""Describes a metric."""

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

@property
def input_measures(self) -> Sequence[PydanticMetricInputMeasure]:
Expand Down
14 changes: 12 additions & 2 deletions dbt_semantic_interfaces/implementations/semantic_model.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from typing import Any, List, Optional, Sequence
from typing import Any, Dict, List, Optional, Sequence

from typing_extensions import override

Expand All @@ -15,6 +15,7 @@
from dbt_semantic_interfaces.protocols import (
ProtocolHint,
SemanticModel,
SemanticModelConfig,
SemanticModelDefaults,
)
from dbt_semantic_interfaces.references import (
Expand All @@ -24,7 +25,7 @@
SemanticModelReference,
TimeDimensionReference,
)
from dsi_pydantic_shim import validator
from dsi_pydantic_shim import Field, validator


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


class PydanticSemanticModelConfig(HashableBaseModel, ProtocolHint[SemanticModelConfig]): # noqa: D
@override
def _implements_protocol(self) -> SemanticModelConfig: # noqa: D
return self

meta: Dict[str, Any] = Field(default_factory=dict)


class PydanticSemanticModel(HashableBaseModel, ModelWithMetadataParsing, ProtocolHint[SemanticModel]):
"""Describes a semantic model."""

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

metadata: Optional[PydanticMetadata]
config: Optional[PydanticSemanticModelConfig]

@property
def entity_references(self) -> List[LinkableElementReference]: # noqa: D
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,19 @@
],
"type": "object"
},
"metric_config_schema": {
"$id": "metric_config_schema",
"additionalProperties": false,
"properties": {
"meta": {
"propertyNames": {
"type": "string"
},
"type": "object"
}
},
"type": "object"
},
"metric_input_measure_schema": {
"$id": "metric_input_measure_schema",
"oneOf": [
Expand Down Expand Up @@ -383,6 +396,9 @@
"$id": "metric_schema",
"additionalProperties": false,
"properties": {
"config": {
"$ref": "#/definitions/metric_config_schema"
},
"description": {
"type": "string"
},
Expand Down Expand Up @@ -578,6 +594,19 @@
],
"type": "object"
},
"semantic_model_config_schema": {
"$id": "semantic_model_config_schema",
"additionalProperties": false,
"properties": {
"meta": {
"propertyNames": {
"type": "string"
},
"type": "object"
}
},
"type": "object"
},
"semantic_model_defaults_schema": {
"$id": "semantic_model_defaults_schema",
"additionalProperties": false,
Expand All @@ -593,6 +622,9 @@
"$id": "semantic_model_schema",
"additionalProperties": false,
"properties": {
"config": {
"$ref": "#/definitions/semantic_model_config_schema"
},
"defaults": {
"$ref": "#/definitions/semantic_model_defaults_schema"
},
Expand Down
22 changes: 22 additions & 0 deletions dbt_semantic_interfaces/parsing/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,15 @@
"required": ["name", "type"],
}

metric_config_schema = {
"$id": "metric_config_schema",
"type": "object",
"properties": {
"meta": {"type": "object", "propertyNames": {"type": "string"}},
},
"additionalProperties": False,
}

# Top level object schemas
metric_schema = {
"$id": "metric_schema",
Expand All @@ -266,6 +275,7 @@
"filter": {"$ref": "filter_schema"},
"description": {"type": "string"},
"label": {"type": "string"},
"config": {"$ref": "metric_config_schema"},
},
"additionalProperties": False,
"required": ["name", "type", "type_params"],
Expand Down Expand Up @@ -378,6 +388,15 @@
"additionalProperties": False,
}

semantic_model_config_schema = {
"$id": "semantic_model_config_schema",
"type": "object",
"properties": {
"meta": {"type": "object", "propertyNames": {"type": "string"}},
},
"additionalProperties": False,
}

semantic_model_schema = {
"$id": "semantic_model_schema",
"type": "object",
Expand All @@ -396,6 +415,7 @@
"dimensions": {"type": "array", "items": {"$ref": "dimension_schema"}},
"description": {"type": "string"},
"label": {"type": "string"},
"config": {"$ref": "semantic_model_config_schema"},
},
"additionalProperties": False,
"required": ["name"],
Expand Down Expand Up @@ -428,6 +448,8 @@
export_schema["$id"]: export_schema,
export_config_schema["$id"]: export_config_schema,
saved_query_query_params_schema["$id"]: saved_query_query_params_schema,
semantic_model_config_schema["$id"]: semantic_model_config_schema,
metric_config_schema["$id"]: metric_config_schema,
}

resources: List[Tuple[str, Resource]] = [(str(k), DRAFT7.create_resource(v)) for k, v in schema_store.items()]
Expand Down
2 changes: 2 additions & 0 deletions dbt_semantic_interfaces/protocols/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
ConstantPropertyInput,
ConversionTypeParams,
Metric,
MetricConfig,
MetricInput,
MetricInputMeasure,
MetricTimeWindow,
Expand All @@ -27,6 +28,7 @@
)
from dbt_semantic_interfaces.protocols.semantic_model import ( # noqa:F401
SemanticModel,
SemanticModelConfig,
SemanticModelDefaults,
SemanticModelT,
)
Expand Down
17 changes: 16 additions & 1 deletion dbt_semantic_interfaces/protocols/metric.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

from abc import abstractmethod
from typing import Optional, Protocol, Sequence
from typing import Any, Dict, Optional, Protocol, Sequence

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


class MetricConfig(Protocol): # noqa: D
"""The config property allows you to configure additional resources/metadata."""

@property
@abstractmethod
def meta(self) -> Dict[str, Any]:
"""The meta field can be used to set metadata for a resource."""
pass


class Metric(Protocol):
"""Describes a metric."""

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

@property
@abstractmethod
def config(self) -> Optional[MetricConfig]: # noqa: D
pass

@property
@abstractmethod
def label(self) -> Optional[str]:
Expand Down
17 changes: 16 additions & 1 deletion dbt_semantic_interfaces/protocols/semantic_model.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

from abc import abstractmethod
from typing import Optional, Protocol, Sequence, TypeVar
from typing import Any, Dict, Optional, Protocol, Sequence, TypeVar

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


class SemanticModelConfig(Protocol): # noqa: D
"""The config property allows you to configure additional resources/metadata."""

@property
@abstractmethod
def meta(self) -> Dict[str, Any]:
"""The meta field can be used to set metadata for a resource."""
pass


class SemanticModel(Protocol):
"""Describes a semantic model."""

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

@property
@abstractmethod
def config(self) -> Optional[SemanticModelConfig]: # noqa: D
pass

@abstractmethod
def checked_agg_time_dimension_for_measure(self, measure_reference: MeasureReference) -> TimeDimensionReference:
"""Returns the `TimeDimensionReference` what a measure should use for it's `agg_time_dimension`.
Expand Down
3 changes: 3 additions & 0 deletions tests/parsing/test_metric_parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ def test_base_metric_parsing() -> None:
type: {metric_type.value}
description: {description}
label: {label}
config:
meta:
random: metadata
type_params:
measure:
name: metadata_test_measure
Expand Down
3 changes: 3 additions & 0 deletions tests/parsing/test_semantic_model_parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ def test_base_semantic_model_parsing() -> None:
node_relation:
alias: source_table
schema_name: some_schema
config:
meta:
test_metadata: random
"""
)
file = YamlConfigFile(filepath="test_dir/inline_for_test", contents=yaml_contents)
Expand Down
2 changes: 2 additions & 0 deletions tests/test_implements_satisfy_protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from dbt_semantic_interfaces.implementations.metric import (
PydanticConversionTypeParams,
PydanticMetric,
PydanticMetricConfig,
PydanticMetricInput,
PydanticMetricInputMeasure,
PydanticMetricTypeParams,
Expand Down Expand Up @@ -117,6 +118,7 @@
filter=builds(PydanticWhereFilter) | none(),
metadata=OPTIONAL_METADATA_STRATEGY,
label=OPTIONAL_STR_STRATEGY,
config=builds(PydanticMetricConfig),
)

SAVED_QUERY_STRATEGY = builds(
Expand Down

0 comments on commit f258b58

Please sign in to comment.