Skip to content

Commit

Permalink
Update MFEngine models to contain attributes from pydantic models (#533)
Browse files Browse the repository at this point in the history
  • Loading branch information
courtneyholcomb authored May 24, 2023
1 parent 8645754 commit dadd45f
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 32 deletions.
5 changes: 5 additions & 0 deletions .changes/unreleased/Under the Hood-20230523-180725.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
kind: Under the Hood
time: 2023-05-23T18:07:25.654887-07:00
custom:
Author: courtneyholcomb
Issue: "0"
46 changes: 26 additions & 20 deletions metricflow/engine/metricflow_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

import pandas as pd

from dbt_semantic_interfaces.references import MetricReference
from dbt_semantic_interfaces.references import MetricReference, DimensionReference
from dbt_semantic_interfaces.objects.elements.dimension import Dimension
from metricflow.configuration.constants import (
CONFIG_DBT_CLOUD_JOB_ID,
CONFIG_DBT_CLOUD_SERVICE_TOKEN,
Expand All @@ -26,7 +27,7 @@
from metricflow.dataflow.sql_table import SqlTable
from metricflow.dataset.convert_semantic_model import SemanticModelToDataSetConverter
from metricflow.dataset.semantic_model_adapter import SemanticModelDataSet
from metricflow.engine.models import Dimension, Metric
from metricflow.engine.models import Metric
from metricflow.engine.time_source import ServerTimeSource
from metricflow.engine.utils import build_semantic_manifest_from_config, build_semantic_manifest_from_dbt_cloud
from metricflow.errors.errors import ExecutionException
Expand Down Expand Up @@ -450,29 +451,35 @@ def explain(self, mf_request: MetricFlowQueryRequest) -> MetricFlowExplainResult
return self._create_execution_plan(mf_request)

def simple_dimensions_for_metrics(self, metric_names: List[str]) -> List[Dimension]: # noqa: D
return [
Dimension(name=dim.qualified_name)
for dim in self._semantic_manifest_lookup.metric_lookup.element_specs_for_metrics(
metric_references=[MetricReference(element_name=mname) for mname in metric_names],
without_any_property=frozenset(
{
LinkableElementProperties.ENTITY,
LinkableElementProperties.DERIVED_TIME_GRANULARITY,
LinkableElementProperties.LOCAL_LINKED,
}
),
)
]
linkable_dimension_tuples = self._semantic_manifest_lookup.metric_lookup.linkable_set_for_metrics(
metric_references=[MetricReference(element_name=mname) for mname in metric_names],
without_any_property=frozenset(
{
LinkableElementProperties.ENTITY,
LinkableElementProperties.DERIVED_TIME_GRANULARITY,
LinkableElementProperties.LOCAL_LINKED,
}
),
).path_key_to_linkable_dimensions.values()

dimensions: List[Dimension] = []
for linkable_dimension_tuple in linkable_dimension_tuples:
for linkable_dimension in linkable_dimension_tuple:
semantic_model = self._semantic_manifest_lookup.semantic_model_lookup.get_by_reference(
linkable_dimension.semantic_model_origin
)
assert semantic_model
dimensions.append(
semantic_model.get_dimension(DimensionReference(element_name=linkable_dimension.element_name))
)
return dimensions

@log_call(module_name=__name__, telemetry_reporter=_telemetry_reporter)
def list_metrics(self) -> List[Metric]: # noqa: D
metric_references = self._semantic_manifest_lookup.metric_lookup.metric_references
metrics = self._semantic_manifest_lookup.metric_lookup.get_metrics(metric_references)
return [
Metric(
name=metric.name,
dimensions=self.simple_dimensions_for_metrics([metric.name]),
)
Metric.from_pydantic(pydantic_metric=metric, dimensions=self.simple_dimensions_for_metrics([metric.name]))
for metric in metrics
]

Expand All @@ -484,7 +491,6 @@ def get_dimension_values( # noqa: D
time_constraint_start: Optional[datetime.datetime] = None,
time_constraint_end: Optional[datetime.datetime] = None,
) -> List[str]:

# Run query
query_result = self.query(
MetricFlowQueryRequest.create_with_random_request_id(
Expand Down
30 changes: 23 additions & 7 deletions metricflow/engine/models.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,35 @@
from __future__ import annotations

from dataclasses import dataclass
from typing import List
from typing import List, Optional

from dbt_semantic_interfaces.objects.metric import MetricType, MetricTypeParams, Metric as SemanticManifestMetric
from dbt_semantic_interfaces.objects.filters.where_filter import WhereFilter
from dbt_semantic_interfaces.objects.metadata import Metadata
from dbt_semantic_interfaces.objects.elements.dimension import Dimension


@dataclass(frozen=True)
class Metric:
"""Dataclass representation of a Metric."""

name: str
description: Optional[str]
type: MetricType
type_params: MetricTypeParams
filter: Optional[WhereFilter]
metadata: Optional[Metadata]
dimensions: List[Dimension]


@dataclass(frozen=True)
class Dimension:
"""Dataclass representation of a Dimension."""

name: str
@classmethod
def from_pydantic(cls, pydantic_metric: SemanticManifestMetric, dimensions: List[Dimension]) -> Metric:
"""Build from pydantic Metric object and list of Dimensions."""
return cls(
name=pydantic_metric.name,
description=pydantic_metric.description,
type=pydantic_metric.type,
type_params=pydantic_metric.type_params,
filter=pydantic_metric.filter,
metadata=pydantic_metric.metadata,
dimensions=dimensions,
)
4 changes: 2 additions & 2 deletions metricflow/model/semantic_manifest_lookup.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from dbt_semantic_interfaces.objects.semantic_manifest import SemanticManifest
from metricflow.model.semantics.semantic_model_lookup import SemanticModelLookup
from metricflow.model.semantics.metric_lookup import MetricLookup
from metricflow.protocols.semantics import SemanticModelAccessor, MetricAccessor
from metricflow.protocols.semantics import SemanticModelAccessor


class SemanticManifestLookup:
Expand All @@ -21,5 +21,5 @@ def semantic_model_lookup(self) -> SemanticModelAccessor: # noqa: D
return self._semantic_model_lookup

@property
def metric_lookup(self) -> MetricAccessor: # noqa: D
def metric_lookup(self) -> MetricLookup: # noqa: D
return self._metric_lookup
7 changes: 4 additions & 3 deletions metricflow/test/api/test_metricflow_client.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from metricflow.api.metricflow_client import MetricFlowClient
from metricflow.dataflow.sql_table import SqlTable
from metricflow.engine.models import Dimension, Metric
from metricflow.engine.models import Metric
from dbt_semantic_interfaces.validations.validator_helpers import ModelValidationResults
from dbt_semantic_interfaces.objects.elements.dimension import Dimension
from metricflow.random_id import random_id


Expand Down Expand Up @@ -74,8 +75,8 @@ def test_list_dimensions(mf_client: MetricFlowClient) -> None: # noqa: D
assert isinstance(dimensions[0], Dimension)

dimensions = mf_client.list_dimensions(["bookings", "revenue"])
assert len(dimensions) == 1
assert dimensions[0].name == "ds"
assert len(dimensions) == 2
assert [dim.name for dim in dimensions] == ["ds", "ds"]


def test_get_dimension_values(mf_client: MetricFlowClient) -> None: # noqa: D
Expand Down

0 comments on commit dadd45f

Please sign in to comment.