From 11787e36c9a8ddb0114e3cabe577aafe532510e4 Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Wed, 24 Apr 2024 15:10:37 -0700 Subject: [PATCH] Add interface for `SavedQueryDependencyResolver`. --- .../metricflow_semantics/api/__init__.py | 0 .../metricflow_semantics/api/v0_1/__init__.py | 0 .../v0_1/saved_query_dependency_resolver.py | 46 +++++++++++++++++++ .../query/saved_query_dependency_resolver.py | 0 .../api/__init__.py | 0 .../api/v0_1/__init__.py | 0 .../test_saved_query_dependency_resolver.py | 35 ++++++++++++++ 7 files changed, 81 insertions(+) create mode 100644 metricflow-semantics/metricflow_semantics/api/__init__.py create mode 100644 metricflow-semantics/metricflow_semantics/api/v0_1/__init__.py create mode 100644 metricflow-semantics/metricflow_semantics/api/v0_1/saved_query_dependency_resolver.py create mode 100644 metricflow-semantics/metricflow_semantics/query/saved_query_dependency_resolver.py create mode 100644 metricflow-semantics/tests_metricflow_semantics/api/__init__.py create mode 100644 metricflow-semantics/tests_metricflow_semantics/api/v0_1/__init__.py create mode 100644 metricflow-semantics/tests_metricflow_semantics/api/v0_1/test_saved_query_dependency_resolver.py diff --git a/metricflow-semantics/metricflow_semantics/api/__init__.py b/metricflow-semantics/metricflow_semantics/api/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/metricflow-semantics/metricflow_semantics/api/v0_1/__init__.py b/metricflow-semantics/metricflow_semantics/api/v0_1/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/metricflow-semantics/metricflow_semantics/api/v0_1/saved_query_dependency_resolver.py b/metricflow-semantics/metricflow_semantics/api/v0_1/saved_query_dependency_resolver.py new file mode 100644 index 0000000000..37190bd1c5 --- /dev/null +++ b/metricflow-semantics/metricflow_semantics/api/v0_1/saved_query_dependency_resolver.py @@ -0,0 +1,46 @@ +from __future__ import annotations + +from dataclasses import dataclass +from typing import Optional, Tuple + +from dbt_semantic_interfaces.protocols import SemanticManifest +from dbt_semantic_interfaces.references import ( + SemanticModelReference, +) + + +@dataclass(frozen=True) +class SavedQueryDependencySet: + """The dependencies of a saved query. + + The primary use case is to handle creation of the cache item associated with the saved query. The dependencies + listed in this class must be up-to-date before the cache associated with the saved query can be created. Otherwise, + running the export / creating the cache may create a cache item that is out-of-date / unusable. + """ + + # A human-readable description for logging purposes. + description: Optional[str] + # The semantic models that the saved query depends on. + semantic_model_references: Tuple[SemanticModelReference, ...] + + +class SavedQueryDependencyResolver: + """Resolves the dependencies of a saved query. Also see `SavedQueryDependencySet`.""" + + def __init__(self, semantic_manifest: SemanticManifest) -> None: # noqa: D107 + self._semantic_manifest = semantic_manifest + + def resolve_dependencies(self, saved_query_name: str) -> SavedQueryDependencySet: + """Return the dependencies of the given saved query in the manifest.""" + return SavedQueryDependencySet( + description=( + f"Dependencies for saved query {repr(saved_query_name)} include all semantic " + f"models as a temporary result until the complete implementation is in place." + ), + semantic_model_references=tuple( + sorted( + (semantic_model.reference for semantic_model in self._semantic_manifest.semantic_models), + key=lambda reference: reference.semantic_model_name, + ) + ), + ) diff --git a/metricflow-semantics/metricflow_semantics/query/saved_query_dependency_resolver.py b/metricflow-semantics/metricflow_semantics/query/saved_query_dependency_resolver.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/metricflow-semantics/tests_metricflow_semantics/api/__init__.py b/metricflow-semantics/tests_metricflow_semantics/api/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/metricflow-semantics/tests_metricflow_semantics/api/v0_1/__init__.py b/metricflow-semantics/tests_metricflow_semantics/api/v0_1/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/metricflow-semantics/tests_metricflow_semantics/api/v0_1/test_saved_query_dependency_resolver.py b/metricflow-semantics/tests_metricflow_semantics/api/v0_1/test_saved_query_dependency_resolver.py new file mode 100644 index 0000000000..168f677123 --- /dev/null +++ b/metricflow-semantics/tests_metricflow_semantics/api/v0_1/test_saved_query_dependency_resolver.py @@ -0,0 +1,35 @@ +from __future__ import annotations + +import pytest +from dbt_semantic_interfaces.implementations.semantic_manifest import ( + PydanticSemanticManifest, +) +from dbt_semantic_interfaces.references import ( + SemanticModelReference, +) +from metricflow_semantics.api.v0_1.saved_query_dependency_resolver import SavedQueryDependencyResolver + + +@pytest.fixture(scope="session") +def resolver( # noqa: D103 + simple_semantic_manifest: PydanticSemanticManifest, +) -> SavedQueryDependencyResolver: + return SavedQueryDependencyResolver(simple_semantic_manifest) + + +def test_saved_query_dependency_resolver(resolver: SavedQueryDependencyResolver) -> None: # noqa: D103 + dependency_set = resolver.resolve_dependencies("p0_booking") + assert tuple(dependency_set.semantic_model_references) == ( + SemanticModelReference(semantic_model_name="accounts_source"), + SemanticModelReference(semantic_model_name="bookings_source"), + SemanticModelReference(semantic_model_name='buys_source'), + SemanticModelReference(semantic_model_name="companies"), + SemanticModelReference(semantic_model_name="id_verifications"), + SemanticModelReference(semantic_model_name="listings_latest"), + SemanticModelReference(semantic_model_name="lux_listing_mapping"), + SemanticModelReference(semantic_model_name="revenue"), + SemanticModelReference(semantic_model_name="users_ds_source"), + SemanticModelReference(semantic_model_name="users_latest"), + SemanticModelReference(semantic_model_name='views_source'), + SemanticModelReference(semantic_model_name='visits_source'), + )